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