vue3知识点:toRaw 与 markRaw

news/2024/7/9 23:40:01 标签: vue, vue3, toRaw, markRaw

在这里插入图片描述

文章目录

  • 三、其它 Composition API(不常用,了解即可)
  • 本人其他相关文章链接

三、其它 Composition API(不常用,了解即可)

toRaw__markRaw_3">3.toRawmarkRaw

在这里插入图片描述
注意点1:
之前上面讲解的函数都是把普通数据 -> 响应式数据,如图红线1,但是有时我们也需要把响应式数据 -> 普通数据,如图绿线2
在这里插入图片描述

注意点2:

问题:如图,我先用toRaw(person)把响应式person对象转为p普通对象,然后一顿修改p的age属性,那么页面会更新值吗?

答案:不会,因为p的对象类型为Object,它不是一个响应式的,所以修改无效。
在这里插入图片描述

结果展示如图:

在这里插入图片描述

注意点3:
toRaw函数只处理reactive缔造的响应式数据有效,针对ref缔造的响应式数据无效,比如代码如图1,点击按钮“输出最原始的person”,打印ref缔造的响应式数据结果如图2,打印reactive缔造的响应式数据结果如图3。
在这里插入图片描述

如图1

在这里插入图片描述

如图2

在这里插入图片描述

如图3

注意点4:

问题:假设我给person新增个car属性,代码如下,但是报错了为啥?,报错如图1

<h3>座驾信息:{{car}}</h3>
<button @click="addCar">给人添加一台车</button>

function addCar(){
	let car = {name:'奔驰',price:40}
	person.car = car
}

//返回一个对象(常用)
return {
	sum,
	...toRefs(person),
	showRawPerson,
	addCar
}

在这里插入图片描述

如图1

答案:你执行到…toRefs(person)的时候,addCar按钮和方法还没执行呢,也就是初始化时person里面还没有car属性呢,你项目启动后模板渲染后肯定报错啊,报错说car没定义在实例上。但是哪怕…toRefs(person)执行后你再往person对象新增个car属性,…toRefs(person)也不会再执行一遍,因为如果…toRefs(person)想再执行一遍,除非setup()再执行一遍,但很可惜整个项目启动后setup()只会执行一遍。

解决方案是:有2种解决办法:

  • 办法1:在定义person对象时,先定义一个空的car属性用来占位
    在这里插入图片描述
  • 办法2:在return返回对象中,在…toRefs(person)的上面提前返回个person对象,同时修改<h3>标签体内容即可。
    在这里插入图片描述
    在这里插入图片描述
    原理是:在…toRefs(person)的上面提前返回个person对象,就会把整个person响应式对象交出去,这个person响应式对象中任何属性发生变化都能被vue监测到。

注意点5:

问题:针对注意点4中代码,为啥定义person.car = car,也行实现person中car属性的的响应式?car不是定义普通的Object类型的对象吗?

function addCar(){
	let car = {name:'奔驰',price:40}
	person.car = car
}

//返回一个对象(常用)
return {
	sum,
	person,
	...toRefs(person),
	showRawPerson,
	addCar	
}

答案:因为return配置了返回person,就相当于配置了Proxy代理,只要捕获到对person任何属性的操作,任何属性的操作都是响应式的。

注意点6:
person.car = markRaw(car),使用markRaw函数,可以使person中car属性无法进行修改,案例效果如图:toRaw与markRwa-注意点6-结果展示.gif,需要说明的是:car内部属性值已经改了,只是没有响应式更新而已,它和readonly不同,readonly是压根不让修改。
在这里插入图片描述

toRaw与markRwa-注意点6-结果展示.gif

注意点7:

问题:何时使用markRaw

答案:

  • 场景1. 有些值不应被设置为响应式的,例如复杂的第三方类库等。
  • 场景2. 当渲染具有不可变数据源的大列表时,跳过响应式转换可以提高性能。

注意点8:

问题:针对注意点7中场景1,如何理解使用复杂的第三方类库时最好使用markRaw函数标记?

答案:如图,假设person中axios这个是第三方类库提供的超级复杂至少二三十层嵌套的数据,当你return配置返回person对象时,那么第三方类库提供的超级复杂的axios数据中,所有的属性都会做proxy代理做响应式,明显会超级浪费资源且效率太低,所以需要用markRaw进行标记为只读不可修改,这样vue监测到就不会把axios数据中所有的属性都会做proxy代理做响应式,从而达到节省了资源消耗的目的,且解决效率太低的问题
在这里插入图片描述

测试案例

完整代码

项目目录

在这里插入图片描述

main.js

//引入的不再是Vue构造函数了,引入的是一个名为createApp的工厂函数
import { createApp } from 'vue'
import App from './App.vue'

//创建应用实例对象——app(类似于之前Vue2中的vm,但app比vm更“轻”)
const app = createApp(App)

//挂载
app.mount('#app')

App.vue

<template>
	<button @click="isShowDemo = !isShowDemo">切换隐藏/显示</button>
	<Demo v-if="isShowDemo"/>
</template>

<script>
	import {ref} from 'vue'
	import Demo from './components/Demo'
	export default {
		name: 'App',
		components:{Demo},
		setup() {
			let isShowDemo = ref(true)
			return {isShowDemo}
		}
	}
</script>

Demo.vue

<template>
	<h4>当前求和为:{{sum}}</h4>
	<button @click="sum++">点我++</button>
	<hr>
	<h2>姓名:{{name}}</h2>
	<h2>年龄:{{age}}</h2>
	<h2>薪资:{{job.j1.salary}}K</h2>
	<h3 v-show="person.car">座驾信息:{{person.car}}</h3>
	<button @click="name+='~'">修改姓名</button>
	<button @click="age++">增长年龄</button>
	<button @click="job.j1.salary++">涨薪</button>
	<button @click="showRawPerson">输出最原始的person</button>
	<button @click="addCar">给人添加一台车</button>
	<button @click="person.car.name+='!'">换车名</button>
	<button @click="changePrice">换价格</button>
</template>

<script>
	import {ref,reactive,toRefs,toRaw,markRaw} from 'vue'
	export default {
		name: 'Demo',
		setup(){
			//数据
			let sum = ref(0)
			let person = reactive({
				name:'张三',
				age:18,
				job:{
					j1:{
						salary:20
					}
				}
			})

			function showRawPerson(){
				const p = toRaw(person)
				p.age++
				console.log(p)
			}

			function addCar(){
				let car = {name:'奔驰',price:40}
				person.car = markRaw(car)
			}

			function changePrice(){
				person.car.price++
				console.log(person.car.price)
			}

			//返回一个对象(常用)
			return {
				sum,
				person,
				...toRefs(person),
				showRawPerson,
				addCar,
				changePrice
			}
		}
	}
</script>

结果展示:

在这里插入图片描述

本人其他相关文章链接

1.《vue3第三章》其它 Composition API(不常用,了解即可),包括shallowReactive 与 shallowRef、readonly 与 shallowReadonly等等
2.vue3知识点:shallowReactive 与 shallowRef
3.vue3知识点:readonly 与 shallowReadonly
4.vue3知识点:toRawmarkRaw
5.vue3知识点:customRef
6.vue3知识点:provide 与 inject
7.vue3知识点:响应式数据的判断


http://www.niftyadmin.cn/n/898084.html

相关文章

vue3知识点:customRef

文章目录三、其它 Composition API(不常用&#xff0c;了解即可)4.customRef测试案例完整代码本人其他相关文章链接三、其它 Composition API(不常用&#xff0c;了解即可) 4.customRef 作用&#xff1a;创建一个自定义的 ref&#xff0c;并对其依赖项跟踪和更新触发进行显式控…

vue3知识点:provide 与 inject

文章目录三、其它 Composition API(不常用&#xff0c;了解即可)5.provide 与 inject测试案例完整代码本人其他相关文章链接三、其它 Composition API(不常用&#xff0c;了解即可) 5.provide 与 inject 作用&#xff1a;实现祖与后代组件间通信套路&#xff1a;父组件有一个 …

vue3知识点:响应式数据的判断

文章目录三、其它 Composition API(不常用&#xff0c;了解即可)6.响应式数据的判断测试案例完整代码本人其他相关文章链接三、其它 Composition API(不常用&#xff0c;了解即可) 6.响应式数据的判断 测试案例 完整代码 项目目录 main.js //引入的不再是Vue构造函数了&#…

《vue3第四章》Composition API 的优势,包含Options API 存在的问题、Composition API 的优势

文章目录四、Composition API 的优势1.Options API 存在的问题2.Composition API 的优势四、Composition API 的优势 1.Options API 存在的问题 使用传统OptionsAPI中&#xff0c;新增或者修改一个需求&#xff0c;就需要分别在data&#xff0c;methods&#xff0c;computed里…

《vue3第五章》新的组件,包含:Fragment、Teleport、Suspense

文章目录五、新的组件1.Fragment2.Teleport案例完整代码3.Suspense案例完整代码本人其他相关文章链接五、新的组件 1.Fragment 在Vue2中: 组件必须有一个根标签在Vue3中: 组件可以没有根标签, 内部会将多个标签包含在一个Fragment虚拟元素中好处: 减少标签层级, 减小内存占用…

《vue3第六章》其他,包含:全局API的转移、其他改变

文章目录六、其他1.全局API的转移2.其他改变六、其他 1.全局API的转移 Vue 2.x 有许多全局 API 和配置。 例如&#xff1a;注册全局组件、注册全局指令等。 //注册全局组件 Vue.component(MyButton, {data: () > ({count: 0}),template: <button click"count"…

vue3知识点:Teleport组件

文章目录五、新的组件2.Teleport案例完整代码本人其他相关文章链接五、新的组件 2.Teleport 问题&#xff1a;什么是Teleport&#xff1f; 答案&#xff1a;Teleport 是一种能够将我们的组件html结构移动到指定位置的技术。 <teleport to"移动位置"><div …

vue3知识点:Suspense组件

文章目录五、新的组件3.Suspense案例完整代码本人其他相关文章链接五、新的组件 3.Suspense 等待异步组件时渲染一些额外内容&#xff0c;让应用有更好的用户体验 使用步骤&#xff1a; 第1步&#xff1a;异步引入组件 import {defineAsyncComponent} from vue const Child …