探究Vue源码:mustache模板引擎(10) 解决不能用连续点符号找到多层对象问题,为编译循环结构做铺垫

上文 探究Vue源码:mustache模板引擎(9) 将单层无喜欢结果tokens转为dom字符串 我们简单处理了 token转字符串的业务逻辑
但是 我们只处理了最贱的花括号
接下来 带着大家将井号的也处理一下
我们打开项目 将 www中的index.html代码改回之前的这样

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script src = "/xuni/bundle.js"></script>
    <script>
        let templateStr = `
            <div>
                {
       
       {#students}}
                    <ul>
                        <li>{
       
       { item.name }}</li>
                        {
       
       {#item.list}}
                            <li>{
       
       { . }}</li>
                        {
       
       {/item.list}}
                    </ul>
                {
       
       {/students}}
            </div>
        `;
        let data = {
      
      
            name: "小猫猫",
            age: 2,
            students: [
                {
      
      
                    id: 0,
                    name: "小明",
                    list: [
                        "篮球",
                        "唱",
                        "跳"
                    ]
                },
                {
      
      
                    id: 1,
                    name: "小红",
                    list: [
                        "电子游戏",
                        "计算机编程"
                    ]
                }
            ]
        }
        GrManagData.render(templateStr,data);
    </script>
</body>
</html>

我们来处理一下这个循环嵌套的结构

然后 我们运行项目 会发现 到 井号位置就有问题了 它无法处理
在这里插入图片描述
这里 我们显然 用平行的结构是搞不定的 需要递归
首先 我们可以想一很简单的思路 不带井号 是调用renderTemplate
那么 我们带井号的 不就可以递归去调用这个 renderTemplate 吗?
是不是 思路非常简单

但在写递归之前 我们先要解决一个问题

例如 我们将 www 下的 index.html
改成这样

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script src = "/xuni/bundle.js"></script>
    <script>
        let templateStr = `
            <div>
                我超喜欢我家的{
       
       {name}},我家{
       
       {name}}也超喜欢我,它今年{
       
       {a.b.c}}岁啦
            </div>
        `;
        let data = {
      
      
            name: "小猫猫",
            a: {
      
      
                b: {
      
      
                    c: 2
                }
            }
        }
        GrManagData.render(templateStr,data);
    </script>
</body>
</html>

这样 我们在语句中 用了 data中的 a对象下的 b 对象下的c对象
然后我们运行项目
在这里插入图片描述
这里 直接成了undefined 因为 他无法识别 点这个语法 就是 你用对象名点字段名 我们写的这个
在这里插入图片描述
它没办法识别

其实 我们可以打印一下 看看这里 a.b.c 它生成的name是什么样的
在这里插入图片描述
我们这里 用console.log 看看里面到底是个什么
在这里插入图片描述

没错 这里 拿到的确实是 a.b.c
但你现在的语法相当于

data["a.b.c"]

这里 我们 js这个括号 只支持找直接下标 他是不认识我们这个点的语法的 他不会帮你往下找
所以 这里就有问题了
真的这个问题
我们在src下再创建一个 lookup.js
先放上这样一段代码

/*
    可以在data中,用连续点符号的形式找到对应键值
*/
export default function lookup(data,keyName) {
    
    

}

先暴露一个函数出去
这个函数 需要两个参数 第一个是总的data 你要找 肯定要给总的数据嘛 对不对?
然后 第二参数 是字段名 例如 a.b.c
写完这个函数 就可以取到 对象中的对象中的对象了

我们将 lookup 内容改成这样

/*
    可以在data中,用连续点符号的形式找到对应键值
*/
export default function lookup(data,keyName) {
    
    
    
    //判断keyName字符串中是否有  .  符号
    if(keyName.indexOf(".") > 0) {
    
    
        //将keyName按点拆分成数组
        var names = keyName.split('.');
        //存一个 指向 data 的临时变量
        let temp = data;

        //循环遍历 用点拆分开的数组names
        for(let i = 0;i < names.length;i++) {
    
    
            //  一层一层寻找对应字段
            temp = temp[names[i]];
        }
        //将得到的结果返回
        return temp;
    }
    //没有  点符号 就直接将data中的keyName字段返回就ok了
    return data[keyName]
}

进来 我们先判断keyName 有没有点符号
如果有 走进来 我们利用字符串拆分的split将他拆开成数组
然后用一个零时变量将data存起来
然后我们循环我们用 点 符号拆开的这个数组 那么 内容自然是 [“a”,“b”,“c”]
那么 循环一次内容 就是 a b c
那么 第一次进来 temp 的值指向的是 data 第一个下标 是 a 就是找到 data下的a
第二次 temp 目前是data下的a 然后 第二个下标是 b 就是 在a下寻找b
第三次 就成立 b下寻找c
非常简单 最后处理好将temp返回回去

如果没有点符号 没有走进if 那就更简单 直接 找data下的keyName值

然后 我们将
src下的 renderTemplate.js 代码改一下

这里 我们引入并使用一下lookup
在这里插入图片描述
运行项目
在这里插入图片描述
可以看到 这些数据就读到啦
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_45966674/article/details/132104132