Vue实例中的template讲解(1)

宗政博
2023-12-01

<body>

    <div id="el">
    </div>
    <script type="text/x-template" id="demo-template">
      <div>
        <p>Selected: {{ selected }}</p>
        <select2 :options="options" v-model="selected">
          <option disabled value="0">Select one</option>
        </select2>
      </div>
    </script>

  <!--前后不分离  可以这样做   -->
    <script type="text/x-template" id="select2-template">
      <select>
        <slot></slot>
      </select>
    </script>

    <script>
    Vue.component('select2', {
      props: ['options', 'value'],
      template: '#select2-template',
      mounted: function () {},
      watch: {},
      destroyed: function () {}
    })

    var vm = new Vue({
      el: '#el',
      template: '#demo-template',
      data: {
        selected: 0,
      }
    })
    </script>
  </body>
</html>

先说下上面的:type="text/x-template"

1. script不写type默认是text/javascript,如果写了不被识别的type将被浏览器忽略。text/x-template或text/html可能只是为了语义而已~而且在有些编辑器还具有语法高亮的显示,type="text/diy"随便写也可以

2. script的type为各种template的时候,可能就是使用了模板引擎。

//别忘了引包
<body>
  <div id="app-1">
     {{msg}}
  </div>
  ================
  <div id="app-2">
     {{msg}}
  </div>
  =================
  <div id="app-3">
     {{msg}}
  </div>

  <script>
    //在vue.js中,可以使用template给元素添加模板,但是元素中只能有一个根元素,不能出现两个或两个以上的根同级元素。还可以在模板中绑定数据、表达式等。下面利用实例说明如何添加模板
    // 创建 Vue 实例,得到 ViewModel
    new Vue({
      el: '#app-1',
      data: {
         msg:'这是通过el属性获取挂载元素的outerHTML方式渲染' 
      }
    });
    //结论:如果vue实例中有template属性,会将该属性值进行编译,将编译后的虚拟dom直接替换掉vue实例绑定的元素(即el绑定的那个元素);
    //注意:template属性中的dom结构只能有一个根元素,如果有多个根元素需要使用v-if、v-else、v-else-if设置成只显示其中一个根元素;
    new Vue({
      el: '#app-2',
      data: {
         msg:'这是通过el属性获取挂载元素的outerHTML方式渲染' 
      },
      template:'<div>这是template属性模板渲染</div>'
    });
    //render 
    new Vue({
      el: '#app-3',
      data: {
         msg:'这是通过el属性获取挂载元素的outerHTML方式渲染' 
      },
      template:'<div>这是template属性模板渲染</div>',
      render: function(createElement){
        return createElement('div', 
        // 参数2、这里相当于给标签加属性 例如:<div style='color:red,font-size: 14px'></div>
        {
       //给div绑定样式
       style:{
         width:'300px',
                height:'400px',
                color:'pink'
       }, 
      //给div绑定点击事件  
            on: {
                click: () => {
                    console.log('点击事件')
                }
            }
        },
        // 参数3、参数中渲染的标签的子元素数组(可选) 
        // [
        //    // 文本节点直接写就可以
        //    'text'
        // ]
        '这是render属性方式渲染。'
        );
      }
    });
  </script>
</body>

 render > template > el  属性优先性:
1.当Vue选项对象中有render渲染函数时,Vue构造函数将直接使用渲染函数渲染DOM树。

2.当选项对象中没有render渲染函数时:Vue构造函数首先通过将template模板编译生成渲染函数,然后再渲染DOM树。

3.而当Vue选项对象中既没有render渲染函数,也没有template模板时,会通过el属性获取挂载元素的outerHTML来作为模板,并编译生成渲染函数。


换言之,在进行DOM树的渲染时,render渲染函数的优先级最高,template次之且需编译成渲染函数,而挂载点el属性对应的元素若存在,则在前两者均不存在时,其outerHTML才会用于编译与渲染。
 

Vue模版编译原理

vue中的模板template无法被浏览器解析并渲染,因为这不属于浏览器的标准,不是正确的HTML语法,所有需要将template转化成一个JavaScript函数,这样浏览器就可以执行这一个函数并渲染出对应的HTML元素,就可以让视图跑起来了,这一个转化的过程,就成为模板编译。模板编译又分三个阶段,解析parse,优化optimize,生成generate,最终生成可执行函数render。

  • 1.解析阶段:使用大量的正则表达式对template字符串进行解析,将标签、指令、属性等转化为抽象语法树AST。
  • 2.优化阶段:遍历AST,找到其中的一些静态节点并进行标记,方便在页面重渲染的时候进行diff比较时,直接跳过这一些静态节点,优化runtime的性能。
  • 3.生成阶段:将最终的AST转化为render函数字符串。

 类似资料: