Fork me on GitHub

vue3(二)(reactive,readonly,shallowReactive,toRef ,toRefs, toRaw)

reactive

用来绑定复杂的数据类型 例如 对象 数组,他是不可以绑定普通的数据类型这样是不允许 会报错

绑定普通的数据类型 我们可以 使用昨天讲到ref

你如果用ref去绑定对象 或者 数组 等复杂的数据类型 我们看源码里面其实也是 去调用reactive

使用reactive 去修改值无须.value

reactive 基础用法

<template>
  <div>
    {{ person.name }}
  </div>
</template>
 
<script setup lang='ts'>
import { reactive } from 'vue'
let person = reactive({
   name:"小满"
})
person.name = "大满"
</script>
<style scoped>
</style>

  

数组异步赋值问题

这样赋值数据是变了,但是页面是不会变化的因为会脱离响应式,需要使用数组方法操作

<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

<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

包裹一层对象

<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对象将其设置为只读

<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 

只能对浅层的数据 如果是深层的数据只会改变值 不会改变视图

<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

如果原始对象是非响应式的就不会更新视图 数据是会变的

<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

<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对象, 二者内部操作的是同一个数据值, 更新时二者是同步的

<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。 

  setup (props, context) {
    const length = useFeatureX(toRef(props, 'foo'))

    return {
      length
    }
  }

  

toRefs

可以帮我们批量创建ref对象主要是方便我们解构使用,将响应式对象Proxy 转换为普通对象,且元素都指向原始对象的ref

<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代理的原始对象

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  

  

 

  

  

  

 

posted @ 2022-11-01 19:48  小白不白10  阅读(234)  评论(0编辑  收藏  举报