vue3-03-创建响应式数据的几种方法


此总结是我看尚硅谷视频总结的,所以可能会有总结不到位或不清楚的情况
适合学过的人回来复习的时候看

一、 ref 创建:响应式数据

ref 可以定义:基本类型、对象类型的响应式数据

1)ref 创建:基本类型的响应式数据

  • vue3项目,在setup中创建的变量,例如 let num = 100 中的num默认不是响应式数据
  • 利用 ref 可以创建基本类型的响应式数据

在这里插入图片描述

2)ref 创建:对象类型的响应式数据

若 ref 接收的是对象类型,内部其实也是调用了 reactive 函数

<script lang="ts" setup name="Person111">
  import { ref } from "vue"
  // 数据
  let car = ref({ brand: '奔驰', price: 100})
  let game = ref([
    { id: 10001, name: '原神'},
    { id: 10002, name: '双人成行'},
    { id: 10003, name: '头七怪谈'}
  ])

  // 方法
  function changePrice() { // 改变汽车价格
    car.value.price += 10
    console.log(car.value.price)
  }

  function changeGame() { // 改变游戏名称
    game.value[1].name = '纸嫁衣'
  }
  
  function changeCar() { // 更改车数据
    // car.value.brand = '小电驴'
    // car.value.price = 0.3
    // 上面两行的效果等同下面的这个代码,即使把整个对象赋给car.value,car也不会失去响应式
    car.value = { '小电驴', price: 0.3 }  
  }
</script>

在这里插入图片描述

3)volar 插件自动添加 .value

vscode左下角点击设置,搜索Dot Value,勾选,如下图
在这里插入图片描述

4)customRef 自定义 ref

customRef: 创建一个自定义的ref,并对其依赖项跟踪和更新触发进行逻辑控制

举例: 想要1s后(有延迟效果)响应式数据更新
注意:下例中 clearTimeout(timer)起到防抖效果

useSumRef.ts

import { customRef } from 'vue'
export default function (initValue: string, delay: number) {
  // 使用Vue提供的customRef定义响应式数据
  // track:跟踪    trigger:触发
  let msg = customRef((track, trigger) => {
    let timer: number
    return {
      // get何时调用? -- msg被读取时
      get(){
        track() // 告诉Vue数据msg很重要,你要对msg进行持续关注,一旦msg变化就去更新
        return initValue
      },
      // set何时调用? -- msg被修改时
      set(value){
        clearTimeout(timer)
        timer = window.setTimeout(() => {
          initValue = value
          trigger() // 通知Vue数据msg变化了
        }, delay)
      }
    }
  })
  return { msg }
}

App.vue

<template>
  <div class="app">
    <h2>{{ msg }}</h2>
    <input type="text" v-model="msg">
  </div>
</template>

<script setup lang="ts" name="App">
  import {ref} from 'vue'
  import useMsgRef from './useMsgRef'
  // 使用Vue提供的默认ref定义响应式数据,数据一变,页面就更新
  // let msg = ref('你好')

  // 使用useMsgRef来定义一个响应式数据且有延迟效果
  let {msg} = useMsgRef('你好',1000)
</script>

二、 reactive 创建:响应式数据

  • reactive 只能创建对象类型的响应式数据
  • 在JS中可以直接操作对象类型数据,不需要.value

1)reactive 创建对象类型的响应式数据

在这里插入图片描述

<template>
  <div class="person">
    <h2>汽车信息:一辆{{ car.brand }}品牌的车,价格为{{ car.price }}</h2>
    <button @click="changePrice">改变汽车价格</button>
    <h2>游戏信息列表</h2>
    <ul>
      <li v-for="item in game" :key="item.id">{{ item.name }}</li>
    </ul>
    <button @click="changeGame">改变游戏名称</button>
    <h4>深层次{{ shen.a.b.id }}</h4>
    <button @click="changeShen">测试</button>
  </div>
</template>

<script lang="ts" setup name="Person111">
  import { reactive } from "vue"
  // 数据
  let car = reactive({ brand: '奔驰', price: 100})
  let game = reactive([
    { id: 10001, name: '原神'},
    { id: 10002, name: '双人成行'},
    { id: 10003, name: '头七怪谈'}
  ])
  let shen = reactive({
    a: {
      b: {
        id: 4
      }
    }
  })

  // 方法
  function changePrice() {
    car.price += 10
    console.log(car.price)
  }

  function changeGame() {
    game[1].name = '纸嫁衣'
  }

  function changeShen() {
    shen.a.b.id = 100
  }
</script>

2)reactive更新对象数据

注意: reactive重新分配对象 ,会失去响应式

场景:

<button @click="changeCar">点击修改车数据</button>
...
let car = ref({ brand: '奔驰', price: 100})
...
function  changeCar()  {
// { brand: '小电驴', price: 0.3 } ,要更新这个信息给car
}

方法一:手动赋值

function  changeCar()  {
// { brand: '小电驴', price: 0.3 } ,要更新这个信息给car
// 弊端:从后端返回的数据可以一个对象里有很多属性,一个一个赋值也太麻烦了
    Person.name = 'lisi'
    Person.age = 20
}

方法二:对象整体赋值

function  changeCar()  {
    // { brand: '小电驴', price: 0.3 } ,要更新这个信息给car

    // 下面这个写法页面可以更新, 而且这个写法car不会失去响应式更新
    Object.assign(car, { brand: '小电驴', price: 0.3})
    
    // 下面是两种错误写法
    // car = { brand: '小电驴', price: 0.3} // 这么写,数据更新了,页面不更新,不是响应式的了
    // car = reactive({ brand: '小电驴', price: 0.3}) // 这么写页面不更新的
}

3)toRefs 与 toRef

在这里插入图片描述

<template>
  <div class="box">
    <div>姓名:{{ person.name }}</div>
    <div>年龄:{{ person.age }}</div>
    <br>
    <button @click="changeName">点击修改姓名</button>
    <button @click="changeAge">点击修改年龄</button>
    <div>叫啥:{{ test }}</div>
  </div>
</template>

<script lang="ts" setup name="Person111">
  import { ref, reactive, toRefs, toRef } from "vue"

  // 数据
  let person = reactive({
    name: '张三',
    age: 18
  })
  let { name, age } = toRefs(person)
  console.log(name)  // 转换为了ref基本数据类型的响应式数据
  console.log(age)   // 相当于是把每一项都拆开了,但是每一项都还是ref响应式的
  let test = toRef(person, 'name') // 这个当然也是响应式的

  function changeName() {
    // person.name = 'zhang-san'
    name.value = 'zhang-san'
  }

  function changeAge() {
    // person.age += 1
    age.value += 1
  }

</script>

<style>
  .box {
    padding: 20px;
    background-color: skyblue;
    box-shadow:  0 0 10px;
    border-radius: 20px;
  }
  button {
    margin-right: 20px;
  }
</style>

三、 ref 和 reactive 的区别

在这里插入图片描述

四、其他补充

1)shallowRef、shallowReactive

1. shallowRef

在这里插入图片描述

举例:
在这里插入图片描述

运行效果:只有 “sum+1” 和 “修改整个人” 的功能能用,另外两个无效

在这里插入图片描述

2. shallowReactive

在这里插入图片描述

举例:
在这里插入图片描述

运行效果:只有 “修改品牌” 和 “修改整个车” 功能能用,另外两个无效

在这里插入图片描述

3. 总结

在这里插入图片描述

2)readonly 与 shallowReadonly

1. readonly

效果:

  • original显示什么,readOnlyCopy就显示什么,original修改,readOnlyCopy也会跟着修改
  • original可以修改自己的值,readOnlyCopy什么都不能修改,只能读

在这里插入图片描述

2. shallowReadonly

效果:

  • original显示什么,shallowReadOnlyCopy就显示什么,original修改shallowReadOnlyCopy也会跟着修改
  • original可以修改自己的值,shallowReadOnlyCopy第一层数据不能修改,但是深层次(第二层、第三层…)数据能够修改

举例:

  • shallowReadOnlyCopy不能修改“name”和“hobby整体”,但能修改hobby.eat和hobby.sport的值
    在这里插入图片描述
    在这里插入图片描述

3)toRaw 与 markRaw

1. toRaw

在这里插入图片描述

使用示例:
在这里插入图片描述

2. markRaw

在这里插入图片描述

  • 12
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue 3中的数据响应式是通过使用选项式API和组合式API中的几种函数来实现的。其中,ref()函数用于创建一个基本类型的响应式数据,reactive()函数用于创建一个对象类型的响应式数据,toRef()函数用于创建一个与另一个响应式数据相绑定的引用,toRefs()函数用于将一个响应式对象转换为一组响应式的引用。 具体来说,ref()函数可以将一个普通的JavaScript值转换为一个响应式数据。例如,你可以使用ref()函数将一个数字、字符串或布尔值转换为一个响应式数据,然后在视图中使用该数据,并在数据改变时自动更新视图。 reactive()函数则可以将一个普通的JavaScript对象转换为一个响应式对象。这意味着当对象中的某个属性发生改变时,Vue会自动通知到使用该属性的代码,使得视图能够及时更新。这种响应式对象可以包含任意深度的嵌套属性。 toRef()函数可以用来创建一个与另一个响应式数据相绑定的引用。这意味着当原始的响应式数据发生改变时,与之绑定的引用也会随之改变。这在一些特定的场景下非常有用,例如在组件之间共享响应式数据时。 最后,toRefs()函数可以将一个响应式对象转换为一组响应式的引用。这样做的好处是可以方便地在组件的模板中使用这些引用,而无需在每个引用前面加上.value来访问其值。 总结起来,Vue 3中的数据响应式是通过选项式API和组合式API中的ref()、reactive()、toRef()和toRefs()等函数来实现的。这些函数能够将普通的JavaScript值或对象转换为响应式数据,使得数据的变化能够自动更新视图。<span class="em">1</span><span class="em">2</span><span class="em">3</span>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值