封装一:只把弹窗封装成一个单独的组件

1. 弹窗组件 my-dialog.vue

<template>
    <el-dialog title="选择水果" :visible.sync="dialogVisible" width="30%">
        <div>弹窗内容</div>

        <span slot="footer">
            <el-button @click="toggleDialog('dialogVisible', false)">取 消</el-button>
            <el-button type="primary" @click="handleOk">确 定</el-button>
        </span>
    </el-dialog>

</template>

<script>
export default {
    props: {
        visible: Boolean,
    },
    data() {
        return {};
    },
    computed: {
        dialogVisible: {
            get() {
                return this.visible;
            },
            set(val) {
                this.$emit('update:visible', val);
            },
        },
    },
    methods: {
        toggleDialog(key, visible) {
            this[key] = visible;
        },
        handleOk() {},
    },
};
</script>

<style lang="less" scoped>
</style>

2. 点击按钮所在的业务组件

<template>
  <div>
    <el-button type="primary" @click="visible = true">显示弹窗</el-button>
    <MyDialog v-if="visible" :visible.sync="visible"/>
  </div>
</template>

优点:弹窗组件上加v-if,只有弹窗显示的时候才会去执行弹窗组件里的生命周期,而且每次弹窗显示都会执行一般完整的组件生命周期,就不用手动去初始化之前缓存的数据了。

缺点:按钮和弹窗的显示、隐藏功能会跟业务代码耦合在一起,解耦不彻底。

封装二:按钮 + 弹窗 封装在一个组件里

1. 按钮 + 弹窗组件 show-dialog-btn.vue

<template>
  <div style="display: inline-block">
    <slot :show="show"></slot>

    <el-dialog
      title="选择水果"
      :visible.sync="dialogVisible"
      width="30%"
    >
      <el-checkbox-group v-model="checkList">
        <el-checkbox
          v-for="it in optionList"
          :key="it.value"
          :label="it.value"
        >{{it.text}}</el-checkbox>
      </el-checkbox-group>
  
      <span slot="footer">
        <el-button @click="toggleDialog('dialogVisible', false)">取 消</el-button>
        <el-button type="primary" @click="">确 定</el-button>
      </span>
    </el-dialog>
  </div>
</template>
  
<script>
  export default {
    data () {
      return {
        ...this.getInitialData(),
        dialogVisible: false,
      };
    },
    created () {
      this.init();
    },
    methods: {
      init() {
        this.optionList = [
          { value: 'apple', text: '苹果' },
          { value: 'orange', text: '橘子' },
          { value: 'pear', text: '梨' },
        ];
      },
      show() {
        this.toggleDialog('dialogVisible', true);
      },
      toggleDialog(key, visible) {
        this[key] = visible;
      },
      // 获取需要初始化的数据
      getInitialData() {
        return {
          checkList: [],
        }
      },
    },
    watch: {
      dialogVisible(val) {
        if (!val) return;
        Object.assign(this, this.getInitialData());
      }
    },
  }
</script>

2. 使用组件

<ShowDialogBtn>
  <template #default="{show}">
    <a @click="show">显示弹窗</a>
  </template>
</ShowDialogBtn>

优点:1. 按钮 + 弹窗的整个组件跟业务组件解耦的比较干净。

           2. 按钮通过 slot 传入,看业务代码的时候也很好知道这个是什么按钮。

缺点:1. 要在组件显示或关闭时手动初始化之前的数据。

           2. 弹窗还没有显示,就要去执行组件的生命周期,有时候用户并不会去打开弹窗,但也会去执行弹窗里面的生命周期,造成不必要的计算。

还有一种按钮 + 弹窗封装在一起的方法是,按钮不用 slot 传入,而是直接写在组件里面:

<template>
  <span>
    <a @click="show">显示弹窗</a>
    <el-dialog
      title="选择水果"
      :visible.sync="dialogVisible"
      width="30%"
    >
      <el-checkbox-group v-model="checkList">
        <el-checkbox
          v-for="it in optionList"
          :key="it.value"
          :label="it.value"
        >{{it.text}}</el-checkbox>
      </el-checkbox-group>
  
      <span slot="footer">
        <el-button @click="dialogVisible = false">取 消</el-button>
        <el-button type="primary" @click="dialogVisible = false">确 定</el-button>
      </span>
    </el-dialog>
  </span>
  </template>
<ShowDialogBtn/>

优点:跟业务代码解耦的最彻底。

缺点:1. 一眼看不出这是哪个功能按钮,还要看一下组件里的代码。

           2. 要在组件显示或关闭时手动初始化data数据。

Logo

前往低代码交流专区

更多推荐