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定义对象型响应式数据的原因

相关推荐
IT_陈寒24 分钟前
Python 3.12性能优化实战:5个让你的代码提速30%的新特性
前端·人工智能·后端
赛博切图仔24 分钟前
「从零到一」我用 Node BFF 手撸一个 Vue3 SSR 项目(附源码)
前端·javascript·vue.js
爱写程序的小高25 分钟前
npm ERR! code ERESOLVE npm ERR! ERESOLVE unable to resolve dependency tree
前端·npm·node.js
loonggg25 分钟前
竖屏,其实是程序员的一个集体误解
前端·后端·程序员
程序员爱钓鱼35 分钟前
Node.js 编程实战:测试与调试 - 单元测试与集成测试
前端·后端·node.js
码界奇点41 分钟前
基于Vue.js与Element UI的后台管理系统设计与实现
前端·vue.js·ui·毕业设计·源代码管理
洛小豆1 小时前
她问我:服务器快被垃圾文件塞爆了,怎么破?我说:给文件办个“临时居住证”
后端·面试
时光少年1 小时前
Android KeyEvent传递与焦点拦截
前端
洛小豆1 小时前
孤儿资源治理:如何优雅处理“上传了但未提交”的冗余文件?
java·后端·面试
a努力。1 小时前
中国电网Java面试被问:分布式缓存的缓存穿透解决方案
java·开发语言·分布式·缓存·postgresql·面试·linq