zoukankan      html  css  js  c++  java
  • Runtime Only和Runtime + Compiler

    如果你需要在客户端编译模板 (比如传入一个字符串给 template 选项,或挂载到一个元素上并以其 DOM 内部的 HTML 作为模板),就将需要加上编译器,即完整版

    当使用 vue-loader 或 vueify 的时候,*.vue 文件内部的模板会在构建时预编译成 JavaScript。你在最终打好的包里实际上是不需要编译器的,所以只用运行时版本即可— 官方文档

    客户端编译模板

     1   <script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.js"></script>
     2 
     3   <div id="app"></div>
     4 
     5   <script>
     6     new Vue({
     7       el: '#app',
     8       data: {
     9         message: 'Hello Vue!'
    10       },
    11       template: '<div>{{ message }}</div>'
    12     })
    13   </script>

    这种用法就需要在客户端(即浏览器中)编译模板,模版的内容是 <div>{{ message }}</div> ,模版的数据是 message: 'Hello Vue!' 。

    因此,如果使用 script 引入只有运行时版本的vue.js vue.runtime.js ,就会报错:

    vue.runtime.js:593 [Vue warn]: You are using the runtime-only build of Vue where the template compiler is not available. Either pre-compile the templates into render functions, or use the compiler-included build.

    使用渲染函数

     1   <script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.runtime.js"></script>
     2 
     3   <div id="app"></div>
     4 
     5   <script>
     6     new Vue({
     7       el: '#app',
     8       data: {
     9         message: 'Hello Vue!'
    10       },
    11       render (createElement) {
    12         return createElement('div', this.message)
    13       }
    14     })
    15   </script>

    这种用法就是直接给出渲染函数来进行内容输出(具体 createElement 语法后面再讲),这种情况下不需要进行客户端渲染,直接引用运行时版本的vue.js即可,并不会报错。

    预编译模板

    简单的页面结构我们可以直接通过 createElement 函数来手动编写,但是对于复杂的页面结构呢?vue提供了 Vue.compile 函数用于将模版编译成 render 函数,示例如下:

    1 <script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.js"></script>
    2 
    3   <script>
    4     const result = Vue.compile('<div>{{ message }}</div>');
    5     console.log(result.render);
    6   </script>

    注意:只有 Runtime + Compiler 版本的vuejs才有 Vue.compile 函数,运行时版本的vue.js是没有这个函数的,所以这里也就是所谓的预编译。

    输出的结果如下:

    1 ƒ anonymous(
    2 ) {
    3 with(this){return _c('div',[_v(_s(message))])}
    4 }

    我们用预编译生成的render函数替代上一章的 render 函数:

     1  <script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.runtime.js"></script>
     2 
     3   <div id="app"></div>
     4 
     5   <script>
     6     new Vue({
     7       el: '#app',
     8       data: {
     9         message: 'Hello Vue!'
    10       },
    11       render (createElement) {
    12         with(this){return _c('div',[_v(_s(message))])}
    13       }
    14     })
    15   </script>

    可以看到这种“开发时预编译,上线使用运行时”的方式既满足了开发需要又减少了线上文件的大小。

    注:通过打印,可以看到 createElement 以及 this._c ,  this._v  和  this._s 的值:

    1  render (createElement) {
    2         console.log(createElement, this._c, this._v, this._s)
    3         with(this){return _c('div',[_v(_s(message))])}
    4       }
    5 ƒ (a, b, c, d) { return createElement(vm, a, b, c, d, true); }
    6 ƒ (a, b, c, d) { return createElement(vm, a, b, c, d, false); }
    7 ƒ createTextVNode (val) {...}
    8 ƒ toString (val) {...}

    所以可以看出,我们最开始手写的渲染函数 return createElement('div', this.message) 只是上面预编译生成的一个简版。

    基于 HTML 的模板语法

    除了上面几种基于js代码的形式来创建模版,vuejs也支持基于 HTML 的模板语法,用法如下:

     1   <script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.js"></script>
     2 </head>
     3 <body>
     4   <div id="app"><div>{{ message }}</div></div>
     5 
     6   <script>
     7     new Vue({
     8       el: '#app',
     9       data: {
    10         message: 'Hello Vue!'
    11       }
    12     })
    13   </script>

    注意,这种写法也必须要使用 Runtime + Compiler 版本的vuejs才可以允许,因为其实质上还是在客户端进行模版编译,因为上面的写法实质上等同于下面的写法:

     1   <div id="app"></div>
     2   <template id="tpl">
     3     <div>{{ message }}</div>
     4   </template>
     5 
     6   <script>
     7     new Vue({
     8       el: '#app',
     9       data: {
    10         message: 'Hello Vue!'
    11       },
    12       template: '#tpl'
    13     })
    14   </script>

    vuejs源码中的 template 解析

    在vuejs源码中,关于获取 template 的关键代码如下:

     1    var template = options.template;
     2     if (template) {
     3       if (typeof template === 'string') {
     4         if (template.charAt(0) === '#') {
     5           template = idToTemplate(template);
     6         }
     7       } else if (template.nodeType) {
     8         template = template.innerHTML;
     9       } else {
    10         {
    11           warn('invalid template option:' + template, this);
    12         }
    13         return this
    14       }
    15     } else if (el) {
    16       template = getOuterHTML(el);
    17     }

    逻辑主要步骤如下:

    • 先判断是否有 template 属性
    • 如果没有,则直接通过 el 中的 html 代码作为模版
    • 如果有,判断是否是字符串(非字符串的形式暂不讨论)
    • 是字符串的情况下,是否以#字符开头
    • 如果是,则获取对应id的 innerHTML 作为模版
    • 如果不是以#字符开头,则直接作为作为模版

    总结

    一句话来讲就是:如果有 render 函数就可以使用运行时版本的vuejs,否则必须使用 Runtime + Compiler 版本的vuejs。

    原文地址

  • 相关阅读:
    201871010114李岩松《面向对象程序设计(java)》第十二周学习总结
    201871010114李岩松《面向对象程序设计(java)》第十六周学习总结
    201871010114李岩松《面向对象程序设计(java)》第八周学习总结
    201871010114李岩松《面向对象程序设计(java)》第七周学习总结
    201871010114李岩松《面向对象程序设计(java)》第六、七周学习总结
    一分钟秒解数据库三大范式
    反射机制获取类的方法
    hashMap和hashTable的区别
    ssm+maven 框架整合
    Hibernate从零开始的反向工程
  • 原文地址:https://www.cnblogs.com/joyco773/p/11657503.html
Copyright © 2011-2022 走看看