elementUI 源码-打造自己的组件库,系列四:Dialog组件(原创)

先上车

废了废了,中间一堆事耽误了迟迟没有更新
来吧继续阅读组件源码,dialog组件安排上
个人觉得dialog组件的难点在于弹出框的流程,特别是层级的处理
当然其他小的知识点也是不少的,这就是阅读源码的快乐

上源码

源码大致分为三部分阅读,先易后难没毛病

html部分

打开packages/dialog/src/component.vue

<template>
  <!--transition组件可以给任何元素和组件添加进入/离开过渡-->
  <!--after-enter、after-leave是对应的钩子-->
  <transition
    name="dialog-fade"
    @after-enter="afterEnter"
    @after-leave="afterLeave">
    <div
      v-show="visible"
      class="el-dialog__wrapper"
     <!-- click.self 只当在 event.target 是当前元素自身时触发处理函数, 即点击弹框背景是触发,点击弹框内部元素不会触发 -->
      @click.self="handleWrapperClick">
      <div
        role="dialog"
        <!--亮点:通过改变key值来销毁div-->
        :key="key"
        aria-modal="true"
        :aria-label="title || 'dialog'"
        :class="['el-dialog', { 'is-fullscreen': fullscreen, 'el-dialog--center': center }, customClass]"
        ref="dialog"
        :style="style">
        <!--dialog_header包含:标题、关闭按钮-->
        <div class="el-dialog__header">
          <!--标题-->
          <slot name="title">
            <span class="el-dialog__title">{
  
  { title }}</span>
          </slot>
          <!--关闭按钮-->
          <button
            type="button"
            class="el-dialog__headerbtn"
            aria-label="Close"
            v-if="showClose"
            @click="handleClose">
            <i class="el-dialog__close el-icon el-icon-close"></i>
          </button>
        </div>
        <!--中间的内容-->
        <div class="el-dialog__body" v-if="rendered"><slot></slot></div>
        <!--底部内容-->
        <div class="el-dialog__footer" v-if="$slots.footer">
          <slot name="footer"></slot>
        </div>
      </div>
    </div>
  </transition>
</template>

总结:
1、亮点:通过改变key值来销毁div(铁子们还知道vue中key的其他用法吗?)
2、vue内置transition组件及其钩子函数的灵活运用
3、@click.self 指触发元素自身时生效

script部分

还是packages/dialog/src/component.vue

<script>
  // Popup用来对dialog弹框的流程控制,是下一小节分析的重点
  import Popup from 'element-ui/src/utils/popup';
  // migrating.js 主要目的是在浏览器控制台输出element ui 已经移除的一些属性
  import Migrating from 'element-ui/src/mixins/migrating';
  // emitter.js 中有两个方法,dispatch是用于派发事件,而broadcast用于广播到子组件以及子孙指定组件
  import emitter from 'element-ui/src/mixins/emitter';

  export default {
    name: 'ElDialog',
    mixins: [Popup, emitter, Migrating],
    props: {
      title: {
        type: String,
        default: ''
      },
      modal: {
        type: Boolean,
        default: true
      },
      modalAppendToBody: {
        type: Boolean,
        default: true
      },
      appendToBody: {
        type: Boolean,
        default: false
      },
      lockScroll: {
        type: Boolean,
        default: true
      },
      closeOnClickModal: {
        type: Boolean,
        default: true
      },
      closeOnPressEscape: {
        type: Boolean,
        default: true
      },
      showClose: {
        type: Boolean,
        default: true
      },
      width: String,
      fullscreen: Boolean,
      customClass: {
        type: String,
        default: ''
      },
      top: {
        type: String,
        default: '15vh'
      },
      beforeClose: Function,
      center: {
        type: Boolean,
        default: false
      },
      destroyOnClose: Boolean
    },

    data() {
      return {
        closed: false,
        key: 0
      };
    },

    watch: {
      // 监听visible来控制弹框的打开与关闭
      visible(val) {
        if (val) {
          /* 组件打开时的流程 */
          this.closed = false;
          // 执行组件外部绑定的open方法,如 <el-dialog @open=openDialog />
          this.$emit('open');
          // 给弹框绑定scroll事件,滚动时触发updatePopper,通过emitter.js中broadcast向子孙组件广播 让他们更新 Popper
          this.$el.addEventListener('scroll', this.updatePopper);
          // 然后dialog 滚动到顶部
          this.$nextTick(() => {
            this.$refs.dialog.scrollTop = 0;
          });
          // appendToBody属性用来控制Dialog自身是否插入至body元素上
          if (this.appendToBody) {
            document.body.appendChild(this.$el);
          }
        } else {
          /* 组件关闭时的流程 */
          // 移除scroll事件
          this.$el.removeEventListener('scroll', this.updatePopper);
          // 执行组件外部绑定的open方法,如 <el-dialog @close=closeDialog />
          if (!this.closed) this.$emit('close');
          // 如果设置destroyOnClose,该属性用来控制关闭时销毁Dialog中的元素,通过改变key值来销毁组件
          if (this.destroyOnClose) {
            this.$nextTick(() => {
         
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

海阔~天空

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值