Vue.extend
属于 Vue 的全局 API,在实际业务开发中我们很少使用,因为相比常用的 Vue.component
写法使用 extend
步骤要更加繁琐一些。但是在一些独立组件开发场景中,Vue.extend
+ $mount
这对组合是我们需要去关注的。
官方文档:https://cn.vuejs.org/v2/api/index.html#Vue-extend
参数:{Object} options
用法:使用基础 Vue 构造器,创建一个“子类”。参数是一个包含组件选项的对象。
data
选项是特例,需要注意 - 在 Vue.extend()
中它必须是函数
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.11/vue.min.js"></script> </head> <body> <div id="mount-point"></div> <script> //创建构造器函数 var profile = Vue.extend({ template:`<p>{{fisrstName}} ---- {{lastName}}</p>`, data:function(){ return { fisrstName:"第一个名字", lastName:"第二个名字" } } }); // 创建 Profile 实例,并挂载到一个元素上。 new profile().$mount("#mount-point"); </script> </body> </html>
渲染结果:
<p>第一个名字 ---- 第二个名字</p>
可以看到,extend
创建的是 Vue 构造器,而不是我们平时常写的组件实例,所以不可以通过
new Vue({ components: testExtend })
来直接使用,需要通过 new Profile().$mount('#mount-point')
来挂载到指定的元素上。
为什么使用 extend
在 vue 项目中,我们有了初始化的根实例后,所有页面基本上都是通过 router 来管理,组件也是通过 import
来进行局部注册,所以组件的创建我们不需要去关注,相比 extend
要更省心一点点。但是这样做会有几个缺点:
- 组件模板都是事先定义好的,如果我要从接口动态渲染组件怎么办?
- 所有内容都是在
#app
下渲染,注册组件都是在当前位置渲染。如果我要实现一个类似于window.alert()
提示组件要求像调用 JS 函数一样调用它,该怎么办?
这时候,Vue.extend + vm.$mount
组合就派上用场了。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.11/vue.min.js"></script> </head> <body> <script> const testComponent = Vue.extend({ template: '<div>{{ text }}</div>', data: function () { return { text: 'extend test' } } }) // 然后我们将它手动渲染: const extendComponent = new testComponent().$mount(); // 这时候,我们就将组件渲染挂载到 body 节点上了。 // 我们可以通过 $el 属性来访问 extendComponent 组件实例: document.body.appendChild(extendComponent.$el) </script> </body> </html>
完。
再看个神操作:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.11/vue.min.js"></script> </head> <body> <script> const testComponent = Vue.extend({ template: `<div> <span v-show="aa == true">{{ text }}{{aa}}{{cc}}</span> </div>`, data: function () { return { text: 'extend test', aa : false } }, methods: { hide(booleanVal){ this.aa = booleanVal; } }, }) //取到实例对象 let instance = new testComponent(); instance.hide(true) instance.cc= "哈哈"; // 然后我们将它手动渲染: const extendComponent = instance.$mount(); // 这时候,我们就将组件渲染挂载到 body 节点上了。 // 我们可以通过 $el 属性来访问 extendComponent 组件实例: document.body.appendChild(extendComponent.$el) </script> </body> </html>
可以看到我们可以在渲染之前 通过操作实例对象的值和方法来控制渲染的结果!!!
另外,在渲染之前 我们可以对实例对象进行混入操作:
比如:
instance = Object.assign(instance,{key,val})
这些key会 混入到 实例的data对象里!!!
另外,在创建实例对象的时候,我们可以传入一些data值以及方法:
比如:
//取到实例对象 let instance = new testComponent({ data:function(){ return{ dd:"dsdds" } } });
!!!真强大
来个综合例子:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.11/vue.min.js"></script> </head> <body> <script> const testComponent = Vue.extend({ template: `<div> <span v-show="aa == true">{{ text }}{{aa}}{{cc}}{{dd}}{{ee}}</span> </div>`, data: function () { return { text: 'extend test', aa : false } }, methods: { hide(booleanVal){ this.aa = booleanVal; } }, }) //取到实例对象 let instance = new testComponent({ data:function(){ return{ dd:"dsdds" } } }); instance.hide(true) instance.cc= "哈哈"; instance = Object.assign(instance,{ee:"asign"}) // 然后我们将它手动渲染: const extendComponent = instance.$mount(); // 这时候,我们就将组件渲染挂载到 body 节点上了。 // 我们可以通过 $el 属性来访问 extendComponent 组件实例: document.body.appendChild(extendComponent.$el) </script> </body> </html>
挂载实例也可以这样写:
// 然后我们将它手动渲染: instance.vm = instance.$mount(); // 这时候,我们就将组件渲染挂载到 body 节点上了。 // 我们可以通过 $el 属性来访问instance组件实例:
document.body.appendChild(instance.$el)
。