Vue.extend
属于 Vue 的全局 API。
创建 Vue 实例时,都会有一个 el 选项,来指定实例的根节点,如果不写 el 选项,那组件就处于未挂载状态
。Vue.extend
的作用,就是基于 Vue 构造器,创建一个子类,它的参数跟 new Vue 的基本一样,但 data 要
跟组件一样,是个函数,再配合$mount
,就可以渲染组件,并且挂载到任意指定的节点上,比如 body(这是单
文件组件做不到的)。
基础用法
<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');
实战
Toast 1
// toast.vue
<template>
<transition name="el-message-fade">
<div
v-show="visible"
class="my-msg"
>
{{ value }}
</div>
</transition>
</template>
<script>
export default {
data() {
return {
value: '',
time: 1000,
visible: true
};
},
methods: {
close() {
setTimeout(() => {
this.$emit('callback', 'Toast 返回的数据');
this.visible = false;
this.$el.remove();
}, this.time);
}
},
mounted() {
this.close();
}
};
</script>
<style>
.my-msg {
position: fixed;
top: 100px;
left: 50%;
z-index: 1000;
transform: translateX(-50%);
width: 160px;
height: 50px;
line-height: 50px;
background-color: #f2f2f2;
color: #000;
text-align: center;
border-radius: 4px;
}
</style>
// toast.js
import Vue from 'vue';
import Toast from './Toast.vue';
export default function (data) {
const instance = new (Vue.extend(Toast))({
data
});
instance.$mount(); // 挂载
document.body.appendChild(instance.$el);
return instance;
}
使用:
<template>
<button @click="show">点击展示</button>
</template>
<script>
import Toast from './toast';
export default {
methods: {
show() {
Toast({ value: '内容', time: 3000 }).$on('callback', text => {
console.log(text);
});
}
}
};
</script>
Toast 2
<!-- Toast.vue -->
<template>
<div :class="{ toast: status }">{{ text }}</div>
</template>
<script>
export default {
name: 'toast',
data() {
return {
status: false,
text: ''
};
}
};
</script>
<style>
.toast {
position: fixed;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
padding: 0 20px;
box-sizing: border-box;
overflow: hidden;
height: 40px;
line-height: 40px;
border-radius: 4px;
font-size: 14px;
min-width: 160px;
background: rgba(0, 0, 0, 0.6);
color: #fff;
box-shadow: 0 0 12px rgba(0, 0, 0, 0.2);
text-align: center;
z-index: 9999;
white-space: nowrap;
animation: fadeoutFrame 3s ease;
}
@keyframes fadeoutFrame {
0% {
height: 0px;
}
5% {
height: 40px;
}
95% {
height: 40px;
}
100% {
height: 0px;
}
}
</style>
// index.js
import ToastComponent from './Toast.vue';
const Toast = {};
Toast.install = function (Vue) {
const ToastConstructor = Vue.extend(ToastComponent);
const instance = new ToastConstructor();
instance.$mount(document.createElement('div'));
document.body.appendChild(instance.$el);
Vue.prototype.$toast = (msg, duration = 3000) => {
instance.text = msg;
instance.status = true;
const timer = setTimeout(() => {
instance.status = false;
instance.text = '';
clearTimeout(timer);
}, duration);
};
};
export default Toast;
// main.js
import Vue from 'vue';
import vToast from './vToast';
Vue.use(vToast);
使用:
<template>
<button @click="show">点击展示</button>
</template>
<script>
export default {
methods: {
show() {
this.$toast('这是一条测试信息', 1500);
}
}
};
</script>