vue3第二次传递数据方法无法获取到最新的值

使用reactive父组件第二次传递给子组件的数据:方法中可以获取到最新数据

xml 复制代码
<template>
  <div>
    <div>
      <h1>子组件</h1>
      <child :infoObj='infoObj' ref="childRef"></child>
    </div>
    <button @click='updateHandler'>跟新值</button>
    <div>
      <h1>父页面</h1>
      <p>{{ infoObj }}</p>
    </div>
  </div>
</template>

<script setup lang="ts">
import child from '@/components/child.vue'
import { ref,reactive } from 'vue'
let infoObj = reactive({
  name:'张三',
  age:26
})
const childRef = ref()
function updateHandler(){
  infoObj.name = '李四'
  infoObj.age = 28
  // 跟新值后,调用父组件的方法。
  childRef.value.getData()
}
</script>
xml 复制代码
<template>
  <div>
    <h1> {{ props.infoObj }}</h1>
  </div>
</template>

<script setup lang="ts">
let props = defineProps({
  infoObj:Object,
})
function getData(){
  console.log('infoObj', props.infoObj)
}
defineExpose({
  getData
})
</script>

使用ref父组件第二次传递给子组件的数据:不能获取到最新的数据

xml 复制代码
<template>
  <div>
    <div>
      <h1>子组件</h1>
      <child :infoObj='infoObj' ref="childRef"></child>
    </div>
    <button @click='updateHandler'>跟新值</button>
    <div>
      <h1>父页面</h1>
      <p>{{ infoObj }}</p>
    </div>
  </div>
</template>
<script setup lang="ts">
import child from '@/components/child.vue'
import { ref } from 'vue'
let infoObj = ref({
  name:'张三',
  age:26
})
const childRef = ref()
function updateHandler(){
  infoObj.value = {
    name:'李四',
    age:28
  }
  // 跟新值后,调用父组件的方法。看下getData是否可以获取到最新的值
  childRef.value.getData()
}
</script>
xml 复制代码
<template>
  <div>
    <h1> {{ props.infoObj }}</h1>
  </div>
</template>
<script setup lang="ts">
let props = defineProps({
  infoObj:Object,
})
function getData(){
  console.log('infoObj', props.infoObj)
}
defineExpose({
  getData
})
</script>

办法1:将数据作为函数的参数进行传递

xml 复制代码
<template>
  <div>
    <div>
      <h1>子组件</h1>
      <child :infoObj='infoObj' ref="childRef"></child>
    </div>
    <button @click='updateHandler'>跟新值</button>
    <div>
      <h1>父页面</h1>
      <p>{{ infoObj }}</p>
    </div>
  </div>
</template>
<script setup lang="ts">
import child from '@/components/child.vue'
import { ref } from 'vue'
let infoObj = ref({
  name:'张三',
  age:26
})
const childRef = ref()
function updateHandler(){
  infoObj.value = {
    name:'李四',
    age:28
  }
  // 将数据作为函数的参数进行传递
  childRef.value.getData(infoObj.value)
}
</script>
xml 复制代码
<template>
  <div>
    <h1> {{ props.infoObj }}</h1>
  </div>
</template>
<script setup lang="ts">
let props = defineProps({
  infoObj:Object,
})
function getData(mess:any){
  console.log('infoObj', props.infoObj)
  console.log('将数据作为函数的参数进行传递:mess', mess)
}
defineExpose({
  getData
})
</script>

解决办法2:在调用方法时使用 nextTick

xml 复制代码
<template>
  <div>
    <div>
      <h1>子组件</h1>
      <child :infoObj='infoObj' ref="childRef"></child>
    </div>
    <div>
      <h1>父页面</h1>
      <p>{{ infoObj }}</p>
    </div>
    <button @click='updateHandler'>跟新值</button>
  </div>
</template>
<script setup lang="ts">
import child from '@/components/child.vue'
import { nextTick, ref } from 'vue'
let infoObj = ref({
  name:'张三',
  age:26
})
const childRef = ref()
function updateHandler(){
  infoObj.value = { name: '李四', age: 28 };
  // 推荐在这里使用nextTick
  nextTick(() => {
    childRef.value.getData()
  })
}
</script>
xml 复制代码
<template>
  <div>
    <h1> {{ props.infoObj }}</h1>
  </div>
</template>
<script setup lang="ts">
let props = defineProps({
  infoObj:Object,
})
function getData(){
  // 或者在这里使用nextTick。
  console.log('getData 方法获取值',  props.infoObj.name, props.infoObj.age)
}
defineExpose({
  getData
})
</script>

结论

使用ref父组件第二次传递给子组件的数据(基本数据和引用数据):不能获取到最新的数据。

使用reactive和ref传递参数给子组件,为啥ref第二次子组件无法获取最新的数据?而reactive可以

在 Vue 3 中,reactive 和 ref 在传递给子组件时的行为有所不同。

这也说明了 reactive 和 ref 是有区别的(屁话)。

ref 和 reactive 的区别

1,ref可以试用于任何数据类型,而reactive只适用于对象类型。

2,在js模块ref获取值,设置值,需要点value, ‌在模板中使用不需要点value。 而reactive都不需要。

3,ref可以完全替换整个对象,不会失去响应式。

reactive不能直接替换整个对象(否则会失去响应式)。需要逐个修改属性或使用 Object.assign

4,返回值不同。ref返回一个‌包装对象‌。reactive返回一个‌Proxy 对象‌

ref完全替换 不会失去响应式

xml 复制代码
<template>
  <button type="button" @click="updateHandler">更改数据</button>
  <p>数据{{ objRef }}</p>
</template>
<script setup lang="ts">
import { ref } from 'vue';
const objRef = ref({ age: 1 })
function updateHandler(){
  //完全替换 不会失去响应式
  objRef.value = { age: 100 } 
}
</script>

reactive不能直接替换整个对象(会失去响应式)

css 复制代码
const objReactive = reactive({ a: 1 })
// 错误方式(失去响应性)
objReactive = { b: 2 }

// 正确方式 或者逐个修改属性
Object.assign(objReactive, { b: 2 })

[错误]:ref解构不会失去响应式。reactive解构或展开会失去响应式。[这句话不正确]

ref和reactive解构都会失去响应式。都需要通过toRefs 或者toRef 来进行解决。

reactive 解构会失去响应式

xml 复制代码
<template>
  <button type="button" @click="updateHandler">更改数据</button>
  <p>数据{{ name }} {{  age}}</p>
</template>
<script setup lang="ts">
import { reactive } from 'vue';
const state = reactive({ name: '张三', age: 20 })
// reactive解构会失去响应式
let { name, age } = state
function updateHandler(){
  // 更新数据后,页面不会跟新
  name = '王麻子'
  age = 1000
}
</script>

ref 解构会失去响应式

xml 复制代码
<template>
  <div>
    <p>Name: {{ name }}</p>
    <p>Age: {{ age }}</p>
    <button @click="changeName">Change Name</button>
  </div>
</template>

<script setup>
import { ref } from 'vue'
// 使用 ref 创建响应式对象
const user = ref({
  name: 'Alice',
  age: 25
})
// 解构 ref 对象 - 会失去响应式,视图不会跟新
let { name, age } = user.value
function changeName() {
  name = 'Bob' // 直接修改解构出来的属性
}
</script>

toRefs()​解构ref,解构后仍然保持响应式

xml 复制代码
<template>
  <div>
    <p>Name: {{ name }}</p>
    <p>Age: {{ age }}</p>
    <button @click="changeName">Change Name</button>
  </div>
</template>
<script setup>
import { ref,toRefs } from 'vue'
// 使用 ref 创建响应式对象
const user = ref({
  name: 'Alice',
  age: 25
})
// 通过toRefs解构不会失去响应式
let { name, age } = toRefs(user.value) 
function changeName() {
  name.value = '大大再大' // 直接修改解构出来的属性
}
</script>

toRef()​解构reactive,解构后仍然保持响应式

xml 复制代码
<template>
  <button type="button" @click="updateHandler">更改数据</button>
  <p>数据{{ name }} {{  age}}</p>
</template>
<script setup lang="ts">
import { reactive, toRefs } from 'vue';
const state = reactive({ name: '张三', age: 20 })
// 通过toRefs解构不会失去响应式
let { name, age } =  toRefs(state) 
function updateHandler(){
  // 更新数据后,页面不会跟新
  name.value = '王麻子'
  age.value = 1000
}
</script>

toRefs()​

官网:将一个响应式对象转换为一个普通对象。

这个普通对象的[每个属性]都是指向源对象[相应属性的] ref。

每个单独的 ref 都是使用 toRef() 创建的。

我的理解:

toRefs 可以把一个响应式对象转换为普通的对象。

该普通对象的每一个值都是ref。

由于变成了ref,所以我们使用每个属性的时候需要点value。

ref和reactive的使用场景

ref 适合于基本数据类型,reactive适合于对象类型。

ref 适合完全替换整个对象

我喜欢用ref定义基本数据类型和数组。对象使用reactive。

ref的本质

我理解的ref本质上是reactive的再封装。

使用reactive定义响应式数据时,若数据不是对象类型直接就返回了。

就不会进行后续的数据响应式处理了。

这也就是我只用reactive定义对象型响应式数据的原因

相关推荐
gnip3 小时前
企业级配置式表单组件封装
前端·javascript·vue.js
一只叫煤球的猫4 小时前
写代码很6,面试秒变菜鸟?不卖课,面试官视角走心探讨
前端·后端·面试
excel5 小时前
Three.js 材质(Material)详解 —— 区别、原理、场景与示例
前端
掘金安东尼5 小时前
抛弃自定义模态框:原生Dialog的实力
前端·javascript·github
hj5914_前端新手9 小时前
javascript基础- 函数中 this 指向、call、apply、bind
前端·javascript
薛定谔的算法9 小时前
低代码编辑器项目设计与实现:以JSON为核心的数据驱动架构
前端·react.js·前端框架
Hilaku9 小时前
都2025年了,我们还有必要为了兼容性,去写那么多polyfill吗?
前端·javascript·css
yangcode9 小时前
iOS 苹果内购 Storekit 2
前端
LuckySusu9 小时前
【js篇】JavaScript 原型修改 vs 重写:深入理解 constructor的指向问题
前端·javascript
LuckySusu9 小时前
【js篇】如何准确获取对象自身的属性?hasOwnProperty深度解析
前端·javascript