由于项目中经常会用到 alert 这种组件,平常都是全局注册标签,使用时引入,比较繁琐;
借鉴别人这种组件一般是在 js 中被调用,vue 中组件主要是使用了标签的形式,
现记录通过 Vue.extend 实现的动态组件;
项目预览
实现代码
1 2 3 4 5 6
| ├── components │ ├── HelloWord.vue │ └── alert │ ├── alert.vue │ └── index.js └── main.js
|
alert.vue
1 2 3 4 5 6 7 8 9 10 11
| template(lang="pug") .shade .mian .content span {{ message }} .btns .btn( v-for="(btn,index) in btns" :key="index" @click="(e)=>clickFn(e,btn)" ) {{btn.text}}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| export default { name: 'alert', data() { return { message: 'this a alert', btns: [ { text: 'yes', click: () => console.log('yes') }, { text: 'no', click: () => console.log('yes') } ] }; }, methods: { clickFn(event, btn) { this.$el.remove(); const { click = () => console.warn('请传入回调函数') } = btn; click(event, btn); } } };
|
点击查看 CSS 部分
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
| .shade { user-select: none; width: 100vw; height: 100vh; position: fixed; top: 0; left: 0; background-color: rgba(0, 0, 0, 0.03); z-index: 998; display: flex; align-items: center; justify-content: center; } .shade .mian { background: white; width: 80%; border-radius: 5px; overflow: hidden; box-shadow: 0px 0px 5px 3px rgba(0, 0, 0, 0.04); box-sizing: border-box; animation: open 0.1s; } .shade .mian .content { box-sizing: border-box; width: 100%; padding: 30px 20px; } .shade .mian .btns { height: 45px; box-sizing: border-box; border-top: 1px solid rgba(0, 0, 0, 0.1); display: flex; justify-content: space-around; align-items: center; } .shade .mian .btns .btn { flex: 1 0 auto; height: 100%; display: flex; align-items: center; justify-content: center; text-align: center; border-right: 1px solid rgba(0, 0, 0, 0.1); } .shade .mian .btns .btn:last-child { border-right: none; } .shade .mian .btns .btn:active { color: white; background-color: rgb(64, 169, 243); } @keyframes open { 0%, 100% { transform: scale(1); } 25%, 75% { transform: scale(1.04); } 50% { transform: scale(1.06); } }
|
index.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| import Vue from 'vue'; import alert from './alert.vue'; let MyAlertConstructor = Vue.extend(alert); let instance; const MyAlert = option => { instance = new MyAlertConstructor({ data: { ...option } }); instance.$mount(); document.body.appendChild(instance.$el); return instance; };
Vue.prototype.$alert = MyAlert;
|
main.js
1
| import './components/alert';
|
到这里我们的 Alert 组件就配置完成了;
组件中使用
这里我在 Helloword.vue 中测试使用;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| export default { name: 'HelloWorld', props: ['msg'], methods: { Alert() { this.$alert({ message: '你今天开心吗?', btns: [ { text: '开心', click: () => { console.log(this.msg); } }, { text: '不开心', click: (e, btn) => { console.log('不开心', e, btn); } }, { text: '无回调' }, { text: '帮助', click: this.isOK } ] }); }, isOK() { console.log('输出帮助'); } } };
|
参考文档