zoukankan      html  css  js  c++  java
  • element-ui Tag、Dialog组件源码分析整理笔记(五)

    Tag 标签组件

    <script>
      export default {
        name: 'ElTag',
        props: {
          text: String,
          closable: Boolean, //是否可关闭
          type: String, //主题
          hit: Boolean, //是否有边框描边
          disableTransitions: Boolean, //是否禁用渐变动画
          color: String, //背景色
          size: String  //尺寸
        },
        methods: {
          handleClose(event) {
            event.stopPropagation();
            this.$emit('close', event);
          }
        },
        computed: {
          tagSize() {
            return this.size || (this.$ELEMENT || {}).size;
          }
        },
        render(h) {
          const classes = [ 'el-tag', this.type ? `el-tag--${this.type}` : '',
            this.tagSize ? `el-tag--${this.tagSize}` : '',
            {'is-hit': this.hit}
          ];
          //最外层包裹的span
          const tagEl = (<span class={classes} style={{backgroundColor: this.color}}>
            { this.$slots.default }
            {
              // closable存在时,返回关闭图标
              this.closable && <i class="el-tag__close el-icon-close" on-click={this.handleClose}></i>
            }
          </span>);
          // disableTransitions存在的话,用transition标签包裹,产生渐变动画
          return this.disableTransitions ? tagEl : <transition name="el-zoom-in-center">{ tagEl }</transition>;
        }
      };
    </script>
    

    Dialog 对话框组件

    <template>
        <!--transition组件可以给任何元素和组件添加进入/离开过渡-->
      <transition
        name="dialog-fade"
        @after-enter="afterEnter"
        @after-leave="afterLeave">
         <!--包裹dialog的div-->
        <div class="el-dialog__wrapper" v-show="visible" @click.self="handleWrapperClick">
          <div
            role="dialog"
            aria-modal="true"
            :aria-label="title || 'dialog'"
            class="el-dialog"
            :class="[{ '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>
    
    <script>
      import Popup from 'element-ui/src/utils/popup';
      //在控制台输出一些已经移除的属性
      import Migrating from 'element-ui/src/mixins/migrating';
      //触发子组件或者父组件的事件
      import emitter from 'element-ui/src/mixins/emitter';
    
      export default {
        name: 'ElDialog',
    
        mixins: [Popup, emitter, Migrating],
    
        props: {
          title: { //Dialog 的标题,也可通过具名 slot(titlefooter)传入
            type: String,
            default: ''
          },
          modal: { //是否需要遮罩层
            type: Boolean,
            default: true
          },
          modalAppendToBody: { //遮罩层是否插入至 body 元素上,若为 false,则遮罩层会插入至 Dialog 的父元素上
            type: Boolean,
            default: true
          },
          appendToBody: { //Dialog 自身是否插入至 body 元素上。嵌套的 Dialog 必须指定该属性并赋值为 true
            type: Boolean,
            default: false
          },
          lockScroll: { //是否在 Dialog 出现时将 body 滚动锁定
            type: Boolean,
            default: true
          },
          closeOnClickModal: { //是否可以通过点击 modal 关闭 Dialog
            type: Boolean,
            default: true
          },
          closeOnPressEscape: { //是否可以通过按下 ESC 关闭 Dialog
            type: Boolean,
            default: true
          },
          showClose: { //是否显示关闭按钮
            type: Boolean,
            default: true
          },
           String, //Dialog 的宽度
          fullscreen: Boolean, //是否为全屏 Dialog
          customClass: { //Dialog 的自定义类名
            type: String,
            default: ''
          },
          top: { //Dialog CSS 中的 margin-top 值
            type: String,
            default: '15vh'
          },
          beforeClose: Function, //关闭前的回调,会暂停 Dialog 的关闭
          center: { //是否对头部和底部采用居中布局
            type: Boolean,
            default: false
          }
        },
    
        data() {
          return {
            closed: false
          };
        },
    
        watch: {
          visible(val) {
            if (val) {
              this.closed = false;
              // Dialog 打开的回调
              this.$emit('open');
              //滚动时,更新弹出框的位置
              this.$el.addEventListener('scroll', this.updatePopper);
              this.$nextTick(() => {
                // 元素的滚动条的垂直位置为0
                this.$refs.dialog.scrollTop = 0;
              });
              //appendToBody为true时,将Dialog插入到body元素上
              if (this.appendToBody) {
                document.body.appendChild(this.$el);
              }
            } else {
              this.$el.removeEventListener('scroll', this.updatePopper);
              if (!this.closed) this.$emit('close');
            }
          }
        },
    
        computed: {
          style() {
            let style = {};
            //如果不是全屏显示Dialog,Dialog的margin-top等于用户设置的top
            if (!this.fullscreen) {
              style.marginTop = this.top;
              if (this.width) {
                style.width = this.width;
              }
            }
            return style;
          }
        },
    
        methods: {
          getMigratingConfig() {
            return {
              props: {
                'size': 'size is removed.'
              }
            };
          },
          handleWrapperClick() {
            //closeOnClickModal为false,则不能通过点击 modal 关闭 Dialog,直接返回
            if (!this.closeOnClickModal) return;
            this.handleClose();
          },
          handleClose() {
            // 关闭前的回调,会暂停 Dialog 的关闭
            if (typeof this.beforeClose === 'function') {
              this.beforeClose(this.hide);
            } else {
              this.hide();
            }
          },
          hide(cancel) {
            if (cancel !== false) {
              this.$emit('update:visible', false);
              this.$emit('close');
              this.closed = true;
            }
          },
          // 这里不知道为什么这么写,没太搞懂
          updatePopper() {
            this.broadcast('ElSelectDropdown', 'updatePopper');
            this.broadcast('ElDropdownMenu', 'updatePopper');
          },
          // Dialog 打开动画结束时的回调
          afterEnter() {
            this.$emit('opened');
          },
          // Dialog 关闭动画结束时的回调
          afterLeave() {
            this.$emit('closed');
          }
        },
    
        mounted() {
          if (this.visible) {
            // rendered这里不是太懂,估计是处理弹出框位置相关的,等后面弄懂后再补充
            this.rendered = true;
            this.open();
            if (this.appendToBody) {
              document.body.appendChild(this.$el);
            }
          }
        },
    
        destroyed() {
          // if appendToBody is true, remove DOM node after destroy
          if (this.appendToBody && this.$el && this.$el.parentNode) {
            this.$el.parentNode.removeChild(this.$el);
          }
        }
      };
    </script>
    
  • 相关阅读:
    Merge Two Sorted Lists
    4Sum
    Letter Combinations of a Phone Number
    3Sum Closest
    3Sum
    Longest Common Prefix
    Roman to Integer
    Integer to Roman
    Container With Most Water
    Regular Expression Matching
  • 原文地址:https://www.cnblogs.com/fangnianqin/p/10044439.html
Copyright © 2011-2022 走看看