
What
这篇文章主要写 vue 弹框组件二次封装,即我们在原有组件上再包装一层。
Why
由于弹框组件涉及的内容比较多,可以算是一个比较复杂的组件了。它包括弹框主体、内容区、以及按钮操作。如果我们在同一个页面里面引用的话,会有非常大的代码量,即使内容区独立出来仍然不少,而且独立出来又涉及到组件之间通信的麻烦事。这篇文章就是解决这个问题,使得弹框组件简洁易用。
Where
适用于所有提示类弹框及业务类弹框,不适用消息框。
How
- 在根目录或者
src目录新建Alert.js,内容如下:// Alert.js import Vue from 'vue' import { Dialog, Button } from 'element-ui' export default function create(Component, props, options) { const vm = new Vue({ data() { return { visible: true } }, render() { const onHandleClose = (e, done) => { if (done) done() options.onClose() if (options.destroyInstance) { comp.remove() } else { comp.hide() } } const onHandleMethod = (e, item) => { if (props && props.ref) { item.callback(this.$refs[props.ref]) } else { item.callback() } if (item.close) { if (options.destroyInstance) { comp.remove() } else { comp.hide() } } } return ( <Dialog title={options.title} visible={this.visible} before-close={(e, done) => onHandleClose(e, done)} > { typeof Component === 'object' ? props.ref ? <Component ref={props.ref} props={props} /> : <Component props={props} /> : Component } { options.showButtons ? <span slot="footer" class="dialog-footer"> { options.buttons.map((item, index) => ( index === options.buttons.length - 1 ? <Button key={index} onClick={e => onHandleMethod(e, item)}>{item.title}</Button> : <Button type="primary" key={index} onClick={e => onHandleMethod(e, item)}>{item.title}</Button> )) } </span> : null } </Dialog> ) } }).$mount() document.body.appendChild(vm.$el) const comp = vm.$children[0] comp.show = () => { vm.$data.visible = true } comp.hide = () => { vm.$data.visible = false } comp.remove = () => { document.body.removeChild(vm.$el) comp.$destroy() } return comp } - 将
Alert组件挂到Vue原型上:// main.js import Vue from 'vue' import App from './App.vue' import router from './router' import store from './store' import ElementUI from 'element-ui' import 'element-ui/lib/theme-chalk/index.css' import Alert from '../Alert.js' Vue.prototype.$alert = Alert Vue.config.productionTip = false Vue.use(ElementUI) new Vue({ router, store, render: h => h(App) }).$mount('#app') HelloWorld组件:// HelloWorld.vue <template> <div class="hello"> <h1>{{ msg }}</h1> <p> For a guide and recipes on how to configure / customize this project</p> </div> </template> <script> export default { name: 'HelloWorld', props: { msg: String } } </script>- 组件中使用:
// App.vue <template> <div id="app"> <div id="nav"> <router-link to="/">Home</router-link> | <router-link to="/about">About</router-link> </div> </div> </template> <script> import HelloWorld from './components/HelloWorld' export default { mounted() { const vm = this.$alert(HelloWorld, { msg: 'HelloWorld', // 内容区组件属性传递 ref: 'hello' // 要获取内容区组件内容该字段必传 }, { title: '标题', // 弹框标题 showButtons: true, // 是否显示操作按钮 buttons: [ // 按钮配置:[标题,点击后是否关闭弹框, 点击后执行的事件] { title: '取消', close: true, callback: () => { alert('取消') } }, { title: '确定', close: false, callback: (data) => { // data 是内容区组件实例 console.log(data.msg) vm.hide() // destroyInstance=false 时设置 display=none alert('确定') setTimeout(() => { vm.show() // destroyInstance=false 时设置 display=block setTimeout(() => { vm.remove() // 移除销毁 dom }, 1000) }, 1000) } } ], destroyInstance: false // 关闭时弹框是否移除销毁 dom }) } } </script>
So
经过这样封装,弹框组件使用起来是不是非常简单呢,希望对大家有用,感谢大家!