vue2封装对话框el-dialog组件

文章介绍了如何在Vue项目中对ElementUI的el-dialog对话框进行二次封装,并展示了父子组件间的通信,包括表单验证和异步操作在权限管理中的应用。

为了页面代码更加整洁我们可以将组件进行二次封装使用,以下是我封装的element中el-dialog对话框组件。

1.写好子组件对话框

<template>
  <el-dialog
    :title="showTitle"
    width="50%"
    :visible="dialogShow"
    @close="handleClose"
  >
    <el-form ref="formList" label-width="80px" :model="formList" :rules="rules">
      <el-form-item label="权限名称" prop="name">
        <el-input v-model="formList.name" />
      </el-form-item>
      <el-form-item label="权限标识" prop="code">
        <el-input v-model="formList.code" />
      </el-form-item>
      <el-form-item label="权限描述" prop="description">
        <el-input v-model="formList.description" />
      </el-form-item>
      <el-form-item label="开启">
        <el-switch
          v-model="formList.enVisible"
          active-value="1"
          inactive-value="0"
        />
      </el-form-item>
      <el-row type="flex" justify="center">
        <el-button type="primary" @click="addOk">确定</el-button>
        <el-button @click="handleClose">取消</el-button>
      </el-row>
    </el-form>
  </el-dialog>

</template>

<script>
import { AddlPermission, EditlPermission, DetailPermission, GetPermission } from '@/api/permission'
export default {
  props: {
    dialogShow: {
      type: Boolean,
      default: true
    },
    type: {
      type: Number,
      default: null
    },
    pid: {
      type: Number,
      default: null
    }
  },
  data() {
    return {
      formList: {
        name: '',
        code: '',
        description: '',
        enVisible: 0

      },
      rules: {
        name: [
          { required: true, message: '请输入权限名称', triggle: ['blur'] },
          {
            validator: async(rule, value, callback) => {
              let result = await GetPermission()
              if (this.formList.id) {
                result = result.filter(item => item.id !== this.formList.id)
              }
              if (result.some(item => item.code === value)) {
                callback(new Error('已经存在相同的权限标识'))
              } else {
                callback()
              }
            }
          }
        ],
        code: [
          { required: true, message: '请输入权限名称', triggle: ['blur'] },
          {
            validator: async(rule, value, callback) => {
              let result = await GetPermission()
              if (this.formList.id) {
                result = result.filter(item => item.id !== this.formList.id)
              }
              if (result.some(item => item.code === value)) {
                callback(new Error('已经存在相同的权限标识'))
              } else {
                callback()
              }
            }
          }
        ],
        description: [
          { required: true, message: '请输入权限名称', triggle: ['blur'] }
        ]
      }
    }
  },
  computed: {
    showTitle() {
      return this.formList.id ? '编辑权限点' : '新增权限点'
    }
  },
  methods: {
    // 点击关闭需要做的事情1.表单清空;2.移出校验结果;3.通知父组件关闭对话框。
    handleClose() {
      this.formList = {
        name: '',
        code: '',
        description: '',
        value: true
      }
      this.$refs.formList.resetFields()
      // 给父元素传值,关闭对话框
      this.$emit('updata:dialogShow', false)
    },
    // 对话框确定功能---------------------
    async addOk() {
      // 表单校验通过再执行之后的
      await this.$refs.formList.validate()
      let msg = '新增'
      if (this.formList.id) {
        msg = '编辑'
        // 编辑
        await EditlPermission(this.formList)
      } else {
        // 添加
        await AddlPermission({ ...this.formList, type: this.type, pid: this.pid })
      }
      // 通知父组件更新页面
      this.$emit('updatePermission')
      // 添加成功提示信息
      this.$message.success(`${msg}成功`)
      // 关闭对话框
      this.handleClose()
    },
    // 编辑功能,数据回显
    async DetailPermission(id) {
      const res = await DetailPermission(id)
      this.formList = res
    }

  }
}
</script>
<style>
</style>

2.父组件引用子组件并进行传值

<template>
  <div class="container">
    <div class="app-container">
      <el-button type="primary" size="mini" @click="AddPermission(0,1)">添加权限</el-button>
      <el-table
        :data="permissionlist"
        row-key="id"
        style="width: 100%"
        default-expand-all
      >
        <el-table-column prop="name" label="名称" />
        <el-table-column prop="code" label="标识" />
        <el-table-column prop="description" label="描述" />
        <el-table-column prop="" label="操作" width="200">
          <template #default="{row}">
            <el-button v-if="row.type===1" type="text" size="mini" @click="AddPermission(row.id,2)">添加</el-button>
            <el-button type="text" size="mini" @click="editPermission(row.id)">编辑</el-button>
            <el-button type="text" size="mini" @click="Delpermissionlist(row.id)">删除</el-button>
          </template>
        </el-table-column>
      </el-table>
      <!-- 对话框-------------- -->
      <Addpermission
        ref="dialog"
        :dialog-show="dialogShow"
        :type="type"
        :pid="pid"
        @updata:dialogShow="dialogShow=$event"
        @updatePermission="GetPermissionlist"
      />
    </div>
  </div>
</template>
<script>
import { GetPermission, DelPermission } from '@/api/permission'
import { transListTotreeData } from '@/utils/index'
import Addpermission from './component/Addpermission.vue'
export default {
  name: 'Permission',
  components: {
    Addpermission
  },
  data() {
    return {
      permissionlist: [], // 权限列表
      dialogShow: false,
      type: null, // 添加类型一级还是二级
      pid: null // 当前行的id
    }
  },
  created() {
    this.GetPermissionlist()
  },
  methods: {
    // 初始获取列表渲染--------------------------
    async GetPermissionlist() {
      const res = await GetPermission()
      // 转成树形数组
      this.permissionlist = transListTotreeData(res, 0)
    },
    // 删除功能----------------------------------
    async Delpermissionlist(id) {
      this.$confirm('确定删除吗?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(async() => {
        // 调取删除接口,并重新渲染,提示成功信息
        await DelPermission(id)
        this.GetPermissionlist()
        this.$message({
          type: 'success',
          message: '删除成功!'
        })
      }).catch(() => {
        this.$message({
          type: 'info',
          message: '已取消删除'
        })
      })
    },
    // 添加功能--------------------------------
    async AddPermission(pid, type) {
      this.dialogShow = true
      this.type = type
      this.pid = pid
    },
    // 编辑功能---------------------------------
    async editPermission(id) {
      //  先调用子组件的方法在编辑的时候数据回显,在执行弹框显示
      await this.$refs.dialog.DetailPermission(id)
      this.dialogShow = true
    }
  }
}
</script>
<style lang="scss" scoped>
.app-container{
  padding:10px;
}
</style>

3.图片解说

在这里插入图片描述

### 封装 `el-dialog` 组件的最佳实践 在 Vue3 中封装 Element Plus 的 `el-dialog` 组件时,最佳实践应注重代码的可维护性和复用性。以下是详细的说明: #### 1. 使用 `<script setup>` 提高开发效率 Vue3 引入了 `<script setup>` 语法糖,简化了组件编写流程。通过该方式可以直接声明响应式变量和方法,无需显式返回对象[^1]。 ```vue <template> <el-dialog v-model="visible" :title="title"> <slot></slot> <!-- 插槽用于动态内容 --> <template #footer> <span class="dialog-footer"> <el-button @click="close">取消</el-button> <el-button type="primary" @click="confirm">确定</el-button> </span> </template> </el-dialog> </template> <script setup> import { ref } from 'vue'; const props = defineProps({ title: { type: String, default: '默认标题' } }); const visible = ref(false); function open() { visible.value = true; } function close() { visible.value = false; } function confirm() { // 执行确认操作 console.log('执行确认'); close(); } defineExpose({ open, close }); </script> ``` 此代码片段展示了如何利用 `<script setup>` 和组合 API 来快速构建一个基础的 `el-dialog` 封装[^1]。 --- #### 2. 支持插槽增强灵活性 为了使封装后的组件更加通用,支持多种场景下的需求,推荐使用 Vue 的插槽机制。例如,在对话框主体部分提供默认插槽,并允许开发者自定义按钮区域的行为[^1]。 ```html <!--组件:CustomDialog.vue --> <template> <el-dialog v-model="visible" :title="props.title"> <slot name="content"></slot> <!-- 自定义内容 --> <template #footer> <slot name="footer"> <div class="default-footer"> <el-button @click="close">取消</el-button> <el-button type="primary" @click="confirm">确定</el-button> </div> </slot> </template> </el-dialog> </template> ``` 这样设计的好处在于父级可以自由决定是否覆盖默认行为或样式。 --- #### 3. 方法暴露提升交互能力 借助 `defineExpose()` 函数对外公开内部逻辑(如打开/关闭窗口),便于外部调用控制生命周期[^4]。 ```javascript // 定义 expose 方法供外界访问 defineExpose({ open, close }); ``` 当其他模块需要触发这些功能时只需简单引用即可完成操作[^4]。 --- #### 4. 数据传递与双向绑定优化 如果希望实现更复杂的参数交换,则可通过事件监听器配合 emit 实现父子间通信[^2]。 ```javascript emits: ['update:modelValue', 'submit'], methods: { submitForm(formData) { this.$emit('submit', formData); }, } ``` 同时也可以考虑采用 `.sync` 修改符或者新的 `v-model` 方案来同步状态变化[^2]. --- #### 5. 错误处理及用户体验改进 针对某些特殊情况下可能存在的问题(比如点击遮罩层时不期望完全退出等情况),需提前做好预防措施并给出合理提示[^4]。 另外还可以加入一些额外配置项让用户能够灵活调整细节设置,像宽度高度等属性都应该是可控范围内的选项之一[^3]。 --- ### 总结 综上所述,在 Vue3 下对 element plus 的 el-dialog 进行二次封装主要围绕以下几个方面展开工作:一是充分利用框架特性减少冗余代码量;二是充分考虑到实际应用场景中的多样性需求从而提高组件适应力;三是注意保持良好的编码习惯以便后续扩展升级变得更容易实施^. ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值