实现一个message组件,类似于element ui的消息提示功能。
功能:跳出提示语,几秒后自动隐藏。
目的:巩固和总结Vue自定义插件的方法。
先写一个用import导入插件的模式
开始
第一步
// Messgae.vue
// 初始化模板和数据
<template>
<div>
<div v-for="m in message" :key="m.id">{{m.message}}</div>
</div>
</template>
<script>
export default {
name: 'ELMessage',
data() {
return {
message: [] // {id, message, duration}
}
}
}
</script>
// message.js
export const Message = {
info (options) {
console.log(options);
}
}
// App.vue
<template>
<div id="app">
<button @click="showMessage">全局message</button>
</div>
</template>
<script>
// import 导入js
import { Message } from './component/message'
let id = 0
export default {
name: 'App',
data() {
return {}
},
created() {
},
methods: {
showMessage() {
Message.info({ message: `这是消息提示${++id}`, duration: 2000})
}
},
}
</script>
输出
第二步
// message.vue
<template>
<div>
<div v-for="m in message" :key="m.id">{{m.message}}</div>
</div>
</template>
<script>
export default {
name: 'ELMessage',
data() {
return {
message: [] // {id, message, duration}
}
},
mounted() {
this.id = 0
},
methods: {
add(options) {
const layer = {
...options,
id: ++this.id
}
this.message.push(layer)
setTimeout(() => {
this.remove(layer)
}, layer.duration)
},
remove(layer) {
this.message = this.message.filter( m => m.id !== layer.id)
}
},
}
</script>
// message.js
import Vue from 'vue'
import MessageComponent from './Message.vue'
const getInstance = () => {
const vm = new Vue({
render: h => h(MessageComponent)
}).$mount() // $mount() 将虚拟DOM转换为真实DOM
//vm.$el 获取Vue实例关联的DOM元素;
document.body.appendChild(vm.$el)
// 当前messageComponent组件
return vm.$children[0]
}
export const Message = {
info (options) {
console.log(options);
getInstance().add(options)
}
}
// App.vue
<template>
<div id="app">
<button @click="showMessage">全局message</button>
</div>
</template>
<script>
// import 导入js
import { Message } from './component/message'
let id = 0
export default {
name: 'App',
data() {
return {}
},
created() {
},
methods: {
showMessage() {
Message.info({ message: `这是消息提示${++id}`, duration: 2000})
}
},
}
</script>
输出效果:前面的消息提示1,2,3过一段时间会消失
发现问题
在第二步中存在一个问题,如下图:
渲染出了多个vm实例
解决
单例模式
import Vue from 'vue'
import MessageComponent from './Message.vue'
// 单例模式
let vm = null
const getInstance = () => {
if (!vm) {
vm = new Vue({
render: h => h(MessageComponent)
}).$mount()
document.body.appendChild(vm.$el)
}
// const vm = new Vue({
// render: h => h(MessageComponent)
// }).$mount() // $mount() 将虚拟DOM转换为真实DOM
//vm.$el 获取Vue实例关联的DOM元素;
// document.body.appendChild(vm.$el)
// 当前messageComponent组件
return vm.$children[0]
}
export const Message = {
info (options) {
console.log(options);
getInstance().add(options)
}
}
现在只会生成一个实例
这里写的是全局可以引用自定义插件的模式
主要是main.js不同,前面重复的文件就不写了
主要是把插件的方法挂载到Vue.prototype
原型对象上
开始
// message.js
import Vue from 'vue'
import MessageComponent from './Message.vue'
// 单例模式
let vm = null
const getInstance = () => {
if (!vm) {
vm = new Vue({
render: h => h(MessageComponent)
}).$mount()
document.body.appendChild(vm.$el)
}
// const vm = new Vue({
// render: h => h(MessageComponent)
// }).$mount() // $mount() 将虚拟DOM转换为真实DOM
//vm.$el 获取Vue实例关联的DOM元素;
// document.body.appendChild(vm.$el)
// 当前messageComponent组件
return vm.$children[0]
}
export const Message = {
info (options) {
console.log(options)
getInstance().add(options)
}
}
// Vue.use(插件)会执行这个install方法
export default {
install(Vue, options) {
console.log(options)
Vue.prototype.$message = {
info: Message.info
}
}
}
// main.js
import Vue from 'vue'
import App from './App.vue'
import Message from './component/message'
// {size: 'small'}作为参数传递
Vue.use(Message, {
size: 'small'
})
// 阻止启动生产消息,常用作指令。浏览器不会打印相关信息
Vue.config.productionTip = false
new Vue({
render: h => h(App),
}).$mount('#app')
这样就可以在任意页面使用this.$message.info
来调用这个插件了
试一下
加一个按钮,执行ShowMessage2
方法
<template>
<div id="app">
<button @click="showMessage">全局message</button>
<button @click="showMessage2">全局原型message</button>
</div>
</template>
<script>
// import 导入js
import { Message } from './component/message'
let id = 0
export default {
name: 'App',
data() {
return {}
},
created() {
},
methods: {
showMessage() {
Message.info({ message: `这是消息提示${++id}`, duration: 2000})
},
showMessage2() {
this.$message.info({message: `这是全局原型消息提示${++id}`, duration: 2000})
}
},
}
</script>
效果:
网友评论