跳到主要内容

基础用法

// 注册组件,传入一个扩展过的构造器
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>