上篇咱介绍了 CompositionAPI, 其核心思想是直接在函数作用域内定义响应式状态变量,并将从多个函数中得到的状态组合起来处理复杂问题.

然后初介绍了 setup 函数的作用, 即其是在 created 实例完全初始化之前调用的, 因此不能用 this, 它的主要作用就可以是管理我们接下来要介绍的 API. 在项目中通常扮演一个"任务调度" 的角色, 对整个单页面的逻辑起一个核心调度的作用.

响应式变量

首先, 注意上面这里有个关键词叫 响应式状态变量 那我们先用一个案例来认识该现象.

<!DOCTYPE html>
<html lang="en"> <head>
<title>响应式变量</title>
<script src="https://unpkg.com/vue@3"></script>
</head> <body>
<div id="root"></div>
<script>
const app = Vue.createApp({
template: `<div>{{name}}</div>`, setup (props, context) {
let name = "youge"
// 延时器的作用是 2秒后, 将 name 的值 改为 "cj"
setTimeout(() => {
name = 'cj'
}, 2000); return { name }
}
})
const vm = app.mount('#root') </script>
</body> </html>

经过 2 秒后, 发现页面的数据并没有改变 !, 这就引入了一个响应式变量的概念.

Vue3 是使用 Proxy, 它可以劫持整个data对象,然后递归返回属性的值的代理即可实现响应式;但是它的兼容性不是很好;

Vue2 是使用 Object.defineProperty,它只能劫持对象的属性,所以它需要深度遍历data中的每个属性,这种方式对于数组很不友好,而且对象观测后,新增的属性就不是响应式的,不过可以用Vue.set()来添加新的属性;

总之结论就是在 vue 中, dom 的更新由数据驱动, 将数据进行 Proxy 封装, 当数据变化时, 会自动触发模板 dom 的更新啦.

ref

像 ref, reactive 他们都是将一个 vue 将数据变量封装为响应式变量的方法啦 ( ref 的底层也是 reactive) .

在使用中呢, ref 用来处理基础类型的数据 (number, string, null, boolean, undefined) 将其变为响应式.

<!DOCTYPE html>
<html lang="en"> <head>
<title>ref</title>
<script src="https://unpkg.com/vue@3"></script>
</head> <body>
<div id="root"></div>
<script>
const app = Vue.createApp({
// 当时 ref 时, 这里不需要写成 name.value, 直接 name
template: `<div>{{name}}</div>`, setup (props, context) { const { ref } = Vue
// proxy: 将 'youge' 封装成 proxy({value: 'youge'}) 的响应式
let name = ref("youge")
// 延时器的作用是 2秒后, 将 name 的值 改为 "cj"
setTimeout(() => {
// ref 底层也是 reactive, 其实是一个对象
name.value = 'cj'
}, 2000); return { name }
}
})
const vm = app.mount('#root') </script>
</body> </html>

再来一波关键点的复述, 这个蛮重要的其实, 就先不探究原理, 重在使用轮子哈:

// 1. 通过结构的方式从 Vue 中引入 ref
// 2. 响应变量 = ref(基础类型变量) 即完成包装
// 3. 通过 响应变量.value = 'xxx' 即完成数据变更
// 4. setup 直接 return 响应变量, 模板便可用, 而不用 .value 的方式 const { ref } = Vue let name = ref("youge") name.value = 'newValue' `<div>{{name}}</div>`,

reactive

同 ref 一样的作用 ( ref 基于 reactive) 用来将引用类型数据 ( object, array, function ... ) 等给封装为响应式变量啦.

当然普通类型也是可以的, 就 reactive 的适普性会更强哦. 还是同上的例子, 我们用 reactive 来改写一波:

<!DOCTYPE html>
<html lang="en"> <head>
<title>reactive</title>
<script src="https://unpkg.com/vue@3"></script>
</head> <body>
<div id="root"></div>
<script>
const app = Vue.createApp({
template: `
<div>{{nameObj}}</div>
<div>{{nameObj.name}}</div>
`, setup (props, context) { const { reactive } = Vue
// proxy: 将 { name: 'youge' } 封装成 proxy({name: 'youge'}) 的响应式
let nameObj = reactive({ name: 'youge' })
setTimeout(() => {
nameObj.name = 'cj'
}, 2000); return { nameObj }
}
})
const vm = app.mount('#root') </script>
</body> </html>

当然数组也是一样的啦.

setup (props, context) {
const { reactive } = Vue let arr = reactive(['a', 'b', 'c']) setTimeout(() => {
arr[1] = 'cj'
}, 2000); return { arr }
}

这样通过 ref 和 reactive 将数据封装为响应式变量,则就可以代替掉原来的 data ( ) 方法啦. 这个会更加通用和方便维护的哦.

readonly

即对响应式变量进行 "只读" 的限定哈.

setup (props, context) {

    const { reactive, readonly } = Vue
let arr = reactive(['a', 'b', 'c']) // 只要用了 readonly 就不能修改啦, 会警告的
const copyArr = readonly(arr)
setTimeout(() => {
arr[1] = 'cj'
copyArr[0] = 666
}, 2000); return { arr, copyArr }
}

toRefs

它的作用其实就是将咱响应式变量中的值, 通过结构的方式获取到时也是一个响应式变量的值, 可以被模板直接引用, 就不用在模板中写类似 xxxObj.xxx 的写法啦.

一句话: 将 reactive 的数据转为 ref 数据, 也是响应式的啦.

在本例中, proxy( { name: 'youge' }) 中的值给再包装为 { name: proxy( { value: 'youge' })} 这样.

<!DOCTYPE html>
<html lang="en"> <head>
<title>toRefs</title>
<script src="https://unpkg.com/vue@3"></script>
</head> <body>
<div id="root"></div>
<script>
const app = Vue.createApp({
template: `
<div>{{name}} : {{age}}</div>
`, setup(props, context) { const { reactive, toRefs } = Vue
let dataObj = reactive({ name: 'youge', age: 18 }) setTimeout(() => {
dataObj.name = 'cj'
dataObj.age = 26
}, 2000); // toRefs: proxy({name: 'cj', age: 18}) 转为: // name: proxy({value: 'cj'}),
// age: proxy({value: 18}) // 然后直接来一波结构赋值
const { name, age } = toRefs(dataObj) return { name, age }
}
})
const vm = app.mount('#root') </script>
</body> </html>

小结

  • ref 和 reactive 都是对 js 数据类型进行响应式的封装, ref 针对基础类型, reactive 针对引用类型
  • ref 原理: proxy: 将 'youge' 封装成 proxy({value: 'youge'}) 的响应式
  • reactive 原理: proxy: 将 { name: 'youge' } 封装成 proxy({name: 'youge'}) 的响应式
  • toRefs 的作用: 将 proxy({name: 'cj' }) 转化为 { name: proxy({ value: 'cj' })}

vue3 基础-API-响应式 ref, reactive的更多相关文章

  1. Vue3中的响应式对象Reactive源码分析

    Vue3中的响应式对象Reactive源码分析 ReactiveEffect.js 中的 trackEffects函数 及 ReactiveEffect类 在Ref随笔中已经介绍,在本文中不做赘述 本 ...

  2. Vue3中的响应式api

    一.setup文件的认识 特点1:script 中间的内容就是一个对象 特点2:script 在第一层 定义的方法 或者 变量 => 就是这个对象 属性  => 顶层的绑定回被暴露给模板( ...

  3. Paip.Php Java 异步编程。推模型与拉模型。响应式(Reactive)”编程FutureData总结... 1

    Paip.Php  Java 异步编程.推模型与拉模型.响应式(Reactive)"编程FutureData总结... 1.1.1       异步调用的实现以及角色(:调用者 提货单) F ...

  4. Bootstrap<基础十> 响应式实用工具

    Bootstrap 提供了一些辅助类,以便更快地实现对移动设备友好的开发.这些可以通过媒体查询结合大型.小型和中型设备,实现内容对设备的显示和隐藏. 需要谨慎使用这些工具,避免在同一个站点创建完全不同 ...

  5. Java9第四篇-Reactive Stream API响应式编程

    我计划在后续的一段时间内,写一系列关于java 9的文章,虽然java 9 不像Java 8或者Java 11那样的核心java版本,但是还是有很多的特性值得关注.期待您能关注我,我将把java 9 ...

  6. vue3剖析:响应式原理——effect

    响应式原理 源码目录:https://github.com/vuejs/vue-next/tree/master/packages/reactivity 模块 ref: reactive: compu ...

  7. Unity基于响应式编程(Reactive programming)入门

    系列目录 [Unity3D基础]让物体动起来①--基于UGUI的鼠标点击移动 [Unity3D基础]让物体动起来②--UGUI鼠标点击逐帧移动 时光煮雨 Unity3D让物体动起来③—UGUI DoT ...

  8. WebFlux基础之响应式编程

    上篇文章,我们简单的了解了WebFlux的一些基础与背景,并通过示例来写了一个demo.我们知道WebFlux是响应式的web框架,其特点之一就是可以通过函数式编程方式配置route.另外究竟什么是响 ...

  9. iOS开发之OC篇-响应式编程Reactive Cocoa

    一.Reactive Cocoa 介绍 Reactive Cocoa 是 iOS 开发的一个 "重量级" 框架 高大上的概念:响应式编程 核心概念:信号 Signal 官方网站:h ...

  10. Vue.js 源码分析(四) 基础篇 响应式原理 data属性

    官网对data属性的介绍如下: 意思就是:data保存着Vue实例里用到的数据,Vue会修改data里的每个属性的访问控制器属性,当访问每个属性时会访问对应的get方法,修改属性时会执行对应的set方 ...

随机推荐

  1. 泰山派(Ubuntu 20.0)更换软件源

    泰山派更换软件源 1.编辑apt软件包源获取文件 vim /etc/apt/sources.list 2.更换为下面的源 deb http://mirrors.ustc.edu.cn/ubuntu-p ...

  2. zabbix - [01] 概述

    参考:Zabbix教程(Zabbix监控系统精讲) 一.监控介绍 Cacti Cacti 是一套基于PHP.MySQL.SNMP以及RRD Tool开发的监测图形分析工具,Cacti 是使用轮询的方式 ...

  3. 机器学习 | 强化学习(1) | 马尔科夫决策过程(MDP)概论

    最近在搞强化学习(Reinforcement Learning),打算把之前写的笔记整理一下 本文基于大卫 希尔维(David Silver)教授的强化学习概论课程,视频中所采用的样例学生马尔科夫链( ...

  4. 【Abaqus】Composite Layup建模

    abaqus 的3个复合材料建模途径: 传统的material->section->orientation->step->job的建模方式 Composite Layup建模方 ...

  5. 基于近红外与可见光双目摄像头的人脸识别与活体检测,文末附Demo

    基于近红外与可见光双目摄像头的活体人脸检测原理 人脸活体检测(Face Anti-Spoofing)是人脸识别系统中的重要一环,它负责验证捕捉到的人脸是否为真实活体,以抵御各种伪造攻击,如彩色纸张打印 ...

  6. [Qt基础-06] QButtonGroup

    QButtonGroup 本文主要根据QT官方帮助文档以及日常使用,简单的介绍一下QButtonGroup的功能以及基本使用 文章目录 QButtonGroup 简介 信号和槽 简介 有的时候,我们会 ...

  7. Redis会遇到的15个坑

    前言 如果你在使用 Redis 时,也遇到过以下这些「诡异」的场景,那很大概率是踩到「坑」了. 究竟是什么原因,导致的这些问题呢? 我把这些问题划分成了三大部分: 常见命令有哪些坑? 数据持久化有哪些 ...

  8. IvorySQL 4.2 发布

    IvorySQL 4.2 已于 2025 年 1 月 13 日正式发布.新版本全面支持 PostgreSQL 17.2,并修复了多项 bug. 增强功能 PostgreSQL 17.1 增强功能 确保 ...

  9. 基于RK3568 + FPGA国产平台的多通道AD实时采集显示方案分享

    在工业控制与数据采集领域,高精度的AD采集和实时显示至关重要.今天,我们就来基于瑞芯微RK3568J + FPGA国产平台深入探讨以下,它是如何实现该功能的.适用开发环境如下: Windows开发环境 ...

  10. static修饰成员变量的特点及static修饰成员变量内存图解-java se进阶 day01

    1.static介绍 static是静态的意思,它可以用于修饰成员变量和成员方法 2.static的特点 1.被static修饰了的成员变量,可以被类中的所有对象所共享 虽然stu02没有给schoo ...