vue.js

关注公众号 jb51net

关闭
首页 > 网络编程 > JavaScript > javascript类库 > vue.js > vue3父组件和子组件传值

vue3父组件和子组件如何传值实例详解

作者:湘锅锅

近期学习vue3的父子组件之间的传值,发现跟vue2.x的父子组件之间的传值并没有太大的区别,下面这篇文章主要给大家介绍了关于vue3父组件和子组件如何传值的相关资料,需要的朋友可以参考下

1.父组件打开子组件的的dialog组件

🕒新建一个vue文件命名为test

🕒然后咱们直接从官网CV一个带有表单的dialog组件如下

 //子组件
<template>
  <el-dialog v-model="dialogFormVisible" title="Shipping address">
    <el-form :model="form">
      <el-form-item label="Promotion name" :label-width="formLabelWidth">
        <el-input v-model="form.name" autocomplete="off" />
      </el-form-item>
      <el-form-item label="Zones" :label-width="formLabelWidth">
        <el-select v-model="form.region" placeholder="Please select a zone">
          <el-option label="Zone No.1" value="shanghai" />
          <el-option label="Zone No.2" value="beijing" />
        </el-select>
      </el-form-item>
    </el-form>
    <template #footer>
      <span class="dialog-footer">
        <el-button @click="dialogFormVisible = false">Cancel</el-button>
        <el-button type="primary" @click="dialogFormVisible = false"
        >Confirm</el-button
        >
      </span>
    </template>
  </el-dialog>
</template>
 
<script setup>
  import { reactive, ref } from "vue";
 
  const formLabelWidth = '140px'
 
  const form = reactive({
    name: '',
    region: '',
    date1: '',
    date2: '',
    delivery: false,
    type: [],
    resource: '',
    desc: '',
  })
 
</script>
 
<style scoped>
  .el-button--text {
    margin-right: 15px;
  }
  .el-select {
    width: 300px;
  }
  .el-input {
    width: 300px;
  }
  .dialog-footer button:first-child {
    margin-right: 10px;
  }
</style>

👫父组件就只需要一个按钮  然后加上咱们的点击事件

<template>
  <el-button type="primary" @click="handlerDialog"
  >添加用户
  </el-button>
  <test />
</template>
 
<script setup>
  import { reactive, ref } from "vue";
  import test from './test'
 
  const dialogFormVisible = ref(false)
 
  const handlerDialog = () => {
    dialogFormVisible.value = true
  }
</script>
 
<style scoped>
 
</style>

然后这个时候发现 弹窗怎么点就是出不来

 注意原因就是咱们的 dialogFormVisible.value值还没传给子组件 所以是打不开的

这个时候就要用到v-model进行数据绑定

所以父组件要进行修改 在test这里加上如下内容

<test v-model="dialogFormVisible"
        v-if="dialogFormVisible"/>

同样子组件也要修改 这里注意 是不能用v-model的  虽然官网的默认自带v-model     

但我们要作为子组件的话 vue3子组件是不能用v-model和父组件进行双向绑定的

那该怎么实现父子组件进行数据传递呢 咱们慢慢道来 咱们先实现父组件如何把dialogFormVisible的值传给子组件

其实很简单 在官网给的文档里面有这一行

017acdcf82af423da863e2c5be538e96.png

model-value 单向数据绑定

直接拿来CV到咱们的子组件上去

 <el-dialog :model-value="dialogFormVisible" title="Shipping address">

然后再去测试一下 可以了!!!

d67fa7a2e4e34215a1863e1186045c42.png

 2.父组件关闭子组件的的dialog组件

b0778dd930864520baab9d7ae80d7250.png

点击那个叉叉按钮可以关闭dialog组件  但是点击Cancel和Confirm按钮毫无反应

没错就是子组件没有传值到父组件上面去 所以!!! 重点来了

📦defineEmits

子组件向父组件事件传递

通俗点就是子组件可以调用父组件的方法并且可以传参

所以在我们的子组件里面修改以下代码

<template>
  <el-dialog :model-value="dialogFormVisible" title="Shipping address">
    <el-form :model="form">
      <el-form-item label="Promotion name" :label-width="formLabelWidth">
        <el-input v-model="form.name" autocomplete="off" />
      </el-form-item>
      <el-form-item label="Zones" :label-width="formLabelWidth">
        <el-select v-model="form.region" placeholder="Please select a zone">
          <el-option label="Zone No.1" value="shanghai" />
          <el-option label="Zone No.2" value="beijing" />
        </el-select>
      </el-form-item>
    </el-form>
    <template #footer>
      <span class="dialog-footer">
        //加上关闭的点击事件
        <el-button @click="handleClose">Cancel</el-button>
        <el-button type="primary" @click="handleClose">Confirm</el-button
        >
      </span>
    </template>
  </el-dialog>
</template>
 
<script setup>
//记得引入defineEmits
  import { reactive, defineEmits,ref } from "vue";
 
//实例化defineEmits
 const emits = defineEmits(['update:modelValue'])
 
//关闭的点击事件
  const handleClose = () => {
    emits('update:modelValue', false)
  }
 
  const dialogFormVisible = ref(false)
 
  const formLabelWidth = '140px'
 
  const form = reactive({
    name: '',
    region: '',
    date1: '',
    date2: '',
    delivery: false,
    type: [],
    resource: '',
    desc: '',
  })
</script>
 
<style scoped>
  .el-button--text {
    margin-right: 15px;
  }
  .el-select {
    width: 300px;
  }
  .el-input {
    width: 300px;
  }
  .dialog-footer button:first-child {
    margin-right: 10px;
  }
</style>

然后再去试试 完美解决!!!

3.开始运用: 用户的增加修改操作

这个想必并不陌生 一般情况下便于维护 增加和修改操作都是在一个dialog上的

所以我们需要通过传入一个参数来区分我们进行的是添加用户还是修改用户 

修改用户还得向子组件传入咱们表格那一行的数据

所以咱们简化一下

如果是添加用户 就传一个字符串

如果是修改用户 就传一个对象过去

思路清晰 开始操作!!!

1.父组件的修改 

在添加用户按钮上修改如下

  <el-button type="primary" @click="handlerDialog('添加用户')"
      >添加用户
      </el-button>

修改按钮这里就要用到自己的表格数据了 

  <template #default="{ row }" v-else-if="item.prop==='action'">
     <el-button type="primary" @click="handlerDialog(row)" :icon="Edit"/>
 </template>

解释一下 这里是elementplus的表格的自定义列 有疑惑的可以参考官网文档

 然后在修改点击事件handlerDialog

 const handlerDialog = (row) => {
 
    if(row==='添加用户'){
      dialogTitile.value = "添加用户"
      dialogTableValue.value = {}
    }else{
      dialogTitile.value = "修改用户"
      console.log(row)
      dialogTableValue.value = JSON.parse(JSON.stringify(row))
 
    }
    dialogFormVisible.value = true
  }

说明一下 JSON.stringify() 系列化对象

系列化对象说白了就是把对象的类型转换为字符串类型

最后 发现这里给子组件是传入了俩个参数

所以 我们要去给父组件绑定上

  <test v-model="dialogFormVisible"
        v-if="dialogFormVisible"
        :dialogTitile="dialogTitile"
        :dialogTableValue="dialogTableValue"
  />

2.子组件的修改

父组件给子组件需要一个插件

📦defineProps:父组件给子组件传值

加入以下方法 别忘了导入defineProps

 import {  defineProps } from 'vue' 
//接受父组件的值
  const props = defineProps({
    dialogTitile: {
      type: String,
      default: '',
      required: true
    },
    dialogTableValue:{
      type:Object,
      default: ()=>{},
    }
 
  })

这个时候添加用户的操作已经完成了

修改用户这块父组件已经传过来值了 接下来开始赋值操作

3.父组件给子组件赋值

📦这时候需要一个监听

所以我们要导入一个watch

import { watch } from 'vue'
watch(()=>props.dialogTableValue,()=>{
   form.value = props.dialogTableValue.value
},{deep:true,immediate:true})

 props是我们创建出来的实例 在defineProps那一块

form.value = props.dialogTableValue.value 是将我们父组件的dialogTableValue传给form对象

这时候再去测试以下 已经没问题了!!!

父组件传过来的值里面还有一个 dialogTitile 

我们知道修改用户的密码话在实际中是不能修改的

所以咱们一不做二不休

只需要修改一下form表单 加上一个v-if

<el-form-item label="密码" :label-width="formLabelWidth" prop="password" v-if="dialogTitile==='添加用户'">
        <el-input v-model="form.password" name="password" type="password" show-password/>
 </el-form-item>

4.子组件调用父组件方法

论异步 咱们就要异步到底 在添加用户和修改用户之后 我们可以调用父组件的更新表格内容的方法

在这里我是  initUserList  小伙伴就调用自己的就好了

所以最后 修改dialog的提交按钮如下

 const emits = defineEmits(['update:modelValue','initUserList']) 
 
const handleConfirm = () => {
    formref.value.validate(async (valid) => {
      if (valid) {
        props.dialogTitile==='添加用户' ? await adduser(form.value) : await editUser(form.value)
        props.dialogTitile==='添加用户' ? ElMessage.success("添加成功"):ElMessage.success("修改成功")
        emits('initUserList')
        handleClose()
      } else {
        props.dialogTitile==='添加用户' ? ElMessage.error('"添加失败'):ElMessage.success("修改失败")
        return false
      }
    })
 
  }

完结撒花🔥🔥🔥

总结

到此这篇关于vue3父组件和子组件如何传值的文章就介绍到这了,更多相关vue3父组件和子组件传值内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文