基础用法
// 注册组件,传入一个扩展过的构造器
Vue.component(
'my-component',
Vue.extend({
/* ... */
})
);
// 注册组件,传入一个选项对象 (自动调用 Vue.extend)
Vue.component('my-component', {
/* ... */
});
// 获取注册的组件 (始终返回构造器)
var MyComponent = Vue.component('my-component');
Vue.component()
会注册一个全局的组件,其会自动判断第二个传进来的是 Vue 继承对象
(vue.extend(baseOptions))还是普通对象(baseOptions),
如果传进来的是普能对象的话会自动调用Vue.extend
,所以你先继承再传,还是直接传普通对象
对Vue.component()
的最终结果是没差的。
Vue.extend()和 Vue.component()的区别
理解Vue.extend()
和Vue.component()
很重要的,由于 Vue 本身是一个构造函数
(constructor),Vue.extend
是—个继承于方法的类 (class ),参效是一个包含组件选项的对象。它的目的是创
建一个 Vue 的子类并且返回相应的构造函数。
而Vue.component
实际上是一个类似于vue.directive()
和vue.filter()
的注册方法,它的目的是给指定的一
个构造函数与一个字符串ID
关联起来,之后 Vue 可以 把它用作模板,实际上当你直接传递选项
给Vue.cosponent()
的时候,它会在背后调用Vue.extend()
。
实用案例
vMessage
<!-- Message.vue -->
<template>
<transition name="fade">
<div
class="message"
:class="type"
v-show="visible"
>
<span class="text">{{ text }}</span>
</div>
</transition>
</template>
<script>
export default {
name: 'vMessage',
props: {
type: {
type: String,
default: 'info',
validator: val => ['info', 'success', 'warning', 'error'].includes(val)
},
text: {
type: String,
default: ''
},
visible: {
type: Boolean,
default: false
}
}
};
</script>
<style scoped lang="scss">
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.3s;
}
.fade-enter,
.fade-leave-to {
opacity: 0;
}
.message {
position: fixed;
top: 40px;
text-align: center;
left: 50%;
transform: translateX(-50%);
min-width: 400px;
padding: 10px 20px;
color: #333333;
background: #f5f5f5;
font-size: 18px;
line-height: 1.4;
border-radius: 4px;
z-index: 1000;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
&.info {
color: purple;
}
&.success {
color: green;
}
&.error {
color: red;
}
&.warning {
color: yellow;
}
}
</style>
// index.js
import Message from './Message';
const vMessage = {
install(Vue) {
if (typeof window !== 'undefined' && window.Vue) {
Vue = window.Vue;
}
// Vue.component 和 Vue.extend 配合使用
Vue.component('vMessage', Message);
function extendVMessage(type, options, callback) {
const { text = '', duration = 1000 } = options;
const MassageConstructor = Vue.extend({
render(h) {
// 生成 vMessage 组件,注入 props
return h('vMessage', { props: { type, text, visible: this.visible } });
},
data: () => ({ visible: true })
});
let instance = new MassageConstructor();
instance.$mount();
document.body.appendChild(instance.$el);
instance.visible = true;
const timer = setTimeout(() => {
clearTimeout(timer);
callback && typeof callback === 'function' && callback();
instance.visible = false;
instance.$destroy();
document.body.removeChild(instance.$el);
instance = null;
}, duration);
}
Vue.prototype.$vMessage = {
info(options, callback) {
extendVMessage('info', options, callback);
},
success(options, callback) {
extendVMessage('success', options, callback);
},
error(options, callback) {
extendVMessage('error', options, callback);
},
warning(options, callback) {
extendVMessage('warning', options, callback);
}
};
}
};
export default vMessage;
// main.js
import Vue from 'vue';
import vMessage from './vMessage/index';
Vue.use(vMessage);
使用:
<template>
<button @click="show">点击展示</button>
</template>
<script>
export default {
methods: {
show() {
// error warning success
this.$vMessage.info(
{
text: '消息',
duration: 3000
},
() => {
console.log('callback');
}
);
}
}
};
</script>