这是我参与8月更文挑战的第15天,活动详情查看:8月更文挑战
上一篇文章写了创建项目和封装button组件,有需要的童鞋请冲从0搭建Vue2 UI组件库(一),这篇来写下如何封装dialog组件。
一、封装dialog组件
重点:
- 双向绑定的父子组件中的非表单数据用修饰符
sync; - 点击除弹窗外的其他内容都关闭,要使用修饰符
self; - 对于加了
scoped的组件,编译后会给此组件的html元素加上随机属性,对应的css也会带有此属性,外界的元素无此属性,所以不能修改到外界的属性。要使用深度选择器,scss的深度选择器为::v-deep, less为/deep/, css为>>>
1.参数支持
| 参数名 | 参数类型 | 参数描述 | 默认值 |
|---|---|---|---|
| title | string | 对话框标题(可用slot传入) | 提示 |
| width | string | 宽度 | 50% |
| top | string | 与顶部的位置 | 15vh |
| visible | boolean | 是否显示dialog(支持sync修饰符) | false |
1.1. 设置title属性
- 当用户直接写title属性时,获取用户传入的title可用props,然后直接在模板中使用;
- 当用户使用具名插槽slot来传入title时,可直接用slot来接收。
<slot name="title">
<span class="zh-dialog__title">{{title}}</span>
</slot>
props: {
title: {
type: String,
default: '提示'
}
}
1.2. 设置width、top属性
- 获取width、top属性一样是用props,width默认设为50%,top默认设为15vh。
- 再给dialog添加行内样式width、marginTop。
<div class="zh-dialog" :style="{width: width, marginTop: top}">
...
</div>
props: {
......
width: {
type: String,
default: "50%"
},
top: {
type: String,
default: "15vh"
}
}
1.3. 设置visible属性
- 获取visible属性一样用props,用v-show设置模态框的显示隐藏。
- 由于我们要在点击关闭按钮和模态框以外的区域时,隐藏模态框,所以需要给这两个地方设置click事件。click事件中将visible设置为false,但由于visible是用户传进来的,所以我们需要使用$emit来传递数据并触发父组件的visible做改变。用户只需要添加sync修饰符即可。
- 由于给最外层的遮罩添加了click事件隐藏模态框,但点击dialog的主体内容时不能隐藏,所以要给遮罩的click事件添加self修饰符。
<template>
<!-- 对话框遮罩 -->
<div class="zh-dialog__wrapper" v-show="visible" @click.self="handleClose">
<div class="zh-dialog" :style="{ width: width, marginTop: top }">
<div class="zh-dialog__header">
<slot name="title">
<span class="zh-dialog__title">{{ title }}</span>
</slot>
<button class="zh-dialog__headerbtn" @click="handleClose">
<i class="zh-icon-guanbi"></i>
</button>
</div>
......
</div>
</div>
</template>
<script>
export default {
name: "ZhDialog",
props: {
......
visible: {
type: Boolean,
default: false,
},
},
methods: {
handleClose() {
this.$emit("update:visible", false);
},
},
};
</script>
2. 插槽支持
| 插槽名 | 插槽描述 |
|---|---|
| default | 默认插槽,设置body内容 |
| title | 设置标题内容 |
| footer | 设置底部内容 |
2.1. 设置body内容
body内容可以直接用默认插槽接收用户传入的数据。
<div class="zh-dialog__body">
<slot></slot>
</div>
2.2. 设置底部内容
底部内容可以通过footer插槽来获取用户传入的数据,当用户没有写footer数据时,不显示。
<div class="zh-dialog__footer" v-if="$slot.footer">
<slot name="footer"></slot>
</div>
由于用户很可能传进来两个按钮,所以我们可以给第一个按钮设置右间距,使两个按钮不会粘在一起。
但我们的样式加了scoped属性,编译后会给此组件的html元素加上随机属性,对应的css也会带有此属性,外界的元素无此属性,所以不能修改到外界的元素,所以需要使用::v-deep来解决这个问题。
::v-deep .zh-button:first-child {
margin-right: 20px;
}
2.3. 测试代码
- 默认插槽为body设置无序列表
- title插槽为标题设置一个h3标题
- footer插槽为底部设置一个按钮
<template>
<div>
<!-- <zh-dialog title="温馨提示"></zh-dialog> -->
<zh-dialog width="70%" top="100px" :visible.sync="visible">
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
<template v-slot:title>
<h3>我是标题</h3>
</template>
<template v-slot:footer>
<zh-button type="primary">确定</zh-button>
</template>
</zh-dialog>
</div>
</template>
2. 事件支持
| 事件名 | 事件描述 |
|---|---|
| opened | 模态框显示的事件 |
| closed | 模态框关闭的事件 |
系列文章
以下是从0搭建Vue2 UI组件库系列的文章,有需要的同学请冲~~ 从0搭建Vue2 UI组件库(一)