前端时间项目需要个预览功能 我的设计是给预览按钮添加自定义指令然后赋予预览功能 自定义指令就没什么可说的了 但是要在自定义指令里去调用预览组件就难到我了 当然最后也是实现了的 但是代码就丑陋了些 这里也就不现眼了 然后今天有看到大佬发的文章 代码也是美妙的狠 所以就爬下来 原文在最下面有连接
下面实现一个简易的message
弹窗组件Message/index.vue
<template>
<div class="wrap">
<template v-for="item in notices">
<transition name="fade" :key="item._name">
<div class="message" :class="item.type">
<div class="content">{{item.content}}</div>
</div>
</transition>
</template>
</div>
</template>
<script>
// 默认选项
const DefaultOptions = {
duration: 1500,
type: "info",
content: "这是一条提示信息!"
};
let mid = 0;
export default {
data() {
return {
notices: []
};
},
methods: {
add(notice = {}) {
// name标识 用于移除弹窗
let _name = this.getName();
// 合并选项
notice = Object.assign(
{
_name
},
DefaultOptions,
notice
);
this.notices.push(notice);
setTimeout(() => {
this.removeNotice(_name);
}, notice.duration);
},
getName() {
return "msg_" + mid++;
},
removeNotice(_name) {
let index = this.notices.findIndex(item => item._name === _name);
this.notices.splice(index, 1);
}
}
};
</script>
<style lang="scss" scoped>
.wrap {
position: fixed;
top: 50px;
left: 50%;
display: flex;
flex-direction: column;
align-items: center;
transform: translateX(-50%);
}
.message {
--borderWidth: 3px;
min-width: 240px;
max-width: 500px;
margin-bottom: 10px;
border-radius: 3px;
box-shadow: 0 0 8px #ddd;
overflow: hidden;
}
.content {
padding: 8px;
line-height: 1.3;
}
.message.info {
border-left: var(--borderWidth) solid #909399;
background: #f4f4f5;
}
.message.success {
border-left: var(--borderWidth) solid #67c23a;
background: #f0f9eb;
}
.message.error {
border-left: var(--borderWidth) solid #f56c6c;
background: #fef0f0;
}
.message.warning {
border-left: var(--borderWidth) solid #e6a23c;
background: #fdf6ec;
}
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.5s;
}
.fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ {
opacity: 0;
}
</style>
Message/index.js
import Vue from 'vue'
import Index from './index.vue'
let messageInstance = null
let MessageConstructor = Vue.extend(Index) // 构造子类
let init = () => {
messageInstance = new MessageConstructor() // 实例化组件
// $mount可以传入选择器字符串,表示挂载到该选择器
// 如果不传入选择器,将渲染为文档之外的的元素,你可以想象成 document.createElement()在内存中生成dom
messageInstance.$mount()
// messageInstance.$el获取的是dom元素
document.body.appendChild(messageInstance.$el)
}
/**
* 单例且惰性
*/
export let caller = (options) => {
if (!messageInstance) {
init(options)
}
messageInstance.add(options)
}
export default {
// 返回 install 函数 用于 Vue.use 注册
install(vue) {
vue.prototype.$message = caller
}
}
main.js
import Message from '@/components/Message/index.js'
Vue.use(Message)
两种使用使用方式
/**
* 在.js文件里这样用
*/
import { caller } from "@/components/Message/index.js";
caller({
type: "success",
content: "成功信息提示",
duration: 3000
});
/**
* 在.vue文件里这样用
*/
this.$message({
type: "success",
content: "成功信息提示",
duration: 3000
});
细节主要集中在Message/index.js
这个文件里
主要是通过Vue.extend
这个全局是api和这个vm.$mount
实例的api去实现的
原文10个Vue开发技巧助力成为更好的工程师
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。