• Vue 之 父组件给子组件的传参的另类方式实现自定义弹窗组件


    父组件向子组件传参

    详情查看:Vue 之 组件之间的传值通信(多种方法,简洁而不失重点)

    • 传统方式:通过属性 props 传参
    • 特殊方式:通过 ref 调用子组件方法,然后通过方法传参

    这里重点说明一下特殊方式,场景的不同决定传参的方式合适与否

    比如自定义弹窗组件,需要的动态参数可能有:确定按钮的text、取消按钮的text、弹窗的文本内容、弹窗的title;

    • 传统方式传参在某种特殊业务下可能不是那么完美:如果在一个页面中可能有操作的不同,不同的操作可能弹窗的数据不一样,这个时候如果使用 props 传参的话,一个弹窗组件4个属性,2个组件就8个……,这么下去的话,在当前vue 页面 data绑定的数据变量就可能有很多了;
    • 而如果是通过ref 调用子组件的方法传参的话就方便很多了,直接在需要调用弹窗的方法里面自定义一个对象,把需要动态改变的参数塞到这个对象里面,在子组件中对传过来的参数进行接收,这样既满足了组件的复用性,又满足了组件的灵活性,并且调用组件的父组件也不用定义那么多数据变量了。


    自定义弹窗组件

    • 自定义弹窗代码如下:
    <template>
      
      <div class="dialog-container" v-if="isShow" @click.stop>
        <div class="dialog-box">
          <div class="dialog-title">{{ dialogData.title }}div>
          <div class="dialog-message">{{ dialogData.message }}div>
          <div class="dialog-btns">
            <el-button class="btn" @click="cancel">{{ dialogData.cancelText }}el-button>
            <el-button type="primary" class="confirm-btn btn" @click="confirm">{{ dialogData.confirmText }}el-button>
          div>
        div>
      div>
    template>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    export default {
      data() {
        return {
          isShow: false, // 是否显示弹窗
          // 弹窗的默认内容
          dialogData: {
            title: '提示', // 弹窗标题
            message: '请确认,是否提交!?', // 弹窗内容message
            cancelText: '取消', // 弹窗的取消按钮文字
            confirmText: '确认', // 弹窗的确认按钮文字
          },
          defaultDialogData: {}, // 弹窗的默认内容
          // 弹窗确定的回调,当然这个也可以不用,直接用按钮的回调传参即可btnCallback
          confirmCallback: null,
          // 弹窗取消的回调,当然这个也可以不用,直接用按钮的回调传参即可btnCallback
          cancelCallback: null,
          // 弹窗按钮的回调
          btnCallback: null,
        }
      },
      methods: {
        open(dialogData) {
          // 保存初始的弹窗数据
          this.defaultDialogData = JSON.parse(JSON.stringify(this.dialogData))
          // 将传过来的弹窗数据赋值给当前数据
          this.dialogData = Object.assign(this.dialogData, dialogData)
          this.isShow = true
          // 这里定义返回一个 promise
          return new Promise((resolve, reject) => {
            // 方式一
            // this.confirmCallback = resolve
            // this.cancelCallback = reject
            // 方式二
            this.btnCallback = resolve
          })
        },
        close() {
          // 重置弹窗相关数据
          this.dialogData = JSON.parse(JSON.stringify(this.defaultDialogData))
          this.isShow = false
        },
        confirm() {
          // 方式一
          // if (this.confirmCallback) {
          //   this.confirmCallback('confirm')
          // }
          // 方式二
          if (this.btnCallback) {
            this.btnCallback('confirm')
          }
          this.close()
        },
        cancel() {
          // 方式一
          // if (this.cancelCallback) {
          //   this.cancelCallback('cancel')
          // }
          // 方式二
          if (this.btnCallback) {
            this.btnCallback('cancel')
          }
          this.close()
        },
      },
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 调用自定义弹窗的父组件,就不写那么多东西了,简单两个按钮模拟一下
      在这里插入图片描述
    <template>
      <div>
        <el-button type="primary" @click="handleSubmit">提交el-button>
        <el-button type="warning" @click="handleDelete">删除el-button>
    
        <ConfirmDialogVue ref="ConfirmDialog" />
      div>
    template>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    import ConfirmDialogVue from '@/components/ConfirmDialog/ConfirmDialog.vue'
    export default {
      data() {
        return {}
      },
      components: {
        ConfirmDialogVue,
      },
      methods: {
        async handleSubmit() {
          // 方式一
          // try {
          //   const res = await this.$refs.ConfirmDialog.open()
          //   if (res) {
          //     console.log('提交-确定-', res)
          //     // 调接口啥的
          //     // doing
          //   }
          // } catch (rej) {
          //   console.log('提交-取消-', rej)
          //   // 取消的时候你如果想做点什么可以这里操作
          // }
    
          // 方式二,就不用 try catch了
          const res = await this.$refs.ConfirmDialog.open()
          if (res) {
            if (res == 'confirm') {
              console.log('提交-确定-', res)
              // 调接口啥的
              // doing
            } else if (res == 'cancel') {
              console.log('提交-取消-', res)
              // 取消的时候你如果想做点什么可以这里操作
            }
          }
        },
        handleDelete() {
          const dialogData = {
            message: '请确认,是否删除!?',
            confirmText: '删除',
          }
          // 方式一
          // this.$refs.ConfirmDialog.open(dialogData)
          //   .then(res => {
          //     console.log('删除-确定-', res)
          //     // 调接口啥的
          //     // doing
          //   })
          //   .catch(rej => {
          //     console.log('删除-取消-', rej)
          //     // 取消的时候你如果想做点什么可以这里操作
          //   })
    
          // 方式二
          this.$refs.ConfirmDialog.open(dialogData).then(res => {
            if (res == 'confirm') {
              console.log('删除-确定-', res)
              // 调接口啥的
              // doing
            } else if (res == 'cancel') {
              console.log('删除-取消-', res)
              // 取消的时候你如果想做点什么可以这里操作
            }
          })
        },
      },
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 效果如下(样式有点难看暂请忽略……)
      在这里插入图片描述

    代码中使用了两种不同的方式解决弹窗按钮回调的问题,具体使用情况视情况而定。


    如有不足,望大家多多指点! 谢谢!

  • 相关阅读:
    靶场战神为何会陨落?
    有什么免费python安装包?
    计算机里的刻度:时钟和步进器
    第58节——redux-toolkit中的createAsyncThunk
    几种常用XML文档解析方案的使用操作
    vue3学习-1配置以及启动
    Java 基础之锁
    LeetCode每日一题(2012. Sum of Beauty in the Array)
    通过jsoup抓取谷歌商店评分
    【GNN报告】华为诺亚实验室周敏:曲率视角下的图数据建模与分析
  • 原文地址:https://blog.csdn.net/Zhuangvi/article/details/126808964