vue3(二)(reactive,readonly,shallowReactive,toRef ,toRefs, toRaw)
reactive
用来绑定复杂的数据类型 例如 对象 数组,他是不可以绑定普通的数据类型
这样是不允许 会报错
绑定普通的数据类型 我们可以 使用昨天讲到ref
你如果用ref去绑定对象 或者 数组 等复杂的数据类型 我们看源码里面其实也是 去调用reactive
使用reactive 去修改值无须.value
reactive 基础用法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <template> <div> {{ person.name }} </div> </template> <script setup lang= 'ts' > import { reactive } from 'vue' let person = reactive({ name: "小满" }) person.name = "大满" </script> <style scoped> </style> |
数组异步赋值问题
这样赋值数据是变了,但是页面是不会变化的因为会脱离响应式,需要使用数组方法操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <template> <div> {{ person }} </div> </template> <script setup lang= 'ts' > import { reactive } from 'vue' let person = reactive<number[]>([]) setTimeout(() => { person = [1, 2, 3] console.log(person); },1000) </script> <style scoped> </style> |
解决方案1 使用push
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | <template> <div> {{ person }} </div> </template> <script setup lang= 'ts' > import { reactive } from 'vue' let person = reactive<number[]>([]) setTimeout(() => { const arr = [1, 2, 3] person.push(...arr) console.log(person); },1000) </script> <style scoped> </style> |
方案2
包裹一层对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | <template> <div> {{ person }} </div> </template> <script setup lang= 'ts' > import { reactive } from 'vue' type Person = { list?:Array<number> } let person = reactive<Person>({ list:[] }) setTimeout(() => { const arr = [1, 2, 3] person.list = arr; console.log(person); },1000) </script> <style scoped> </style> |
readonly
拷贝一份proxy对象将其设置为只读
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <template> <div> {{ person.count }} </div> </template> <script setup lang= 'ts' > import { reactive ,readonly} from 'vue' const person = reactive({count:1}) const copy = readonly(person) //person.count++ //可以增加 copy.count++ //只读不可以增加 </script> <style scoped> </style> |
shallowReactive
只能对浅层的数据 如果是深层的数据只会改变值 不会改变视图
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | <template> <div> <div>{{ state }}</div> <button @click= "change1" >test1</button> <button @click= "change2" >test2</button> </div> </template> <script setup lang= "ts" > import { shallowReactive } from 'vue' const obj = { a: 1, first: { b: 2, second: { c: 3 } } } const state = shallowReactive(obj) function change1() { state.a = 7 //可以改变视图 } function change2() { state.first.b = 8 //不可以改变视图 state.first.second.c = 9 //不可以改变视图 console.log(state); } </script> <style> </style> |
toRef toRefs toRaw
toRef
如果原始对象是非响应式的就不会更新视图 数据是会变的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | <template> <div> <button @click= "change" >按钮</button> {{state}} </div> </template> <script setup lang= "ts" > import { reactive, toRef } from 'vue' const obj = { foo: 1, bar: 1 } const state = toRef(obj, 'bar' ) // bar 转化为响应式对象 const change = () => { state.value++ console.log(obj, state); } </script> |
如果原始对象是响应式的是会更新视图并且改变数据的 ,为源响应式对象上的某个元素 新创建一个 ref
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | <template> <div> <button @click= "change" >按钮</button> {{state}} </div> </template> <script setup lang= "ts" > import { reactive, toRef } from 'vue' const obj = reactive({ foo: 1, bar: 1 }) const state = toRef(obj, 'bar' ) // bar 转化为响应式对象 const change = () => { state.value++ console.log(obj, state); } </script> |
更改person.age的值时,
通过ref(person.age)得到的age1不会改变,因为ref是复制,拷贝了一份新的数据值单独操作, 更新时相互不影响
通过toRef(person,‘age’)得到的age2会改变,因为 toRef是引用。它为源响应式对象上的某个属性创建一个 ref对象, 二者内部操作的是同一个数据值, 更新时二者是同步的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | <template> <div> <button @click= "change" >按钮</button> <h1>{{age1}}</h1> <h1>{{age2}}</h1> </div> </template> <script setup lang= "ts" > import { reactive,ref, toRef } from "vue" ; let person =reactive( { name: "long" ,age:23 }); let age1 = ref(person.age); let age2=toRef(person, 'age' ) const change = () => { person.age++ }; </script> |
应用: 当要将 某个prop 的 ref 传递给复合函数时,toRef 很有用
useFeatureX函数需要使用props中的foo属性,且foo要为ref。
1 2 3 4 5 6 7 | setup (props, context) { const length = useFeatureX(toRef(props, 'foo' )) return { length } } |
toRefs
可以帮我们批量创建ref对象主要是方便我们解构使用,将响应式对象Proxy 转换为普通对象,且元素都指向原始对象的ref
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | <template> <div> <button @click= "change" >按钮</button> {{ foo }} </div> </template> <script setup lang= "ts" > import { reactive, toRefs } from "vue" ; const obj = reactive({ foo: 1, bar: 1, }); let { foo, bar } = toRefs(obj); const change = () => { foo.value++; console.log(foo, bar); }; </script> |
toRaw
将响应式对象转化为普通对象,返回 reactive或readonly代理的原始对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | import { reactive, toRaw } from 'vue' const obj = reactive({ foo: 1, bar: 1 }) const state = toRaw(obj) // 响应式对象转化为普通对象 const change = () => { console.log(obj, state); } |
————————————————
版权声明:本文为CSDN博主「小满zs」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq1195566313/article/details/122768533
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现