>[success] # 开始封装 >[danger] ##### 封装主体部分 ~~~ 1.现在知道'.vue' 文件最后还是会解析成类似js 文件这样,我们前期创建这个'$Alert' 组件过程还是和以前 一样就行 2.使用的时候: this.$Alert({ content: '这是一条提示信息', duration: 3 }) 2.1.虽然现在我们不清楚这种调用的形式是怎么实现的,但是可以注意到需要传入是一个对象,这个对象 有负责输出内容的'content',有可以设置延迟的'duration' 3.下面代码中的add 主要负责就是将传进来的这个对象进行重新,对 属性中多的'content' 和'duration' 进行分配 首先定义了一个全局的'getUuid' 的方法,因为在使用的时候会出现连续调用的情况,我们做一个标记,这样 我们就清楚合适应该对那个弹窗进行销毁,和应该展示那个弹窗的先后顺序 4.当然iview 作者 也对这个add 方法做了更多的解释: 由这个思路,Alert 组件就可以无限扩展,只要在 add 方法中传递更多的参数,就能支持更复杂的组件, 比如是否显示手动关闭按钮、确定 / 取消按钮,甚至传入一个 Render 函数都可以。 ~~~ ~~~ <!-- alert.vue --> <template> <div class="alert"> <div class="alert-main" v-for="item in notices" :key="item.name"> <div class="alert-content">{{ item.content }}</div> </div> </div> </template> <script> let seed = 0; function getUuid() { return "alert_" + seed++; } export default { data() { return { notices: [] }; }, methods: { add(notice) { const name = getUuid(); let _notice = Object.assign( { name: name }, notice ); this.notices.push(_notice); // 定时移除,单位:秒 const duration = notice.duration; setTimeout(() => { this.remove(name); }, duration * 1000); }, remove(name) { const notices = this.notices; for (let i = 0; i < notices.length; i++) { if (notices[i].name === name) { this.notices.splice(i, 1); break; } } } } }; </script> <style> .alert { position: fixed; width: 100%; top: 16px; left: 0; text-align: center; pointer-events: none; } .alert-content { display: inline-block; padding: 8px 16px; background: #fff; border-radius: 3px; box-shadow: 0 1px 6px rgba(0, 0, 0, 0.2); margin-bottom: 8px; } </style> ~~~ >[danger] ##### 将组件主体变成一个未挂载组件 ~~~ 1.我们在Alert 组件文件夹下创建一个这个文件叫'notification.js' 2.我们再将组件封装的两个方法暴露出去,也就是'add' 方法和'remove' 方法 ~~~ ~~~ // notification.js import Alert from './alert.vue'; import Vue from 'vue'; Alert.newInstance = properties => { const props = properties || {}; const Instance = new Vue({ data: props, render (h) { return h(Alert, { props: props }); } }); const component = Instance.$mount(); document.body.appendChild(component.$el); const alert = Instance.$children[0]; return { add (noticeProps) { alert.add(noticeProps); }, remove (name) { alert.remove(name); } } }; ~~~ >[danger] ##### 提供一个调用者 ~~~ 1.在创建一个alert.js 文件这样可以供全局调用 2.'getMessageInstance' 函数用来获取实例,它不会重复创建,如果 'messageInstance' 已经存在, 就直接返回了,只在第一次调用 'Notification' 的 'newInstance' 时来创建实例 2.要考虑销毁组件 ~~~ ~~~ // alert.js import Notification from './notification.js'; let messageInstance; function getMessageInstance () { messageInstance = messageInstance || Notification.newInstance(); return messageInstance; } function notice({ duration = 1.5, content = '' }) { let instance = getMessageInstance(); instance.add({ content: content, duration: duration }); } export default { info (options) { return notice(options); } } ~~~ >[danger] ##### 注册这个组件 ~~~ // src/main.js import Vue from 'vue' import App from './App.vue' import router from './router' import Alert from '../src/components/alert/alert.js' Vue.config.productionTip = false Vue.prototype.$Alert = Alert new Vue({ router, render: h => h(App) }).$mount('#app') ~~~ >[danger] ##### 使用它 ~~~ <!-- src/views/alert.vue --> <template> <div> <button @click="handleOpen1">打开提示 1</button> <button @click="handleOpen2">打开提示 2</button> </div> </template> <script> export default { methods: { handleOpen1 () { this.$Alert.info({ content: '我是提示信息 1' }); }, handleOpen2 () { this.$Alert.info({ content: '我是提示信息 2', duration: 3 }); } } } </script> ~~~