vue3:直接修改reative的值,页面却不响应,这是什么情况?

目录

前言:

错误示范:

reactive() 的局限性

解决办法:

1.使用ref

2.reative多套一层

3.使用Object.assign


前言:

        今天看到有人在提问,问题是这样的,我修改了reative的值,数据居然失去了响应性,页面毫无变化,这是什么情况?本着好奇心害死猫的原则,我就看了下,我直呼好家伙!

错误示范:

请看以下代码,大概是这个样子的:

<template>
	<view>
		<view class="">{
  { user }}</view>
		<button @click="setUser">修改user</button>
	</view>
</template>
 
<script setup>
	import {
		reactive
	} from 'vue';
 
	let user = reactive({
		name: 'jay'
	});
 
	const setUser = () => {
		user = {
			name: 'qianjue',
			age: 20
		}
	};
</script>

此时我无论如何点击改变user按钮,页面岿然不动

本着严谨的原则,我们在setUser内打印下user的值,观察观察

	const setUser = () => {
		console.log(user);
		user = {
			name: 'qianjue',
			age: 20
		}
	};

红色框是我们第一次点击按钮的打印值,绿色框是我们之后点击的打印值,我们都很清楚这两个值所代表的意义,当我们第一次点击之后,我们的user对象变成了一个普通的对象,并不是由proxy的代理对象,所以根本不具有响应性。

这个时候,就会有人想点子了,不是说我是个普通对象,不是代理的吗?我给他重新赋值一个reative,这不就完美解决?
 

	const setUser = () => {
		console.log(user);
		user = reactive({
			name: 'qianjue',
			age: 20
		})
	};

 然后点击按钮发现,页面还是毫无变化,user的打印值如下,嗯?感觉没毛病啊,莫非是vue3的bug?

 原因:Vue 的响应式系统是通过属性访问进行追踪的,因此我们必须始终保持对该响应式对象的相同引用。这意味着我们不可以随意地“替换”一个响应式对象,因为这将导致对初始引用的响应性连接丢失

这可不是我说的,是vue官网说的---- vue响应式文档icon-default.png?t=N7T8https://cn.vuejs.org/guide/essentials/reactivity-fundamentals.html#reactive-proxy-vs-original-1

reactive() 的局限性

reactive() API 有一些局限性:

  • 有限的值类型:它只能用于对象类型 (对象、数组和如 MapSet 这样的集合类型)。它不能持有如 stringnumber 或 boolean 这样的原始类型

  • 不能替换整个对象:由于 Vue 的响应式跟踪是通过属性访问实现的,因此我们必须始终保持对响应式对象的相同引用。这意味着我们不能轻易地“替换”响应式对象,因为这样的话与第一个引用的响应性连接将丢失:

let state = reactive({ count: 0 })

// 上面的 ({ count: 0 }) 引用将不再被追踪
// (响应性连接已丢失!)
state = reactive({ count: 1 })
  • 对解构操作不友好:当我们将响应式对象的原始类型属性解构为本地变量时,或者将该属性传递给函数时,我们将丢失响应性连接: 
const state = reactive({ count: 0 })

// 当解构时,count 已经与 state.count 断开连接
let { count } = state
// 不会影响原始的 state
count++

// 该函数接收到的是一个普通的数字
// 并且无法追踪 state.count 的变化
// 我们必须传入整个对象以保持响应性
callSomeFunction(state.count)

由于这些限制,我们建议使用 ref() 作为声明响应式状态的主要 API。 

解决办法:

1.使用ref
	let user = ref({
		name: 'jay'
	});
 
	const setUser = () => {
		console.log(user.value);
		user.value = {
			name: 'qianjue',
			age: 20
		}
	};

 

2.reative多套一层
<template>
	<view>
		<view class="">{
  { state.user }}</view>
		<button @click="setUser">修改user</button>
	</view>
</template>
 
<script setup>
	import {
		reactive
	} from 'vue';
	const state = reactive({
		user: {
			name: 'jay'
		}
	})
	const setUser = () => {
		console.log(state.user);
		state.user = {
			name: 'qianjue',
			age: 20
		}
	};
</script>
3.使用Object.assign
	const user = reactive({
		name: 'jay'
	})
 
	const setUser = () => {
		console.log(user);
		Object.assign(user, {
			name: 'qianjue',
			age: 20
		})
	};

相关推荐

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2023-12-16 14:10:05       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2023-12-16 14:10:05       101 阅读
  3. 在Django里面运行非项目文件

    2023-12-16 14:10:05       82 阅读
  4. Python语言-面向对象

    2023-12-16 14:10:05       91 阅读

热门阅读

  1. TS Option类型与Promise

    2023-12-16 14:10:05       41 阅读
  2. typescript学习笔记

    2023-12-16 14:10:05       45 阅读
  3. SQL连续

    2023-12-16 14:10:05       70 阅读
  4. 贰[2],函数OpenWindow/CloseWindow

    2023-12-16 14:10:05       62 阅读
  5. vue3拖拽组件vuedraggable

    2023-12-16 14:10:05       66 阅读
  6. QT之QMessageBox的用法

    2023-12-16 14:10:05       44 阅读
  7. 大语言模型--引言

    2023-12-16 14:10:05       45 阅读
  8. Clion下编写QT界面方法详解

    2023-12-16 14:10:05       58 阅读
  9. Storm+Kafka+Redis+zookeeper docker集群实战问题与解决

    2023-12-16 14:10:05       40 阅读
  10. 使用boost::mpl模块实现push_back相关的测试程序

    2023-12-16 14:10:05       63 阅读