快速打通 Vue 3(二):响应式对象基础

很激动进入了 Vue 3 的学习,作为一个已经上线了三年多的框架,很多项目都开始使用 Vue 3 来编写了

这一组文章主要聚焦于 Vue 3 的新技术和新特性

如果想要学习基础的 Vue 语法可以看我专栏中的其他博客
Vue(一):Vue 入门与 Vue 指令
Vue(二):计算属性与 watch 监听器
Vue(三):Vue 生命周期与工程化开发
一篇文章快速通关 Vuex(适合小白学习)
Vue 框架前导:详解 Ajax
快速打通 Vue 3(一):基本介绍与组合式 API
上一篇 Vue3 博客快速打通 Vue 3(一):基本介绍与组合式 API

后续还会继续更新,期待大家的关注!

04. 响应式数据 ------ ref 与 reactive

关于响应式数据的官方介绍

4.1 ref 创建响应式数据

要点概览:

  1. 要使用需要加入 .value
  2. 模板会自动添加

通过上面的尝试我们知道,在 setup 中声明的数据默认 不是响应式的 ,我们需要手动将其声明为响应式,这里就需要 ref 函数。

语法 let xxx = ref(初始值),返回值是一个 RefImpl 的实例 对象

对象中的 value 属性 是响应式的,相当于 ref 为我们的数据上了一层包装,数据放在其中的 value 属性上,我们操控数据要通过操控其 value 属性来实现

这意味着我们只写 sum += 1 是无法实现我们想要的效果的

模板会自动为我们添加 value 属性,模板中直接写 {``{数据名}} 即可

html 复制代码
<template>
  <div class="person">
    <h2>当前数字的为 {{ sum }}</h2>
    <button @click="addOne">+1</button>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue';
  let sum = ref(0);
  function addOne() {
    console.log(sum);
    sum.value += 1;
  }
</script>

我们来打印一下整个对象

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

要点概览

  1. reactive 函数只能创建响应式对象数据
  2. 创建的响应式数据是深层次[1](#1)
  3. 修改对象为新对象会破坏其响应式特性

响应式数据除了基本的数据类型还包括对象类型,上面的 ref 函数也可以创建对象类型的响应式数据

但是要借助 reactive 函数实现,所以我们这里先来说一下 reactive 函数

reactive 函数 只能 创建对象类型的响应式数据

语法:let xxx = reactive(源对象)

返回值是一个 Proxy 的实例对象,简称响应式对象

html 复制代码
<template>
  <div class="person">
    <h2>姓名:{{person.name}}</h2>
    <h2>年龄:{{person.age}}</h2>
    <button @click="changeName">changeName</button>
  </div>
</template>

<script setup lang="ts">
import { reactive } from 'vue';
  let person = reactive({
    name: 'Tom',
    age: '18'
  })
  function changeName () {
    person.name = 'Jack';
  }
</script>


reactive 声明的对象是 深层次

html 复制代码
<template>
  <div class="person">
    <h2>数字:{{a.b.c}}</h2>
    <button @click="change">change</button>
  </div>
</template>

<script setup lang="ts">
import { reactive } from 'vue';
  let a = reactive({
    b: {
      c: 111
    }
  })
  function change () {
    a.b.c = 1;
  }
</script>

上面声明了一个嵌套对象,我们来尝试修改嵌套对象中的数据。


需要注意的是,我们不能修改对象,reactive 是将原本地址上的对象变为响应式对象。

但如果我们创建一个新的对象并且赋值给它,就不是响应式的了(用的不多但需要了解)。

官方文档:

值得注意的是,reactive() 返回的是一个原始对象的 Proxy,它和原始对象是不相等的。

只有代理对象是响应式的,更改原始对象不会触发更新。因此,使用 Vue 的响应式系统的最佳实践是 仅使用你声明对象的代理版本

javascript 复制代码
  function changePerson() { 
    person = {name: 'Jack', age: 10};
  }

比如我们尝试修改,界面是没有任何变化的

4.3 ref 声明对象类型的响应式数据

要点概览:

  1. ref 的响应式对象是借助 reactive 函数创建的
  2. 使用响应式对象仍然需要 .value

上面我们提到 ref 函数也可以创建对象类型的响应式数据,让我们来尝试一下:

html 复制代码
<template>
  <div class="person">
    <h2>姓名{{person.name}}</h2>
    <h2>年龄{{person.age}}</h2>
    <button @click="changeAge">changeAge</button>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue';
  let person = ref({
    name: 'Tom',
    age: 18
  })
  function changeAge() {
    console.log(person);  
    person.value.age++;
  }
</script>

还是经典的修改年龄的界面,我们打印出来创建的这个 person 对象

非常熟悉的内容,正是我们上面 reactive 函数创建的响应式对象

我们使用 ref 创建的对象仍然需要加上 .value

4.4 ref 与 reactive

要点概述:

  1. 推荐使用 ref 作为主要 API
  2. reactive 在某些特定情况可以使用

根据官方文档,reactive 有如下的缺点:

  1. 有限的值类型 :它只能用于对象类型 (对象、数组和如 MapSet 这样的集合类型)。它不能持有如 stringnumberboolean 这样的原始类型

  2. 不能替换整个对象:由于 Vue 的响应式跟踪是通过属性访问实现的,因此我们必须始终保持对响应式对象的相同引用。这意味着我们不能轻易地"替换"响应式对象,因为这样的话与第一个引用的响应性连接将丢失:

    js

  3. 对解构操作不友好:当我们将响应式对象的原始类型属性解构为本地变量时,或者将该属性传递给函数时,我们将丢失响应性连接:

所以一般推荐使用 ref 作为主要的 API

但是当我们的对象深度很深的时候,例如表单对象,我们可能要写无数个 value 比较影响代码的美观,这时候在不影响的情况下是可以使用 reactive 的。


补充:关于解构

在Vue中,解构操作通常用于从对象或数组中提取数据,并将其赋值给变量,以便在Vue组件中使用。Vue支持解构赋值语法,让开发者可以更方便地操作组件中的数据。

  1. 对象解构

在Vue组件中,可以使用对象解构从组件的数据对象中提取数据。例如:

javascript 复制代码
javascriptCopy codeexport default {
  data() {
    return {
      person: {
        name: 'Alice',
        age: 30,
        city: 'New York'
      }
    };
  },
  mounted() {
    const { name, age, city } = this.person;
    console.log(name); // 输出:Alice
    console.log(age); // 输出:30
    console.log(city); // 输出:New York
  }
};
  1. 数组解构

数组解构可以用于解构数组中的数据。例如:

javascript 复制代码
javascriptCopy codeexport default {
  data() {
    return {
      numbers: [1, 2, 3, 4, 5]
    };
  },
  mounted() {
    const [first, second, third] = this.numbers;
    console.log(first); // 输出:1
    console.log(second); // 输出:2
    console.log(third); // 输出:3
  }
};
  1. 在模板中使用解构

还可以在Vue的模板中使用对象解构,例如:

javascript 复制代码
htmlCopy code<template>
  <div>
    <p>{{ person.name }}</p>
    <p>{{ person.age }}</p>
    <p>{{ person.city }}</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      person: {
        name: 'Alice',
        age: 30,
        city: 'New York'
      }
    };
  }
};
</script>

在模板中,可以直接通过{``{ 变量名 }}的方式使用解构后的数据。


4.5 toRefs 与 toRef

要点概览:

  1. 响应式对象的属性转换为 ref 对象
  2. toRefs 批量转化呢,toRef 实现单个转换
  3. 需要加 .value 操控

我们来尝试将对象解构,将其中的属性交给模板 <template> 去显示

html 复制代码
<template>
  <div class="person">
    <h2>姓名{{name}}</h2>
    <h2>年龄{{age}}</h2>
    <button @click="changeAge">changeAge</button>
  </div>
</template>

<script setup lang="ts">
import { reactive } from 'vue';
  let person = reactive({
    name: 'Tom',
    age: 18
  })
  let {name, age} = person;
  function changeAge() {
    console.log(person);  
    age.value++;
  }
</script>

那这个属性是响应式的吗?

很明显不是,无法将改变的属性显示在网页上,那应该怎么将结构出来的属性变为响应式的呢?

就需要这里讲的 toRefs

语法 let {name, age} = toRefs(person);

这样数据就变为响应式的了

toReftoRefs 作用相同,但可以指定需要将哪个属性变为响应式的

语法:let name = toRef(person, 'name')

这样就可以将响应式对象中的属性也设置为响应式的

转换出来的是 ref 对象,很明显操控需要加 .value


补充------插件自动填充 .value

我们有时候会忘记添加 .value 或者会加错,这是和可以借助插件来自动为我们添加 .value

这里用到的插件是我们之前提到的 Vue Language Features (Volar)

打开设置界面 -> 拓展 -> Volar -> 打开 Auto Insert: Dot Value


  1. 深层次即对象内嵌套的对象也会被声明为响应式的对象。 ↩︎
相关推荐
dsyyyyy11015 分钟前
JavaScript变量
开发语言·javascript·ecmascript
kyriewen35 分钟前
手写 Promise.all、race、any:不到 30 行代码,解决并发异步的所有姿势
前端·javascript·面试
胡志辉的博客2 小时前
深入浅出理解浏览器事件循环:从一道输出题讲到 Chrome 源码
前端·javascript·chrome·chromium·event loop
代码不加糖2 小时前
js中不会冒泡的事件有哪些?
前端·javascript·vue.js
懂懂tty2 小时前
Vue2与Vue3之间API差异
前端·javascript·vue.js
老毛肚3 小时前
软件测试期末考试
vue.js
小二·3 小时前
Next.js 15 全栈开发实战
开发语言·javascript·ecmascript
杨若瑜4 小时前
本地开发环境慢?localhost的锅!
vue.js
Rain5094 小时前
2.1 Nest.js 项目初始化与模块化架构
开发语言·前端·javascript·后端·架构·数据分析·node.js
拾年2755 小时前
从零手写 Ajax:用原生 XHR 搭建前后端交互全流程
前端·javascript·ajax