从0搭建Vue2 UI组件库(二)

1,357 阅读3分钟

这是我参与8月更文挑战的第15天,活动详情查看:8月更文挑战

上一篇文章写了创建项目和封装button组件,有需要的童鞋请冲从0搭建Vue2 UI组件库(一),这篇来写下如何封装dialog组件。

一、封装dialog组件

重点:

  1. 双向绑定的父子组件中的非表单数据用修饰符sync
  2. 点击除弹窗外的其他内容都关闭,要使用修饰符self
  3. 对于加了scoped的组件,编译后会给此组件的html元素加上随机属性,对应的css也会带有此属性,外界的元素无此属性,所以不能修改到外界的属性。要使用深度选择器,scss的深度选择器为 ::v-deep, less为/deep/, css为>>>

1.参数支持

参数名参数类型参数描述默认值
titlestring对话框标题(可用slot传入)提示
widthstring宽度50%
topstring与顶部的位置15vh
visibleboolean是否显示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组件库(一)

从0搭建Vue2 UI组件库(二)

从0搭建Vue2 UI组件库(三)

从0搭建Vue2 UI组件库(四)

从0搭建Vue2 UI组件库(五)

从0搭建Vue2 UI组件库(六)

从0搭建Vue2 UI组件库(七)

从0搭建Vue2 UI组件库(八)