组件的二次封装(弹框为例)

实现思路(核心)

  • 封装时可借助ekement-ui(样式)
  • 利用好 $listener, $attr隔代传值,在组件中调用属性或方法
  • slot插槽的运用

$listener, $attr的详细用法:
https://blog.csdn.net/lqlq54321/article/details/106389054
*首次封装

<template>
  <div v-if="show">
    <div :class="{'base-dialog--mask': true, 'base-dialog--mask--white': styleType === 'white'}">
      <div class="base-dialog--content" :style="width&&{width:width}">
        <div class="base-dialog--header" :style="titleHeight&&{height:titleHeight, lineHeight: titleHeight}">
          <slot name="header">
            {{title}}
            <br ref="defaultFocus" tabindex="0" />
            <div class="base-dialog--header-close" @click="cancel" :style="iconSize&&{height:iconSize, width: iconSize}"></div>
          </slot>
        </div>
        <div class="base-dialog--main">
          <slot></slot>
        </div>
        <div v-if="!nofooter" class="base-dialog--footer">
          <slot name="footer">
            <template v-if="isConfirmDialog">
              <BaseButton class="del" @click="btnClick">{{submitBtnText}}</BaseButton>
              <BaseButton type="plain" class="cancel" @click="cancel">取消</BaseButton>
            </template>
            <template v-else>
              <BaseButton class="know" @click="closeDialog">我知道了</BaseButton>
            </template>
          </slot>
        </div>
      </div>
    </div>
  </div>
</template>
export default {
  inheritAttrs: false,
  components: {
    BaseButton,
  },
  props: {
    show: {
      type: Boolean,
      default: false,
    },
    title: String,
    width: String,
    submitBtnText: {
      type: String,
      default: "确定",
    },
    failBtnText: {
      type: String,
      default: "取消",
    },
    dialogType: {
      type: String,
      default: "confrim",
    },
    nofooter: {
      type: Boolean,
      default: false,
    },
  },
  computed: {
    isConfirmDialog() {
      return this.dialogType === "confrim";
    },
  },
  watch: {
    show: {
      handler(val) {
        if (val) {
          this.$emit("open");
          this.$nextTick(() => {
            if (!this.isConfirmDialog) {
              this.focus();
            } else {
              this.$refs.defaultFocus.focus();
            }
          });
        }
      },
      immediate: true,
    },
  },
  mounted() {
    const body = document.body;
    if (body.append) {
      body.append(this.$el);
    } else {
      body.appendChild(this.$el);
    }
  },
  destroyed() {
    this.$el.remove();
  },
  methods: {
    btnClick() {
      this.$emit("btnClick");
      this.closeDialog();
    },
    cancel() {
      this.$emit("cancel");
      this.closeDialog();
    },
    closeDialog() {
      this.$emit("close");
      this.$emit("update:show", false);
    },
    focus() {
      this.$nextTick(() => {
        deepRun(this.$refs.firstButton, "focus");
      });
    },
  },
};

注释:BaseButton为一个组件
二次封装

<template>
  <BaseDialog class="normal-dialog" ref="baseDialog" :show="show" v-bind="$attrs" v-on="$listeners">
    <div class="normalDiaglogContent">
      <slot></slot>
    </div>
  </BaseDialog>
</template>
import BaseDialog from "./BaseDialog.vue";
export default {
  components: { BaseDialog },
  inheritAttrs: false,
  props: { show: Boolean },
  watch: {
    show(val) {
      if (val) {
        this.$nextTick(() => {
          this.focus();
        });
      }
    }
  },
  methods: {
    focus() {
      this.$refs.baseDialog.focus();
    }
  }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值