1- 模板

作者: 我爱阿桑 | 来源:发表于2020-07-13 17:17 被阅读0次
    1 .拿到模板
      let tmpNode= document.querySelector('#root')
    
    2.拿到数据
     let data = {
          name: '一个新name',
          message: '一个消息'
        };
    
    3.将数据放入模板中

    一般都是使用递归,在真正的 Vue 源码中是 DOM -> 字符串模板 -> VNode -> 真正的 DOM

    // template   DOM元素
    let rkuohao = /\{\{(.+?)\}\}/g
     function  complier( template ,data){
         let childNodes = template.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(rkouhao,function( - ,g){  // replace 使用正则匹配一次 函数就会被调用一次                                                                    
                                                      // 函数的 第 0 个参数 表示匹配到的内容
                                                       // 函数的 第 n 个参数 表示正则中的 第 n 组
    
               let key=g.trim()  // 写在双花括号里面的 东西(相当于key)
               let value = data[key]
               return value
           })
              // 注意:  txt 现在和 DOM 元素是没有关系
              childNodes[ i ].nodeValue = txt;
        }else if ( type === 1 ) {
              // 元素, 考虑它有没有子元素, 是否需要将其子元素进行 判断是否要插值
              compiler( childNodes[ i ], data );
            }
     }
    }
    // 利用 模板生成一个 需要被渲染的 HTML 标签 ( 准 真正在页面中显示的 标签 )
        let generateNode = tmpNode.cloneNode( true ); // 注意这里是 DOM 元素, 可以这么用
    
     compiler( generateNode, data ); // 将{{}} 替换掉
    
    
    4..将 渲染好的 HTML 加到页面中
        root.parentNode.replaceChild( generateNode, root );
    
    5 全部代码
     <!--
     * @Author: MJC
     * @Date: 2020-07-13 16:24:09
     * @LastEditTime: 2020-07-13 16:36:44
    --> 
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <meta http-equiv="X-UA-Compatible" content="ie=edge">
      <title>Document</title>
    </head>
    <body>
      <!-- 写模板 -->
      <div id="root">
        <div>
          <p>{{name}}-{{message}}</p>
        </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  拿到数据 ( data )
        let data = {
          name: '一个新name'
          , message: '一个消息'
        };
    
        // 3. 将数据放到模板中( ??? )
        //  一般都是使用 递归
        // 在现在这个案例中 template 是 DOM 元素,
        // 在真正的 Vue 源码中是 DOM -> 字符串模板 -> VNode -> 真正的 DOM
        function compiler( template, data ) {
          let childNodes = template.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 ( _, g ) { // replace 使用正则匹配一次 函数就会被调用一次
                                                        // 函数的 第 0 个参数 表示匹配到的内容
                                                        // 函数的 第 n 个参数 表示正则中的 第 n 组
                let key = g.trim(); // 写在双花括号里面的 东西
                let value = data[ key ];
    
                // 将 {{ xxxx }} 用这个 值替换
                return value;
              } );
    
    
              // 注意:  txt 现在和 DOM 元素是没有关系
              childNodes[ i ].nodeValue = txt;
            } 
            else if ( type === 1 ) {
              // 元素, 考虑它有没有子元素, 是否需要将其子元素进行 判断是否要插值
              compiler( childNodes[ i ], data );
            }
          }
        }
    
        // 利用 模板生成一个 需要被渲染的 HTML 标签 ( 准 真正在页面中显示的 标签 )
        let generateNode = tmpNode.cloneNode( true ); // 注意这里是 DOM 元素, 可以这么用
    
        console.log( tmpNode );
        compiler( generateNode, data ); // 将 坑 替换掉
        console.log( generateNode );
    
        // 我们此时是没有生成 新的 template, 所以这里看到的 是直接在页面中就更新的数据, 因为 DOM 是引用类型
        // 这样做 模板就没有了
    
        // 4. 将 渲染好的 HTML 加到页面中
        root.parentNode.replaceChild( generateNode, root );
    
        // 上面的思路有很大的问题:
        // 1. Vue 使用的 虚拟 DOM
        // 2. 只考虑了 单属性 ( {{ name }} ), 而 Vue 中大量的使用层级 ( {{ child.name.firstName }} )
        // 3. 代码没有整合
      </script>
    </body>
    </html>
    

    相关文章

      网友评论

          本文标题:1- 模板

          本文链接:https://www.haomeiwen.com/subject/jeracktx.html