天天看点

vue 如何从 0 实现自己的 UI 组件库之 Dialog 组件

一、vue 实现 ui 组件库之 Dialog 组件

  1. 在项目的

    components

    文件夹中,建立

    dialog.vue

    文件,在

    template

    中,先写对话框的遮罩,并且在遮罩外使用

    transition

    动画进行包裹,定义对话框的动画效果。在对话框的遮罩中,使用

    v-show

    命令控制

    visible

    的值,来控制对话框的显示与隐藏。通过

    @click

    绑定点击事件

    handleClose

    ,对话框的关闭事件,通过使用

    .self

    修饰符,只有当点击自己的时候才会被触发。对话框的显示标题使用

    title

    属性,旁边的关闭按钮也通过

    @click

    绑定点击事件

    handleClose

    。对于对话框的中间显示内容部分,使用默认插槽

    slot

    。对于对话框的底部,使用具名插槽为

    footer

    ,同时使用

    v-if

    命令判断

    $slots.footer

    ,有插槽

    footer

    就显示,没有就不显示,代码如下所示:
<transition name="dialog-fade">
        <div class="jc-dialog__wrapper" v-show="visible" @click.self="handleClose">
            <div class="jc-dialog" :style="{width, marginTop:top}">
                <div class="jc-dialog__header">
                    <slot name="title">
                        <span class="jc-dialog__title">{{ title }}</span>
                    </slot>
                    <button class="jc-dialog__headerbtn" @click="handleClose">
                        <i class="jc-icon-close"></i>
                    </button>
                </div>
                <div class="jc-dialog__body">
                    <slot></slot>
                </div>
                <div class="jc-dialog__footer" v-if="$slots.footer">
                    <slot name="footer"></slot>
                </div>
            </div>
        </div>
  </transition>
           
  1. script

    中,定义

    name

    的值为

    JcDialog

    。定义

    props

    ,定义

    title

    String

    类型,默认显示为提示;定义

    width

    String

    类型,默认显示为

    50%

    ;定义

    top

    String

    类型,默认显示为

    15vh

    ;定义

    visible

    Boolean

    类型,默认显示为

    false

    。在

    methods

    中,定义

    handleClose

    对话框的关闭事件,通过

    this.$emit

    向父组件传递

    update:visible

    事件,传递值为

    false

    ,使用

    update:visible

    这种写法是为了后面使用

    sync

    修饰符,代码如下随所示:
<script>
export default {
  name: 'JcDialog',
  props: {
    title: {
      type: String,
      default: '提示'
    },
    width: {
      type: String,
      default: '50%'
    },
    top: {
      type: String,
      default: '15vh'
    },
    visible: {
      type: Boolean,
      default: false
    }
  },
  methods: {
    handleClose () {
      this.$emit('update:visible', false)
    }
  }
}
</script>
           
  1. 这个

    Dialog

    按钮组件的参数支持,如下所示:
参数名 参数描述 参数类型 默认值
title 对话框标题 string 提示
width 宽度 string 50%
top 与顶部的距离 string 15vh
visible 是否显示dialog(支持sync修饰符) boolean false
  1. style

    中,写对话框的一些样式,

    ::v-deep

    是使用

    scss

    中的深度选择器。定义

    @keyframes

    动画

    fade

    ,进行显示与隐藏。在

    .dialog-fade-enter-active

    中对话框进入的动画,在

    .dialog-fade-leave-active

    中对话框离开的动画,代码如下所示:
<style lang="scss" scoped>
.jc-dialog__wrapper {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  overflow: auto;
  margin: 0;
  z-index: 2001;
  background-color: rgba(0,0,0, .5);

  .jc-dialog {
    position: relative;
    margin: 15vh auto 50px;
    background: #fff;
    border-radius: 2px;
    box-shadow: 0 1px 3px rgba(0,0,0,.3);
    box-sizing: border-box;
    width: 30%;

    &__header {
      padding: 20px 20px 10px;
      .jc-dialog__title {
        line-height: 24px;
        font-size: 18px;
        color: #303133;
      }
      .jc-dialog__headerbtn {
        position: absolute;
        top: 20px;
        right: 20px;
        padding: 0;
        background: transparent;
        border: none;
        outline: none;
        cursor: pointer;
        font-size: 16px;
        .el-icon-close {
          color: #909399;
        }
      }
    }

    &__body {
      padding: 30px 20px;
      color: #606266;
      font-size: 14px;
      word-break: break-all;
    }
    &__footer {
      padding: 10px 20px 20px;
      text-align: right;
      box-sizing: border-box;
      ::v-deep .jc-button:first-child {
        margin-right: 20px;
      }
    }
  }
}

.jc-button {
  margin-right: 20px;
}

.dialog-fade-enter-active {
  animation: fade .3s;
  transform: translateY(-20px);
}

.dialog-fade-leave-active {
  animation: fade .3s reverse;
  transform: translateY(0px);
}

@keyframes fade {
  0% {
    opacity: 0;
  }
  100% {
    opacity: 1;
  }
}
</style>

           
  1. main.js

    文件中,引入

    JcDialog

    组件,并且进行全局注册组件,代码如下所示:
import JcDialog from './components/dialog.vue'

Vue.component(JcDialog.name, JcDialog)
           
  1. App.vue

    文件中,使用

    dialog

    组件,在

    data

    中,定义

    visible

    的值为

    false

    。先使用

    jc-button

    按钮组件,控制对话框的显示与隐藏,绑定点击事件,将

    visible

    的值变为

    true

    ,对话框显示。在

    jc-dialog

    中,分别设置

    title

    width

    top

    的值,使用

    :visible.sync

    ,也就是

    sync

    修饰符,将子组件传递的

    false

    的值赋值为

    visible

    ,对话框就会由显示变为隐藏。

    ul

    是对话框中间显示的内容,使用

    template

    ,名为

    footer

    的插槽,定义两个按钮,绑定点击事件,将

    visible

    变为

    false

    ,对话框进行隐藏,代码如下所示:
<template>
  <div id="app">
    <jc-button type="primary" @click="visible = true">按钮</jc-button>
    <jc-dialog title="温馨提示" width="20%" top="200px" :visible.sync="visible">
      <ul>
        <li>张三</li>
        <li>李四</li>
        <li>王五</li>
      </ul>
      <template v-slot:footer>
        <jc-button type="primary" @click="visible = false">确定</jc-button>
        <jc-button type="primary" @click="visible = false">取消</jc-button>
      </template>
    </jc-dialog>
    
  </div>
</template>

<script>
export default {
  data () {
    return {
      visible: false
    }
  }
}
</script>

<style lang="scss">
.row {
  margin-bottom: 20px;
  .jc-button {
    margin-right: 20px !important;
  }
}
</style>

           
  1. 在浏览器中输入

    http://localhost:8080/

    ,显示如下所示:
vue 如何从 0 实现自己的 UI 组件库之 Dialog 组件
vue 如何从 0 实现自己的 UI 组件库之 Dialog 组件