美文网首页vuejs
Vue - 组件和Vue.extend

Vue - 组件和Vue.extend

作者: 人话博客 | 来源:发表于2019-04-17 12:06 被阅读0次

    在初学 Vue 的时候,都是利用 cdn 的方式在一个页面中导入 vue.js 的库文件.

    <script src='https://cdn.jsdelivr.net/npm/vue/dist/vue.js'></script>
    
     var app = new Vue({
        el: '#app',
        data: {
          title: '我的第一个vue组件'
        },
        methods: {},
        filters: {},
        directives: {},
        components: {},
      })
    

    接着,肯定就学到了组件开发.

    当然,也是在单页面中.

    API文档告诉我们

    • Vue.component 用来注册全局组件.
    • 在某个组件内部使用 components:{} 来注册局部组件.
    <global-vue-component></global-vue-component>
    
    Vue.component('GlobalVueComponent',{
        template:`<div>{{title}}</div>`,
        data () {
          return {
            title: '我是使用 Vue.component 注册的全局组件'
          }
        }
    })
    
    <scope-vue-component></scope-vue-component>
    
    let ScopeVueComponent = {
        template:`<div>{{title}}</div>`,
        data () {
          return {
            title: '我是使用 components 使用的局部组件'
          }
        }
      }
      
       var app = new Vue({
        el: '#app',
        data: {
          title: '我的第一个vue组件'
        },
        components: {
          ScopeVueComponent
        }
      })
    
    image.png

    在后来,学到了使用 vue-cli 搭配 .vue 模板的方式开发组件.

    <template>
      <div>
        {{ title }}
      </div>
    </template>
    
    <script>
    // 这是组件的数据和行为内容 vm & model
    export default { 
      name:'vue-template-mode-component',
      data () {
        return {
          title: '这是.vue组件的模板开发模式'
        }
      }
    }
    </script>
    

    好了,三种组件创建的方式说完了,且在各自的环境里都能够正常的运作.


    Vue.extend 方法.

    Vue 开发中,所有的组件本质上都是由一个继承自 Vue 的构造函数创建的.

    比如在注册局部组件时.

    const TodoListComp = {
        template:`<div><h1>{{ title }}</h1></div>`,
        data () {
          return {
            title:'用 object 搭配 components 的方式去创建局部组件'
          }
        }
    }
    
    
    const app = new Vue({
        el:'#app',
        components: {
            TodoListComp,        
        }
    })
    
    
    <todo-list-comp></todo-list-comp>
    
    

    从视觉上,我们看到 TodoListComp 只是一个普通的 Object 对象.

    直接赋值给了其他组件的components属性里.

    然后,这个组件就成为了一个局部组件,并可以在注册了当前组件的内部去使用了.

    那它在内部做了什么,导致这个普通的对象最后可以被当成是一个正常的组件来使用呢?

    比如,普通对象上都没有$el 之类的属性.丢给components之后,就啥都有了.

    其实,在Vue内部,所有的组件都是通过 Vue.extend() 函数来构建的.
    这个函数接收一个满足组件定义的object对象(比如,data,watch,computed,methods等).
    最终返回一个构建此组件的构造函数(VueComponent)

    使用Vue.extend(options)会根据传入的options创建一个VueComponent的组件构造函数并返回.

    const TodoList = Vue.extend({
        template:`<div><h1>{{ title }}</h1></div>`,
        data () {
          return {
            title:'Vue.extend 创建的组件构造函数,使用new的方式创建并挂载'
          }
        }
      })
    
      console.log(TodoList)
      
    
    image.png

    既然使用 Vue.extend 会返回一个组件的构造函数.

    那么我们就可以使用 new 这个返回的构造函数

    并手动的 mount 并替换某个 dom 节点(就和 new App() 一样)

    <!--用TodoListComp构造出来的组件实例对象替换这个节点-->
    <div id="todolistcomp"></div>
    const comp = new TodoList() // 这不不用传options,是因为在 Vue.extend(options) 的时候已经传递了.
    comp.$mount('#todolistcomp') // 既然是创建出来的组件,继承自 Vue.prototype 所以就会有$mount 函数.
    
    image.png

    .vue 模板文件开发.

    前面,我么已经知道了,所有的vue组件,不管是全局的还是局部的.

    都是利用 Vue.extend 方法构建并返回出一个继承自 Vue 的组件构造函数.

    这个函数接受一个满足了 Vue 组件属性项的普通的 Object 对象.

    在.vue模板文件开发中,也不例外.

    我们可以看看,在书写.vue模板文件时,我们到底在写什么?

    <template>
      <div>
        <h2>{{title}}</h2>  
        <p v-html="content"></p>
      </div>
    </template>
    <script>
    export default {
      name:'about-vue-template',
      data() {
        return {
          title:"我是.vue模板创建的组件",
          content:"使用.vue模板文件创建的组件本质上是vue-loader将这个文件编译成一个普通的不能在普通的obj对象.[template]xxxxx[/template]就被定义成对象的<b color='red'>.template属性.</b> 其他属性同理<ul><li>data</li><li>watch</li><li>methods</li><li>computed</li></ul>"
        }
      },
      directives:{},
      computed: {},
      methods: {},
      filters: {}
    }
    

    我们写的是一个 .vue 文件.

    并按照 <template></template> <script></script> (这里不关注<style></style>节点) 的格式编写 .vue 文件.

    把它整合起来来看.

    • template 就有点像我们在定普通组件options对象时的 template属性.
    • data 就是options对象的data
    • methods 就是options对象的methods
    • computed 就是options对象的computed
    • filters 就是 options 对象的 filters

    等价于

    const normalObjectOptions = {
        template: 
        data:
        methods:
        computed:
        filters:
    }
    

    好了,继续回到 .vue 模板开发文件中.

    在另外一个组件中,使用此组件时,我们会 import xxx from xxx.vue 并搭配 components:{ xxxx }

    .vue 会被 webpack 中配置的 vue-loader 处理.这是我们已知的.

    结合上述的判断,vue-loader 仅仅只是把 .vue 文件编译成了一个 vue.extend(options) 创建组件所需要的 options 普通对象而已.

    // 导入一个.vue文件的模板
    import AboutVueComp from './components/about' 
    // 查看实际导出的数据
    console.log('AboutVueComp',AboutVueComp)
    
    image.png

    既然 vue-loader 仅仅,只是把 .vue 模板文件编译成了一个 options 普通对象.

    那么我们可以手动的使用 Vue.extends(options) 来获得这个组件对象的构造函数.

    const AboutVueCompConstructor = Vue.extend(AboutVueComp)
    console.log('AboutVueCompConstructor',AboutVueCompConstructor)
    
    image.png

    拿到此组件的构造函数,我们就可以在 组件 mounted 的时候,通过 new 的方式,挂在到 html 上了. (而无需去注册到 components,成为一个局部组件.直接把它当成一个自己熟悉的不能在熟悉的构造函数调用即可.)

    // 导入一个.vue文件的模板
    import AboutVueComp from './components/about' 
    // 查看实际导出的数据
    console.log('AboutVueComp',AboutVueComp) // object 
    const AboutVueCompConstructor = Vue.extend(AboutVueComp)
    console.log('AboutVueCompConstructor',AboutVueCompConstructor)
    
    
     mounted() {
        new AboutVueCompConstructor().$mount('#aboutvuecompcontstrutor')
      },  
    
    image.png

    使用.js文件的方式使用.vue组件.

    既然我们已经知道:

    • .vue模板文件本质上会被vue-loader 编译成了一个普通的不能在普通的 object 对象.
    • 这个对象里包含了 vue 组件需要的一些数据和方法.
    • 然后接着使用 Vue.extend() 接受这个普通的不能在普通的 object 对象.
    • 并返回一个创建此对象的构造函数f VueComponent(options){ this._init(options) }.
    • 最后,我们就可以使用 new 构造函数的方式来创建此组件.

    我们完全可以直接使用 .js 文件的方式来创建 vue 组件,进而省略 .vue & vue-loader 这个执行的步骤.

    import Vue from 'vue'
    
    export default Vue.extend({
      name: 'js-comp-constructor',
      template: `<div @click="hanlderClick">{{title}}</div>`,
      data () {
        return {
          title: "我是通过.js文件创建出来的组件"
        }
      },
      methods: {
        hanlderClick () { 
          console.log('我是js模式组件提供的click方法')
        }
      },
      mounted () { 
        this.$el.style.width = '300px'
        this.$el.style.height = '200px'
        this.$el.style.backgroundColor = 'red'
        this.$el.style.margin ='0 auto'
        this.$el.style.lineHeight = '200px'
        this.$el.style.color = '#fff'
        this.$el.style.textAlign = 'center'
      }
    })
    

    .js文件到处一个vue组件的构造函数.

    在另外一个组件里

    import JsCompConstructor from './components/js-comp-constructor'
    
    注册这个组件:
    
    components: {
        JsCompConstructor
    }
    
    
    使用这个组件
     <JsCompConstructor></JsCompConstructor>
    
    image.png

    通过这样的原理,我们完全可以在HTML页面的任意地方,任意位置,任意的挂在我们自己的组件.并不一定必须使用.vue声明式组件的语法.


    最后总结

    • 在 vue 开发中,组件是很常见的.
    • 组件分局部组件全局组件
    • 组件的本质是通过 Vue.extend(options)来构建出一个组件的构造函数.
    • 组件对象 options 写法有两种.
      • .vue 模板格式.
        • 搭配 vue-loader 就编译成一个普通的 options 对象.
      • .js 格式.
        • 提供一个满足组件options的对象.
        • 通过 Vue.extend() 拿到组件构造函数
        • 我们就可以很自由的在任意时间,任意地方去挂载我们的组件了.
    image.png

    [码云地址]

    相关文章

      网友评论

        本文标题:Vue - 组件和Vue.extend

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