封装elementui弹出框el-dialog

6,057 阅读1分钟

场景

vue + elementUi框架做后台管理系统时,需要使用弹出框 新增/编辑 内容时,可以将el-dialog二次封装,使代码简洁易维护。

子组件 addDialog.vue:

<template>
  <div>
    <el-dialog
      title="新增"
      :visible.sync="show"
      @close="$emit('update:visible', false)"
    >
      <el-form>
        <el-form-item label="姓名">
          <el-input v-model="name" />
        </el-form-item>
      </el-form>
    </el-dialog>
  </div>
</template>
<script>
    export default {
        props: {
            visible: {
              type: Boolean,
              default: false
            }
          },
          data() {
            return {
              name: ' ',
              show: this.visible,
            };
          },
          watch: {
            visible(val) {
              this.show = val;
            }
          }
      }
</script>

父组件中使用:

<template>
    <div>
        <button @click="handleAdd">打开/关闭</button>
        <addDialog :visible.sync="addshow" />
    </div>
</template>
<script>
    import addDialog from "./addDialog.vue";
    export default {
        components: { addDialog },
        data() {
          return {
            addshow: false,
          };
        },
        methods: {
          handleAdd() {
            this.addshow = true;
          }
        }
  };
</script>

在子组件中不能直接使用 props 的 visible来控制显示与隐藏,需要一个中间值 show 来控制。因为 el-dialog 关闭时会设置 visible 的值,子组件直接更改 props 的值会报错 [Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value. Prop being mutated: "visible"

所以,实现的思路是 父组件传递的参数添加 .sync 修饰,子组件中关闭弹框时使用 $emit('update:visible', false) 这样更改父组件中传递的 visible 的值,子组件中watchvisible改变,就改变中间值show达到关闭的目的。

另外 <addDialog :visible.sync="addshow" />.sync 是下面代码的语法糖

<addDialog
:visible="addshow"
@update:visible="newVal => addshow = newVal"
/>

有 新增/修改 使用同一个弹出框的需求时,需要动态修改dialog中的内容,可以给子组件传递其他参数,在子组件watch中监听。之所以用watch监听,是因为子组件渲染只会执行一次created生命周期,如果非要将更改内容写在created中,就要配合 v-if 使用,将子组件用 v-if 包裹起来,每次都重新加载子组件,此时可以达到动态修改dialog内容的需求,但是el-dialog弹出的动画效果会消失。

更新:Vue3与Element plus

最新版Element Plus V2.9.8版本,dialog组件提供了Exposes handleClose 方法,关闭弹窗时不要用 emits 或直接改变visible的值,改用handleClose关闭弹窗,这样的话结合 v-if使用,关闭动画就不会消失了。

  <el-dialog
    v-model="visibleInner"
    title="新建"
    width="720px"
    ref="dialogRef"
    destroy-on-close
    :close-on-click-modal="false"
    @closed="关闭之后的操作()"
  >
  // ...
  </el-dialog>

const dialogRef = ref(null);
// 取消按钮
function handleCancel() {
  // visibleInner.value = false; // 这样关闭没有关闭动画
  // emits("update:visible", false); // 这样关闭没有关闭动画
  dialogRef.value.handleClose();
}

只有使用v-if控制自己封装的弹窗组件时才需要考虑动画问题,其他情况动画都是正常的。