首页 > 其他 > 详细

vue源码解析之,插值替换

时间:2020-09-06 14:42:55      阅读:64      评论:0      收藏:0      [点我收藏+]

通过一个小例子 看一下,vue做了些什么?

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="../node_modules/vue/dist/vue.js"></script>
</head>
<body>
    <div id="root">
        <p>{{name}}</p>
        <p>{{message}}</p>
    </div>
    <div id="a"></div>

    <script>
        console.log(root);
        let app = new Vue({
            el:"#root",
            data:{
                name:"哈哈",
                message:"是一个男人"
            }
        })
        console.log(root);
    </script>
</body>
</html>

技术分享图片

 

 下面我们模仿一下vue去实现一下,插值替换的步骤:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="../node_modules/vue/dist/vue.js"></script>
</head>
<body>
    <div id="root">
        <div>
            <div>
                <p>{{name}}--{{message}}</p>
            </div>
        </div>
        <p>{{name}}</p>
        <p>{{message}}</p>
    </div>

    <script>
        let rkuohao = /\{\{(.+?)\}\}/g;//匹配双括号的正则  .+?  两面加小括号 目的是 通过正则可以把它取出来
        /**
         * 步骤拆解
         * 1、拿到模板
         * 2、拿到数据data
         * 3、将数据与模板结合,得到的是html元素(DOM元素)
         * 4、放到页面当中
        */
        // 第1步
        let tmpNode = document.querySelector("#root");
        // 第2步
        let data = {
            name:"姓名",
            message:"是一个男人"
        }
        // 第3步
        // 递归的方法去找到需要替换的节点
        // 在现在的案例中 template 是dom元素,
        // 在真正的vue源码中是DOM-》字符串-》虚拟DOM(vnode)-》真正的DOM
        function compiler( template,data ){
            let childNodes = template.childNodes;//取出子元素
            console.log(childNodes);
            for(let i=0;i<childNodes.length;i++){
                let type = childNodes[i].nodeType;//判断是否为文本节点 1:元素 3:文本节点
                if(type === 3){
                    // 是文本节点
                    // 可以判断 里面是有有{{}}的插值
                    let txt = childNodes[i].nodeValue;//该属性只有文本节点才有意义
                    // 有没有{{}}
                    txt = txt.replace(rkuohao,function(_,g1){
                        let key = g1.trim();
                        let value = data[key];
                        // 将{{ xxx }} 替换成value
                        return value;
                    })
                    // 注意 现在这个txt和DOM元素是没有关系的
                    childNodes[i].nodeValue = txt;
                }else if(type === 1){
                    // 是元素,需要判断是都有子元素,判断是否要插值
                    compiler(childNodes[i],data);//递归
                }
            }
        }
        console.log(tmpNode);//此时 插值还未被替换
        let generatorNode = tmpNode.cloneNode(true);//拷贝一份模板   这里是DOM元素可以通过这样的方法 拷贝
        compiler( generatorNode,data );//调用一下
        console.log(generatorNode);//此时 模板中的 插值就被替换成真正的值了
        // 我们此时是没有生成新的template,所以这里看到的,是直接在页面中就更新了数据,因为DOM是引用类型
        // 这样做模板就没有了
        // 第4步
        root.parentNode.replaceChild(generatorNode,root);//替换子元素   用新的元素去替换旧的元素

        // 上面的案例是一个极简的 例子 存在很大的问题
        // 1、vue使用的是虚拟DOM
        // 2、上面只考虑到了单属性 {{name}}  在真正的vue中会有很多这样的写法  {{child.name.firstName}}
        // 3、代码没有整合  vue是用构造函数的形式整合的
    </script>
</body>
</html>

 

技术分享图片

 

 

 

 

 

vue源码解析之,插值替换

原文:https://www.cnblogs.com/fqh123/p/13621466.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!