vue3-reactive系列

109 阅读1分钟

Reactive全家桶

reactive

用来定义复杂的数据类型:对象、数组

reactive 源码约束了我们的类型,ref支持所有类型

绑定普通的数据类型不被允许的 会报错

绑定普通数据类型用 ref,你如果用 ref 去绑定 对象 或者 数组复杂的数据类型 你去看源码里面其实也是 去调用 reactive,使用 reactive 去修改值无须 .value

<template>
  <div>
    <p>{{rea}}</p>
    <input type="text" v-model="rea.name">
    <hr>
    <input type="text" v-model="rea.age">
  </div>
</template>

<script setup lang="ts">
import { ref,reactive} from 'vue'
//ref支持所有类型    reactive 复杂的数据类型
let rea=reactive({
  name:"zs",
  age:23
})
//reactive  修改值不需要  .value
rea.age=18
</script> 

<style>
</style>

数据异步赋值问题

这样直接赋值页面是不会变化的因为会脱离响应式

<template>
  <div>
    <ul>
      <li v-for="item in list" :key="item">{{item}}</li>
    </ul>
    <button @click="add">add</button>
  </div>
</template>

<script setup lang="ts">
import { ref,reactive} from 'vue'

let list=reactive([])

const add=()=>{
  setTimeout(()=>{
    let res=['1','2','3']
    list=res;//不能直接赋值,会破坏响应式对象
    console.log(list);
  },1000)
}
</script> 
<style>
</style>

解决方案push

<template>
  <div>
    <ul>
      <li v-for="item in list" :key="item">{{item}}</li>
    </ul>
    <button @click="add">add</button>
  </div>
</template>

<script setup lang="ts">
import { ref,reactive} from 'vue'

let list=reactive([])

const add=()=>{
  setTimeout(()=>{
    let res=['1','2','3']
    list.push(...res)//解决方案 push
    console.log(list);
  },1000)
}
</script> 
<style>
</style>

解决方案-解构、包裹一层对象

<template>
  <div>
    <ul>
      <li v-for="item in list.arr" :key="item">{{item}}</li>
    </ul>
    <button @click="add">add</button>
  </div>
</template>

<script setup lang="ts">
import { ref,reactive} from 'vue'

let list=reactive({//包裹一层对象
  arr:[]
})

const add=()=>{
  setTimeout(()=>{
    let res=['1','2','3']
    list.arr=res
    console.log(list);
  },1000)
}
</script> 
<style>
</style>

readonly

拷贝一份proxy对象将其设置为只读

受原始对象影响

<template>
  <div>
    <button @click="show">show</button>
  </div>
</template>

<script setup lang="ts">
import { ref,reactive,readonly} from 'vue'

let obj=reactive({
 name:'原始对象'
})

const read=readonly(obj)

const show=()=>{
//obj.name='修改后'
read.name='read修改'
console.log(obj,read);
}
</script> 
<style>
</style>

shallowReactive

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

浅响应式

只处理对象最外层属性的响应式

<template>
  <div>
    <p>shallowReactive:{{obj.foo.bar.num}}</p>
    <button @click="edit">add</button>
  </div>
</template>

<script setup lang="ts">
import { ref,reactive,readonly,shallowReactive} from 'vue'

let obj=shallowReactive({
  foo:{
    bar:{
      num:1
    }
  }
})

const edit=()=>{
  obj.foo.bar.num+=1
  console.log(obj.foo.bar.num)//后台变,视图不变
}
</script> 
<style>
</style>

只能处理第一层的属性,如下,

第一层被改变后其他层也会变化(视图和后台都变化)

只触发第三层、第二层只有后台会变

<template>
  <div>
    <p>第三层:{{obj.foo.bar.num}}</p>
    <button @click="edit3">add</button>
    <hr>
    <p>foo.name:{{obj.foo.name}}</p>
    <button @click="edit2">add</button>
    <hr>
    <p>第一层:{{obj.str}}</p>
    <button @click="edit1">add</button>
  </div>
</template>

<script setup lang="ts">
import { ref,reactive,readonly,shallowReactive} from 'vue'

let obj=shallowReactive({
  str:"第一层",
  foo:{
    name:"第二层",
    bar:{
      num:1
    }
  }
})

const edit3=()=>{
  obj.foo.bar.num+=1
  console.log(obj.foo.bar.num)
}
const edit2=()=>{
  obj.foo.name="修改后"
  console.log(obj.foo.name);
}
const edit1=()=>{
  obj.str="第一层被修改"
  console.log(obj.str);
}
</script> 
<style>
</style>

shallowReactive被reactive影响

<template>
  <div>
    <p>shallowReactive:{{obj.foo.bar.num}}</p>
    <p>reactive:{{obj1.name}}</p>
    <button @click="edit">add</button>
  </div>
</template>

<script setup lang="ts">
import { ref,reactive,readonly,shallowReactive} from 'vue'

let obj1=reactive({name:"zs"})

let obj=shallowReactive({
  foo:{
    bar:{
      num:1
    }
  }
})

const edit=()=>{
  obj.foo.bar.num+=1
  console.log(obj.foo.bar.num)
  console.log("----------------");
  obj1.name="change"
  console.log(obj1.name);
}
</script> 
<style>
</style>

都变化了