vue3父子组件交互问题,哪种写法更优,为什么?

作者站长头像
站长
· 阅读数 5

描述:在父组件引入子组件,子组件是一个弹窗,两种方式都可实现,哪种写法更好,为什么?方式1是在父组件定义控制子组件是否打开的参数以及传递的参数,在子组件进行监听赋值方式2是用ref操作子组件方法

方式一:

父组件
<template>
   <el-button
     text
      type="warning"
      icon="CircleCheck"
     @click="handleSetRole(scope.row)"
   >分配角色</el-button>
   <AssigningRoles
      :is-open="isOpen"
      :params-data="paramsData"
      @get-role-result="getRoleResult">
   </AssigningRoles>
</template>
<script setup>
    const isOpen = ref(false) // 控制子组件是否显示
    const paramsData = ref({}) // 其他数据传递
    // 方法
    const handleSetRole = () => {
       isOpen.value = true
       paramsData.value = {
           account: row.account,
           nickname: row.nickname
        }
     }
     分配角色回调
     const getRoleResult = (flag) => {
         isOpen.value = false
         flag && getList()
      }
</script>

子组件
<template>
 <el-dialog
    title="分配角色"
    v-model="isOpen"
    width="500px"
    append-to-body
    :close-on-click-modal="false"
    @close="cancel">
    <el-form>
        <el-input v-model="form.account"></el-input>
        ....
     </el-form>
     <template #footer>
      <el-button text @click="cancel">取消</el-button>
      <el-button type="primary" @click="submitForm">确定</el-button>
    </template>
 </el-dialog>
</template>
<script setup>
    const { proxy } = getCurrentInstance()
    const form = reactive({
       account: '',
       nickname: '',
       role: []
    })
   // props
    const props = defineProps({
      isOpen: {
        type: Boolean,
        default: false
      },
      paramsData: {
        type: Object,
        default: () => ({})
      }
    })
    const { isOpen } = toRefs(props)
    // watch监听
    watch(
      () => props.paramsData,
      (newVal, oldVal) => {
        form.account = newVal.account
        form.nickname = newVal.nickname
        form.role = []
      },
      { immediate: true, deep: true }
    )

    // 子组件传父组件emit
    const emit = defineEmits(['get-role-result'])
    // 取消
    const cancel = () => {
      emit('get-role-result', false)
    }
    // 提交
    const submitForm = () => {
      assignUserRole(form.value).then((res) => {
        proxy.$modal.msgSuccess('分配成功')
        emit('get-role-result', true)
      })
    }
</script>

方式二:

父组件
<template>
   <el-button
     text
      type="warning"
      icon="CircleCheck"
     @click="handleSetRole(scope.row)"
   >分配角色</el-button>
   <AssigningRoles
      ref="editFormRef"
      @getEditResult="editEvent">
   </AssigningRoles>
</template>
<script setup>
    const editFormRef = ref(null)
    // 分配角色
    function handleSetRole(row) {
      proxy.$refs.editFormRef.openEditForm(row)
    }
    // 分配角色回调
    function editEvent() {
      getList()
    }
</script>

子组件
<template>
 <el-dialog
    title="分配角色"
    v-model="editVisible.visible"
    width="500px"
    append-to-body
    :close-on-click-modal="false"
    @close="cancel">
    <el-form>
        <el-input v-model="form.account"></el-input>
        ....
     </el-form>
     <template #footer>
      <el-button text @click="cancel">取消</el-button>
      <el-button type="primary" @click="submitForm">确定</el-button>
    </template>
 </el-dialog>
</template>
<script setup>
    const { proxy } = getCurrentInstance()
    // 定义form表单数据
    const form = reactive({
      account: '',
      nickname: '',
      role: []
    })
    // 编辑窗口参数
    const editVisible = reactive({
      visible: false // 窗口开关
    })
    const emit = defineEmits(['getEditResult'])
    const openEditForm = (data) => {
      form.account = data.account
      form.nickname = data.nickname
      form.role = []
      editVisible.visible = true
    }
    // 取消
    const cancel = () => {
      editVisible.visible = false
    }
    // 提交
    const submitForm = () => {
      assignUserRole(form.value).then((res) => {
        proxy.$modal.msgSuccess('分配成功')
        editVisible.visible = false
        emit('getEditResult')
      })
    }

    defineExpose({ openEditForm })

</script>
回复
1个回答
avatar
test
2024-06-28

一种是状态控制(响应式),一种是直接控制(命令式)

对于 Vue 来说,推荐使用响应式(本来 Vue 设计就是数据触发呈现变化的)

但是有些组件确实控制性要求较强,需要主动控制的,使用 ref 处理会方便一些。不过不建议使用 ref 来直接修改数据。

回复
likes
适合作为回答的
  • 经过验证的有效解决办法
  • 自己的经验指引,对解决问题有帮助
  • 遵循 Markdown 语法排版,代码语义正确
不该作为回答的
  • 询问内容细节或回复楼层
  • 与题目无关的内容
  • “赞”“顶”“同问”“看手册”“解决了没”等毫无意义的内容