Vue - 组件和Vue.extend

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



 var app = new Vue({
    el: '#app',
    data: {
      title: '我的第一个vue组件'
    },
    methods: {},
    filters: {},
    directives: {},
    components: {},
  })

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

当然,也是在单页面中.

API文档告诉我们

  • Vue.component 用来注册全局组件.
  • 在某个组件内部使用 components:{} 来注册局部组件.


Vue.component('GlobalVueComponent',{
    template:`
{{title}}
`, data () { return { title: '我是使用 Vue.component 注册的全局组件' } } })


let ScopeVueComponent = {
    template:`
{{title}}
`, data () { return { title: '我是使用 components 使用的局部组件' } } } var app = new Vue({ el: '#app', data: { title: '我的第一个vue组件' }, components: { ScopeVueComponent } })
image.png

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




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


Vue.extend 方法.

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

比如在注册局部组件时.

const TodoListComp = {
    template:`

{{ title }}

`, data () { return { title:'用 object 搭配 components 的方式去创建局部组件' } } } const app = new Vue({ el:'#app', components: { TodoListComp, } })

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

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

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

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

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

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

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

const TodoList = Vue.extend({
    template:`

{{ title }}

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

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

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

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


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模板文件时,我们到底在写什么?


 (这里不关注节点) 的格式编写 .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: `
{{title}}
`, 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
}


使用这个组件
 
image.png

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


最后总结

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

[码云地址]

你可能感兴趣的:(Vue - 组件和Vue.extend)