Vue.extend构造器的延伸
前段时间花了不少的时间在学习和了解Vue的组件,虽然中间浅尝了Vue组件的基础,体验了其魅力,但还是有很多深层的东西未掌握,也还不能非常灵活的使用Vue的组件。但这一切并不重要,随着后面的学习,我想会对Vue越来越熟悉。这两天在看Vue中的 Vue.extend 构造器,今天简单的对这方面的东西做个笔记。
什么是Vue.extend
Vue.extend 返回的是一个扩展实例构造器,也就是预设了部分选项的Vue实例构造器。其主要用来服务于 Vue.component ,用来生成组件。可以简单的理解为当在模板中遇到该组件名称作为标签的自定义元素时,会自动调用扩展实例构造器来生产组件实例,并挂载到自定义元素上。
创建一个Vue.extend
在学习Vue实例和生命周期时,了解了在Vue中创建一个Vue实例,大致经会经历四个过程:
当Vue实例创建之后,可以看到Vue实例预设了很多参数:
那么创建一个 Vue.extend 其实也有点类似,首先通过 Vue.extend() 来创建一个扩展实例构造器:
1 let baseExtend = Vue.extend({ 2 template: `<p> {{ firstName }} {{ lastName }} aka {{ alias }}</p>`, 3 data () { 4 return { 5 firstName: '大漠', 6 lastName: 'w3cplus', 7 alias: '大漠_w3cplus' 8 } 9 }, 10 created () { 11 console.log('onCreated-1'); 12 } 13 })
为了后面更好的使用 Vue.extend() 中的 options ,直接把上面示例中的一些选项提出来,这些选项其实就是前面所说的预设选项:
1 let baseOptions = { 2 template: `<p> {{ firstName }} {{ lastName }} aka {{ alias }}</p>`, 3 data () { 4 return { 5 firstName: '大漠', 6 lastName: 'w3cplus', 7 alias: '大漠_w3cplus' 8 } 9 } 10 }
这个时候可以这样使用:
let baseExtend = Vue.extend(baseOptions);
可以借用 new 关键词来声明这个构造器:
new baseExtend()
可以看到,这个有 new Vue() 有点类似,除了我们预设的一些东西之外,Vue还给其预设了很多其他的东西:
Vue的实例最终是要挂载到一个元素上,那么 Vue.extend 也是一样的,也需要挂载到一个元素上:
new baseExtend().$mount('#app')
我尝试了一下像Vue的实例挂载的方式:
1 let app = new baseExtend({ 2 el: '#app' 3 })
最终得到的效果是相同的。除此之外,还可以将其挂载到自定义的标签上,比如:
1 <!-- HTML --> 2 <custom-element></custom-element> 3 4 <!-- Script --> 5 new baseExtend().$mount('custom-element')
结果如下:
整个过程是不是有点类似于Vue实例创建的过程:
Vue.extend的作用
Vue.extend 常和Vue的组件配合在一起使用。简单点说: Vue.extend 是构造一个组件的语法器,你给这个构造器预设一些参数,而这个构造器给你一个组件,然后这个组件你就可以用到 Vue.component 这个全局注册方法里,也可以在任意Vue模板里使用这个构造器。
基于上面的实例,咱们通过 Vue.extend 构建了一个 baseExtend() 构造器,这个构造器具有 baseOptions 设置的参数。
咱们先忽略上面这段描述,来看 Vue.component() 创建的组件:
1 Vue.component('base-component',baseOptions) 2 let app = new Vue({ 3 el: '#app' 4 }) 5 <!-- HTMl --> 6 <div id="app"> 7 <base-component></base-component> 8 </div>
如果我们把 Vue.component() 中的 baseOptions 换成前面已创建的扩展器 baseExtend :
1 Vue.component('base-component',baseExtend) 2 // 其等于 3 Vue.component('base-component', Vue.extend(baseOptions))
可以看到效果是相同的。
也就是说:
1 Vue.component('base-component', Vue.extend(baseOptions)) 2 Vue.component('base-component',baseExtend) 3 Vue.component('base-component',baseOptions)
三者是等同的。即:
Vue.component()会注册一个全局的组件,其会自动判断第二个传进来的是Vue继续对象(Vue.extend)还是普通对象({...}),如果传进来的是普能对象的话会自动调用Vue.extend,所以你先继承再传,还是直接传普通对象对Vue.component()的最终结果是没差的。
Vue.extend()和Vue.component()的区别
Vue允许你将注册的 ViewModel 构造函数视为可重用的组件,这些组件在概念上与Web组件相似,不需要任何Polyfill。要注册一个组件,首先使用 Vue.extend() 创建一个Vue的子类构造函数,然后使用 Vue.component() 方法注册该构造函数:
1 // 扩展Vue来获取可重用的构造函数 2 var MyComponent = Vue.extend({ 3 template: '一个自定义的组件!' 4 }) 5 // 使用`id:my-component`注册构造函数 6 Vue.component('my-component', MyComponent)
平时我们看到的是直接在 Vue.component() 中使用 options 对象,而不是实际的构造函数来注册一个组件,比如:
1 Vue.component('my-component', { 2 template: '一个自定义的组件!' 3 })
其实上面这段代码隐式的调用了 Vue.extend() ,然后注册返回的构造函数。当你不需要编程实例化组件时,使用此语法。注意:这个方法返回的是Vue
,而不是注册的构造函数。
然后,你可以在父ViewModel的 template 中使用它:
<div v-component="my-component"></div>
如果你喜欢,组件也可以使用自定义元素标记的形式:
<my-component></my-component>
为了避免使用的时候与原生元素命名冲突,并且与W3C自定义元素规范保持一致,组件的ID必须包含一个连字符-作为自定义标签。
理解 Vue.extend() 和 Vue.component() 是很重要的。由于Vue本身是一个构造函数 (constructor) , Vue.extend() 是一个继承于方法的类(class
),参数是一个包含组件选项的对象。它的目的是创建一个Vue的子类并且返回相应的构造函数。而 Vue.component() 实际上是一个类似于 Vue.directive() 和 Vue.filter() 的注册方法,它的目的是给指定的一个构造函数与一个字符串ID
关联起来。之后Vue可以把它用作模板,实际上当你直接传递选项给 Vue.component() 的时候,它会在背后调用 Vue.extend() 。
Vue.js支持两种不同的API模型:一种是基于类的,命令式的,Backbone 类型的API;另一种是基于标记语言的,声明式的,Web组件类型的API。如果还是困惑的话,可以想象你是怎么通过 new Image() 或者 <img>
标签创建 image 元素的就知道了。这两种方法都对指定的类型很有用,Vue提供这两者只是为了更好的灵活性。
总结
这篇文章简单的了解了Vue中的 Vue.extend() 相关的基础知识。另外简单的学习了 Vue.extend() 和 Vue.component() 之间的关系。本来想看看 Vue.extend() 一般用于什么情景之下,目前看到在写Vue插件的时候,会时常运用到 Vue.extend() ,我想后续在学习这方面知识的时候,我们应该又会回来重温 Vue.extend() 。另外,在学习中我发现,在Vue中,还有一个 extends 和 Vue.mixin 。感觉好乱,要学的东西特多,昨天就把 Vue.extend() 和 extends 给混淆了。我想有必要花点时间来理清楚这些基础的东东。
由于本人是Vue初学者,如果文中有何不对之处,还请各路大神拍正!