共计 2611 个字符,预计需要花费 7 分钟才能阅读完成。
前端时间项目需要个预览功能 我的设计是给预览按钮添加自定义指令然后赋予预览功能 自定义指令就没什么可说的了 但是要在自定义指令里去调用预览组件就难到我了 当然最后也是实现了的 但是代码就丑陋了些 这里也就不现眼了 然后今天有看到大佬发的文章 代码也是美妙的狠 所以就爬下来 原文在最下面有连接
下面实现一个简易的 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 开发技巧助力成为更好的工程师
正文完