Vue两个版本、单文件组件

130 阅读3分钟

Vue有两个不同的版本,分别是Vue完整版vue.js和Vue非完整版vue.runtime.js:

1. Vue完整版

  • 文件名:vue.js

  • 优点:含有编译器compiler,可以将视图直接写入html

  • 缺点:文件体积较大,用户要下载很大的文件,体检较差

2. Vue非完整版

  • 文件名:vue.runtime.js

  • 优点:文件体积小,用户加载很快,体验较好

  • 缺点:没有编译器,无法将html编译成视图,开发时需要将视图写到render函数里,对开发者来说不直观

3. Vue两个版本的详细介绍:

3.1 完整版Vue实例创建过程(从HTML得到视图):

  • 完整版的实现思路为:通过编译器compiler把含有占位符'html {{n}}'或条件循环'v-if','v-for'@click='add'转化为'html 0'真实的DOM节点,这样的话,在执行this.n += 1的时候,vue就知道要改的是n,不用再去编译,直接就改DOM节点,分析得到'html 1'

  • 支持在index.html中写标签,或在main.js中写template,都可以用得到视图:

template: `
<div>Hello</div>
`
  • 引入vue.js或vue.min.js的方法有两种:
  1. boot cdn 复制链接 放在index.html的script标签里
  2. import 引入import Vue from 'vue'import App from './App.vue'
console.log(window.Vue)
Vue.config.productionTip = false

new Vue({
    el:'#app',
    template:`      //一种方法是直接在main.js中写
        <div>{{n}}</div>
    `
    data:{
        n:0
    }
})
<!DOCTYPE html>
<html lang="">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <link rel="icon" href="<%= BASE_URL %>favicon.ico">
    <title><%= htmlWebpackPlugin.options.title %></title>
  </head>
  <body>
    <noscript>
      <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
    </noscript>
    <div id="app">
      {{n}}             //另一种方法是在index.html中写标签
    </div>
    <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.7.4/vue.js"></script>    //引入Vue.js 
    <!-- built files will be auto injected -->
  </body>
</html>

[Vue warn]:You are using the runtime-only build of Vue where the template compiler is not available.


3.2 非完整版Vue实例创建过程():

  • 不支持在main.js里面写template,视图写在render函数里创建标签,接收到vue传给render的参数h,实质就是createElement,用h可以创建:

非完整版Vue原理,代码演进过程:

  1. 第一步
new Vue({
  el:'#app',    //引用的是页面index.html中<div id="app"></div>的'app'
  render(creatElement){
    const h =creatElement
    return creatElement('div', [this.n, creatElement('button'),'+1'])
  },
  data:{
    n:0
  }
})
  1. 第二步,用h代替creatElement
new Vue({
  el:'#app',
  render(h){
    return h('div', [this.n, h('button'), '+1'])
  }
})
  1. 第三步,添加button监听事件
new Vue({
  el:'#app',
  render(h){
    return h('div', [this.n, h('button',{on:{click:this.add}}),'+1'])
  }
})
  • 非完整版的Vue本身没有编译器compiler,而是结合webpack的vue-loader把<div>{{n}} <botton>转化为h('div',this.n)
console.log(window.Vue)
Vue.config.productionTip = false

new Vue({
  el:'#app',
  render(h){
    return h("div",[this.n, h('button',{on:{click:this.add}},"+1")])
  },
  data:{
    n:0
  },
  methods:{
    add(){
      this.n += 1;
    }
  }
});

4. Vue单文件组件:

  • 非完整版的Vue本身没有编译器compiler,而是结合webpackvue-loader<div>{{n}} <botton>转化为h('div',this.n),也可以说通过vue-loader可以把demo.vue变成一个对象
  • Vue单文件组件中的index.html,存在一个问题:因为div内容是空的,所以会存在用户交互不友好的情况,称为SEO不友好,搜索引擎优化
<template>  //视图
<div class="red">
    {{n}}
    <button @click="add">+1</button>
</div>
</template>

<script>   //视图之外的其他选项
export default{
    data(){
        return {
          n:0
        }
    },
    methods:{
        add(){
          this.n += 1  
        }
    }
};
</script>

<style scoped>   //css样式
.red{
    color:red;
} 
</style>
import Demo from './Demo.vue'  //引入当前目录下的Demo.vue文件
new Vue({
  el:'#app',  
  render(h){
    return h(Demo)
  }, 
});
  • 以上代码通过打log可以得知,通过vue-loader的转化,结果得到的Demo其实就是一个对象:

25.png

render里面就是把Demo.vue的html翻译成如下代码:

render(h){
  h('div')
}

对比就可以知道是做了这样的事:

24.png

23.png