Vue.extend是 vue的全局API,在平常业务开发过程中,使用的频率不高。在一些独立的开发场景中,我们常常将Vue.extend和 $mount 就行结合使用。
一、基本使用
- Vue.extend( options )
- 参数: {Object} options 用法:
使用基础 Vue 构造器,创建一个“子类”。参数是一个包含组件选项的对象。
data 选项是特例,需要注意 - 在 Vue.extend() 中它必须是函数
<div id="mount-point"></div>
// 创建构造器
var Profile = Vue.extend({
template: '<p>{{firstName}} {{lastName}} aka {{alias}}</p>',
data: function () {
return {
firstName: 'Walter',
lastName: 'White',
alias: 'Heisenberg'
}
}
})
// 创建 Profile 实例,并挂载到一个元素上。
new Profile().$mount('#mount-point')
结果如下:
<p>Walter White aka Heisenberg</p>
注意: Vue.extend创建的是一个构造器,和我们平常用的组件区别还是比较大的。注意是使用 new Profile().$mount('#mount-point') 进行指定元素的挂载,而不是 new Vue()
二、Vue.extend 和 Vue.component 的区别
Vue.component需要进行组件注册才能使用,在 template中使用注册的标签名来使用;Vue.extend是编程式写法- 关于组件的显示与否,需要在父组件中传入一个状态来控制 或者 在组件外部用
v-if/v-show来实现控制;而Vue.extend的显示与否是手动的去做组件的挂载和销毁。 Vue.component使用起来更为简单,Vue.extend常用来封装一些全局组件。
三、Vue.extend 的应用
element-ui框架中message 和 message-box 等全局组件的实现,便使用了
Vue.extend。 以message组件为例进行详细分析。
1. 创建 main.vue 组件
创建message组件的架子,这里支持多种类型的信息提醒,使用变量 typeClass 和 type 来控制。
<template>
<transition name="el-message-fade" @after-leave="handleAfterLeave">
<div
:class="[
'el-message',
type && !iconClass ? `el-message--${ type }` : '',
center ? 'is-center' : '',
showClose ? 'is-closable' : '',
customClass
]"
:style="positionStyle"
v-show="visible"
@mouseenter="clearTimer"
@mouseleave="startTimer"
role="alert">
<i :class="iconClass" v-if="iconClass"></i>
<i :class="typeClass" v-else></i>
<slot>
<p v-if="!dangerouslyUseHTMLString" class="el-message__content">{{ message }}</p>
<p v-else v-html="message" class="el-message__content"></p>
</slot>
<i v-if="showClose" class="el-message__closeBtn el-icon-close" @click="close"></i>
</div>
</transition>
</template>
2. vue.extend 实现
let MessageConstructor = Vue.extend(Main): 将main组件引入创建构造器- 声明一个 Message 对象,内部将
MessageConstructor实例化并进行挂载:instance.$mount()
let MessageConstructor = Vue.extend(Main);
const Message = function(options) {
if (Vue.prototype.$isServer) return;
options = options || {};
if (typeof options === 'string') {
options = {
message: options
};
}
let userOnClose = options.onClose;
let id = 'message_' + seed++;
options.onClose = function() {
Message.close(id, userOnClose);
};
instance = new MessageConstructor({
data: options
});
instance.id = id;
if (isVNode(instance.message)) {
instance.$slots.default = [instance.message];
instance.message = null;
}
instance.$mount();
document.body.appendChild(instance.$el);
let verticalOffset = options.offset || 20;
instances.forEach(item => {
verticalOffset += item.$el.offsetHeight + 16;
});
instance.verticalOffset = verticalOffset;
instance.visible = true;
instance.$el.style.zIndex = PopupManager.nextZIndex();
instances.push(instance);
return instance;
};
['success', 'warning', 'info', 'error'].forEach(type => {
Message[type] = options => {
if (typeof options === 'string') {
options = {
message: options
};
}
options.type = type;
return Message(options);
};
});
四、总结
vue是单页面框架,不同页面都是通过router进行控制组件的显示与否。Vue.component 注册的组件都是在当前位置渲染,但若我们想在JavaScript中使用alert()一样方便去使用组件,就可以结合 Vue.extend + $mount 来实现