Wuxh

Front-end Development

0%

用Vue.extend写一个全局使用的Alert

由于项目中经常会用到 alert 这种组件,平常都是全局注册标签,使用时引入,比较繁琐;

借鉴别人这种组件一般是在 js 中被调用,vue 中组件主要是使用了标签的形式,
现记录通过 Vue.extend 实现的动态组件;

项目预览

实现代码

1
2
3
4
5
6
├── components
│   ├── HelloWord.vue
│   └── alert
│   ├── alert.vue
│   └── index.js
└── main.js

alert.vue

  • template 部分
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}}
  • JavaScript 部分
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(); // 移除DOM
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原型上
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: () => {
// 测试是否可以拿到这边的this
console.log(this.msg);
}
},
{
text: '不开心',
click: (e, btn) => {
// 这里的event target 可能没用 因为已经移除DOM了 返回btn原来本身
console.log('不开心', e, btn);
}
},
{ text: '无回调' /* 测试一下没有回调函数的时候 */ },
{ text: '帮助', click: this.isOK }
]
});
},
isOK() {
console.log('输出帮助');
}
}
};

参考文档