vue怎么使用Vue.extend创建全局toast组件
Vue.extend创建全局toast组件
src -> components -> Toast -> toast.vue
{{txt}}
src -> components -> Toast -> index.js
import Toast from './toast.vue'
const toast = {}
toast.install = (vue) => {
const ToastClass = vue.extend(Toast)
const instance = new ToastClass()
instance.$mount(document.createElement('div'))
document.body.appendChild(instance.$el)
let t = null
const ToastMain = {
show (msg, seconds = 2000) {
if (t) clearTimeout(t)
instance.txt = msg
instance.show = true
t = setTimeout(() => {
instance.show = false
}, seconds)
}
}
vue.prototype.$toast = ToastMain
}
export default toastmain.js
import Vue from 'vue' import App from './App.vue' import toast from '@/components/Toast/index' Vue.use(toast)
使用
$toast.show(message)
关于vue.extend的理解应用
基本概念
Vue.extend( options )
使用基础 Vue 构造器,创建一个“子类”。参数是一个包含组件选项的对象。
一般,我们会用 Vue.extend 接收一个组件对象来创建一个构造器,再利用创建的构造器 new 一个实例,并将这个实例挂载到一个元素上。
官网基本示例
// 创建构造器
var Profile = Vue.extend({
template: '{{firstName}} {{lastName}} aka {{alias}}
',
data: function () {
return {
firstName: 'Walter',
lastName: 'White',
alias: 'Heisenberg'
}
}
})
// 创建 Profile 实例,并挂载到一个元素上。
new Profile().$mount('#mount-point')data 选项是特例,需要注意 - 在 Vue.extend() 中它必须是函数
结果如下:
Walter White aka Heisenberg
应用
Vue.extend 属于 Vue 的全局 API,在实际业务开发中我们很少使用,因为相比常用的 Vue.component 写法使用 extend 步骤要更加繁琐一些。
但是在一些独立组件开发场景中,例如要实现一个类似于 window.alert() 提示组件,要求像调用 JS 函数一样调用它,这时候 Vue.extend + $mount 这对组合就是我们需要去关注的。
1、vue $mount 和 el的区别说明
在应用之前我们先了解一下2个东西 —— $mount 和 el,两者在使用效果上没有任何区别,都是为了将实例化后的vue挂载到指定的dom元素中。
如果在实例化vue的时候指定el,则该vue将会渲染在此el对应的dom中,反之,若没有指定el,则vue实例会处于一种“未挂载”的状态,此时可以通过$mount来手动执行挂载。
注:如果$mount没有提供参数,模板将被渲染为文档之外的的元素,并且你必须使用原生DOM API把它插入文档中。
var MyComponent = Vue.extend({
template: 'Hello!'
})
// 创建并挂载到 #app (会替换 #app)
new MyComponent().$mount('#app')
// 同上
new MyComponent({ el: '#app' })
// 或者,在文档之外渲染并且随后挂载
var component = new MyComponent().$mount()
document.getElementById('app').appendChild(component.$el)2、Vue.extend实现Loading插件($mount)
function Loading(msg) { // 创建构造器 const Loading = Vue.extend({ template: '{{ msg }}', props: { msg: { type: String, default: '加载中' } }, name: 'Loading' }) // 创建挂载div const div = document.createElement('div') div.setAttribute('id', 'loading-div') document.body.append(div) // 创建实例并挂载到一个元素上 new Loading().$mount('#loading-div') // 返回一个移除元素的function return () => { document.body.removeChild(document.getElementById('loading-div')) } } // 挂载到vue实例上 Vue.prototype.$loading = Loading new Vue({ el: '#root', methods: { showLoading() { const hide = this.$loading('正在加载,请稍等...') setTimeout(() => { hide() }, 1500) } } })
3、Vue.extend实现信息弹窗插件(el)
新建一个popBox.vue
{{ text.title }}{{ text.msg }}
新建一个popBox.js
import Vue from 'vue'
import PopBox from './popBox.vue'
// Vue.extend返回一个实例创建的构造器,但实例构造器需要进行挂载到页面中
let popBox = Vue.extend(PopBox)
popBox.install = (vue, text) => {
// 在body中动态创建一个div元素,之后此div将会替换成整个vue文件的内容
// 此时的popBoxDom通俗讲就是相当于是整个组件对象,通过对象调用属性的方法来进行组件中数据的使用
let popBoxDom = new popBox({
el: document.createElement('div')
})
// 可以通过$el属性来访问创建的组件实例
document.body.appendChild(popBoxDom.$el)
// 将需要传入的文本内容传给组件实例
popBoxDom.text = text;
// 返回一个promise,进行异步操作,成功时返回,失败时返回
return new Promise((res, rej) => {
popBoxDom.show = () => {
res() //正确时返回的操作
popBoxDom.flag = false;
}
popBoxDom.hide = ()=>{
rej() //失败时返回的操作
popBoxDom.flag = false;
}
}
vue.prototype.$popBox = popBox
})
}
// 将逻辑函数进行导出和暴露
export default popBox页面使用
import PopBox from './popBox.js'
Vue.use(popBOx);
this.$popBox({
title:'标题',
msg:'内容',
btn:{ ok:'确定', no:'取消'}
}).then(()=>{
console.log('ok')
}).catch(()=>{
console.log('no')
})其他
import toastCom from "./Toast";
const toast = {};
toast.install = vue => {
const ToastCon = vue.extend(toastCom);
const ins = new ToastCon();
ins.$mount(document.createElement("div"));
document.body.appendChild(ins.$el);
console.log(ins.toast)
vue.prototype.$toast = ins.toast;
};
const globalComponent = {
install: function(Vue) {
Vue.use(toast);
}
};
export default globalComponent;