element-ui dialog 封装

7,364 阅读2分钟

要实现点击某个按钮就能弹出一个对话框 Element 文档中是这样写的

<el-button type="text" @click="dialogVisible = true">点击打开 Dialog</el-button>
<el-dialog
  title="提示"
  :visible.sync="dialogVisible"
  width="30%"
  :before-close="handleClose">
  <span>这是一段信息</span>
  <span slot="footer" class="dialog-footer">
    <el-button @click="dialogVisible = false">取 消</el-button>
    <el-button type="primary" @click="dialogVisible = false">确 定</el-button>
  </span>
</el-dialog>
<script>
  export default {
    data() {
      return {
        dialogVisible: false
      };
    },
    methods: {
      handleClose(done) {
        this.$confirm('确认关闭?')
          .then(_ => {
            done();
          })
          .catch(_ => {});
      }
    }
  };
</script>

但是这只是把对话框的代码写在一个页面里的时候可以这样写,在日常的开发中,如果对话框弹出的是一个表单或者更复杂的业务需求的时候,把对话框写在一个页面里就会使代码显得特别冗余,维护起来特别麻烦。 最好是把每个dialog 单独封装成一个组件,在页面中引入对应的弹窗组件即可。为了能使父组件可以打开弹窗,弹窗组件得暴露属性给父组件,参考下面的代码实现

// 弹窗组件
<template>
    <el-dialog title="示例弹窗" :visible.sync="dialogVisible">
        <div class="dialog-content">
        </div>
        <span slot="footer" class="dialog-footer">
            <el-button>取 消</el-button>
            <el-button type="primary">确 定</el-button>
        </span>
    </el-dialog>
</template>
<script>
export default {
    name: 'dialogExample',
    data() {
        return {
            
        }
    },
    props: {
        dialogVisible: {
            type: Boolean,
            default: false,
        },
    },
    methods: {
       
    },
}
</script>

// 父组件
<dialog-example :dialog-visible="showDialog"></dialog-example>
<el-button @click="showDialog=true">打开弹窗</el-button>

现在,在父组件中点击按钮,可以正常打开弹窗,但是现在无法关掉弹窗,弹窗组件中使用了:visible.sync="dialogVisible",而 dialogVisible 是父组件传递的值,弹窗组件中不能直接修改dialogVisible,直接修改,控制台中会提示有错误,子组件不能直接修改父组件传递下来的值,所以需要通过事件的方式,通知父组件,如下面的代码所示

// 弹窗组件
<template>
    <el-dialog title="示例弹窗" :visible.sync="dialogVisible">
        <div class="dialog-content">
        </div>
        <span slot="footer" class="dialog-footer">
            <el-button @click="cancel">取 消</el-button>
            <el-button type="primary">确 定</el-button>
        </span>
    </el-dialog>
</template>
<script>
export default {
    name: 'dialogExample',
    data() {
        return {
            
        }
    },
    props: {
        dialogVisible: {
            type: Boolean,
            default: false,
        },
    },
    methods: {
       cancel() {
            this.$emit('dialog-cancel');
       }
    },
}
</script>

// 父组件
<dialog-example :dialog-visible="showDialog" @dialog-cancel="showDialog=false"></dialog-example>
<el-button @click="showDialog=true">打开弹窗</el-button>

这样,点击关闭弹窗,通过事件通知的方式,让父组件修改 showDialog 的值,即可关闭弹窗。 但是,事情,还没有到此结束,因为,弹窗右上角会有一个 close按钮,点击的时候,发现控制台仍然会报错。这是因为,:visible.sync 使用了 sync 修饰符,点击close按钮的回调中,触发了dialogVisible的修改,回到了前面提到的情况。查看 文档的中的详细说明,发现👇 before-close 关闭前的回调,会暂停 Dialog 的关闭 function(done),done 用于关闭 Dialog 所以,只要加个before-close,里面不要调用 done,即可

// 弹窗组件
<template>
    <el-dialog title="示例弹窗" :visible.sync="dialogVisible" :before-close="cancel">
        <div class="dialog-content">
        </div>
        <span slot="footer" class="dialog-footer">
            <el-button @click="cancel">取 消</el-button>
            <el-button type="primary">确 定</el-button>
        </span>
    </el-dialog>
</template>
<script>
export default {
    name: 'dialogExample',
    data() {
        return {
            
        }
    },
    props: {
        dialogVisible: {
            type: Boolean,
            default: false,
        },
    },
    methods: {
       cancel() {
            this.$emit('dialog-cancel');
       }
    },
}
</script>

// 父组件
<dialog-example :dialog-visible="showDialog" @dialog-cancel="showDialog=false"></dialog-example>
<el-button @click="showDialog=true">打开弹窗</el-button>

至此,一个完美的 dialog 组件封装完毕