前端基础之《Vue(4)—响应式原理》

news2025/4/21 21:58:12

一、什么是响应式

1、响应式英文reactive
当你get/set一个变量时,你有办法可以“捕获到”这种行为。

2、一个普通对象和一个响应式对象对比

(1)普通对象

<script>
    // 这种普通对象不具备响应式
    var obj1 = {
        a: 1,
        b: 2
    }
</script>

普通对象,当我们获取、修改属性的时候没办法捕获get/set行为(这种普通对象是不具备响应式的):

(2)响应式对象

<script>
    var obj2 = {}
    var a = 1
    var b = 2
    // 给obj2这个对象添加一个新属性
    Object.defineProperty(obj2, 'a', {
        get() {
            console.log(`有人访问了a`)
            return a
        },
        set(val) {
            console.log(`有人修改了a`)
            a = val
        }
    }) // 给obj2对象加一个a属性
    
    Object.defineProperty(obj2, 'b', {
        get() {
            console.log(`有人访问了b`)
            return b
        },
        set(val) {
            console.log(`有人修改了b`)
            b = val
        }
    }) // 给obj2对象加一个b属性
    
</script>

当获取、修改obj2属性的时候,会触发钩子函数。obj2对象多了get和set函数。obj2具有了响应式:

二、响应式原理

1、流程图

2、代码

<html>
<head>
    <title>响应式原理</title>
    
</head>
<body>
    输入:<input id="ipt" type="text" />
    输出:<h2 id="h2" style='display:inline-block;'></h2>
    <hr>
    <h1 id="h1"></h1>
    <button id="btn">自增</button>

    <script>
        // 这是模拟data选项(普通的对象)
        const data = {
            name: '张三',
            num: 1
        }

        // 这是模拟vue组件实例
        const app = {}

        // 对data进行遍历,['name', 'num']
        // 遍历完了把数组放到app上
        // 生命周期的第一阶段(劫持,就是添加get/set)
        Object.keys(data).forEach(k=>{
            Object.defineProperty(app, k, {
                // handle加劫持
                get() {
                    console.log(`getter ${k}`) // touch操作
                    return data[k]
                },
                set(val) {
                    console.log(`setter ${k}`) // notify操作
                    data[k] = val
                    
                    watcher(k) // 通知更新界面
                }
            })
        })

        // dep对象专门用于依赖收集的
        const dep = {
            name: [],
            num: []
        }

        // 生命周期的第二阶段(相当于挂载阶段)
        // Collect as Dependency依赖收集
        function init() {
            // 模拟v-model='name'
            dep['name'].push(() => { // 依赖收集
                document.getElementById('ipt').value = app.name // get功能
            })
            // 绑定input事件
            document.getElementById('ipt').addEventListener('input', ev => {
                app.name = ev.target.value // set功能
            })

            // 模拟v-text='name'
            dep['name'].push(() => {
                document.getElementById('h2').innerText = app.name // get功能
            })

            dep['num'].push(()=> {
                document.getElementById('h1').innerText = app.num // get功能
            })

            document.getElementById('btn').addEventListener('click', ev => {
                app.num++ //set功能
            })

            // 第一次更新DOM
            Object.keys(dep).forEach(k=>watcher(k))
        }

        // 封装一个Watcher
        function watcher(k) {
            dep[k].forEach(fn=>fn()) // 循环调用变量依赖的function
        }

        // 调用init
        init()
    </script>

</body>
</html>

3、说明
(1)生命周期的第一阶段(劫持,就是添加get/set)
"Touch"和Notify
(2)生命周期的第二阶段(相当于挂载阶段)
把DOM放在真实的DOM上渲染,Collect as Dependency依赖收集
收集的结果是得到一个Watcher,通过re-render更新DOM(以后变量有变化,我通知Watcher,让Watcher再去更新界面)
(3)依赖收集
我要改变表单的值,并且要push一个依赖

二、vue的响应式原理小结

1、正常的对象是没有办法做更新的,必须要给它加钩子,才能知道它被访问

2、解释几个重要概念
劫持:使用Object.defineProperty对data选项进行遍历并添加getter/setter的钩子
touch:当指令第一次与声明式变量绑定时,第一次触发声明式变量的get钩子
依赖收集:当第一次touch时,把当前声明式变量的更新方法添加到dep依赖数组中
watcher:与声明式变量对应的DOM方法
re-render:当声明式变量被set时,Vue通知watcher更新DOM

3、响应式原理
当vue组件被创建时,在生命周期的第一阶段,vue使用Object.defineProperty()对data选项进行遍历劫持并添加get/set钩子。
在生命周期第二阶段,指令第一次与声明式变量touch时,发生依赖收集,再调用当前组件的watch第一次更新DOM,DOM视图就显示出来了。
当声明式变量发生变化时,vue再次通知watcher更新视图,这就是响应式。
 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2335653.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Go学习系列文章声明

本次学习是基于B站的视频&#xff0c;【Udemy高分热门付费课程】Golang&#xff1a;完整开发者指南&#xff08;基础知识和高级特性&#xff09;中英文字幕_哔哩哔哩_bilibili 本人会尝试输出视频中的内容&#xff0c;如有错误欢迎指出 next page: Go installation process

Go:程序结构

文章目录 名称声明变量短变量声明指针new 函数变量的生命周期 赋值多重赋值可赋值性 类型声明包和文件导入包初始化 作用域 名称 命名规则&#xff1a; 通用规则&#xff1a;函数、变量、常量、类型、语句标签和包的名称&#xff0c;开头须是字母&#xff08;Unicode 字符 &a…

Python 二分查找(bisect):排序数据的高效检索

二分查找&#xff1a;排序数据的高效检索 第二天清晨&#xff0c;李明早早来到了图书馆。今天他的研究目标是bisect模块&#xff0c;特别是其中的bisect_left和bisect_right函数。这些函数实现了二分查找算法&#xff0c;用于在已排序的序列中高效地查找元素或确定插入位置。 …

【数据结构】堆排序详细图解

堆排序目录 1、什么是堆&#xff1f;1.1、什么是大顶堆1.2、什么是小顶堆 2、堆排序的过程3、堆排序的图解3.1、将数组映射成一个完全二叉树3.2、将数组转变为一个大顶堆3.3、开始进行堆排序 4、堆排序代码 1、什么是堆&#xff1f; 堆的定义&#xff1a;在一棵完全二叉树中&a…

CST1016.基于Spring Boot+Vue高校竞赛管理系统

计算机/JAVA毕业设计 【CST1016.基于Spring BootVue高校竞赛管理系统】 【项目介绍】 高校竞赛管理系统&#xff0c;基于 DeepSeek Spring AI Spring Boot Vue 实现&#xff0c;功能丰富、界面精美 【业务模块】 系统共有两类用户&#xff0c;分别是学生用户和管理员用户&a…

安卓性能调优之-掉帧测试

掉帧指的是某一帧没有在规定时间内完成渲染&#xff0c;导致 UI 画面不流畅&#xff0c;产生视觉上的卡顿、跳帧现象。 Android目标帧率&#xff1a; 一般情况下&#xff0c;Android设备的屏幕刷新率是60Hz&#xff0c;即每秒需要渲染60帧&#xff08;Frame Per Second, FPS&a…

GPT-SoVITS:5 步实现 AI 语音克隆

在 AI 技术高速迭代的今天&#xff0c;语音合成早已突破”机械朗读“的局限 —— 从短视频创作者的虚拟配音、游戏角色的个性化声线&#xff0c;到智能客服的自然交互&#xff0c;GPT-SoVITS正凭借其强大的多模态融合能力&#xff0c;成为实现”AI 声音克隆“与“情感化语音生成…

记录:安装 Docker Desktop 时直接设置安装路径及容器存储路径

近期学用 deepseek 本地知识库的构建&#xff0c;准备尝试几个不同的 RAG 工具&#xff0c;结果基本都需要 Docker 支持&#xff0c;故又重新拾起 Docker 来安装&#xff0c;刚好看到个不用目录链接就可以直接设置安装路径的方法&#xff0c;就记录一下&#xff0c;以免以后忘…

算法训练之贪心

♥♥♥~~~~~~欢迎光临知星小度博客空间~~~~~~♥♥♥ ♥♥♥零星地变得优秀~也能拼凑出星河~♥♥♥ ♥♥♥我们一起努力成为更好的自己~♥♥♥ ♥♥♥如果这一篇博客对你有帮助~别忘了点赞分享哦~♥♥♥ ♥♥♥如果有什么问题可以评论区留言或者私信我哦~♥♥♥ ✨✨✨✨✨✨ 个…

Vagrant 安装指南:从零开始搭建开发环境

Vagrant 是一款强大的虚拟化工具&#xff0c;能够帮助开发者快速创建和管理轻量级的、可复制的开发环境。它通过与 VirtualBox、VMware 或 Hyper-V 等虚拟机提供程序结合使用&#xff0c;让你在本地轻松运行虚拟机。本文将详细介绍如何在 Windows、macOS 和 Linux 系统上安装 V…

APIGen-MT:高效生成多轮人机交互Agent数据的两阶段框架

APIGen-MT&#xff1a;高效生成多轮人机交互数据的两阶段框架 引言 随着人工智能技术的飞速发展&#xff0c;AI代理&#xff08;Agent&#xff09;已从简单的聊天机器人发展为能够执行复杂现实任务的系统&#xff0c;例如管理金融交易、安排预约和处理客户服务等。然而&#x…

【NLP】 21. Transformer整体流程概述 Encoder 与 Decoder架构对比

1. Transformer 整体流程概述 Transformer 模型的整个处理流程可以概括为从自注意力&#xff08;Self-Attention&#xff09;到多头注意力&#xff0c;再加上残差连接、层归一化、堆叠多层的结构。其核心思想是利用注意力机制对输入进行并行计算&#xff0c;从而避免传统 RNN …

《Vue Router实战教程》21.扩展 RouterLink

欢迎观看《Vue Router 实战&#xff08;第4版&#xff09;》视频课程 扩展 RouterLink RouterLink 组件提供了足够的 props 来满足大多数基本应用程序的需求&#xff0c;但它并未尝试涵盖所有可能的用例&#xff0c;在某些高级情况下&#xff0c;你可能会发现自己使用了 v-sl…

开发一个答题pk小程序的大致成本是多少

答题 PK 小程序通常指的是一种允许用户之间进行实时或异步答题竞赛的应用程序&#xff0c;可能结合PK答题、积分系统、排行榜等功能。 一、首先&#xff0c;确定答题 PK 小程序的基本功能模块。这可能包括用户注册登录、题库管理、题目类型&#xff08;单选、多选、判断等&am…

GPT-2 语言模型 - 模型训练

本节代码是一个完整的机器学习工作流程&#xff0c;用于训练一个基于GPT-2的语言模型。下面是对这段代码的详细解释&#xff1a; 文件目录如下 1. 初始化和数据准备 设置随机种子 random.seed(1002) 确保结果的可重复性。 定义参数 test_rate 0.2 context_length 128 tes…

科技项目验收测试包括哪些内容?有什么作用?

在现代科技快速发展的背景下&#xff0c;科技项目的验收测试已成为项目管理中的重要环节。科技项目验收测试是一种系统性的方法&#xff0c;旨在评估一个科技项目是否达到预定的技术指标和要求&#xff0c;确认项目的完成质量。该测试通常在项目实施完成后进行&#xff0c;通过…

websoket 学习笔记

目录 基本概念 工作原理 优势 应用场景 HTTP协议与 webSoket协议之间的对比 消息推送场景 1. 轮询&#xff08;Polling&#xff09; 2. 长轮询&#xff08;Long Polling&#xff09; 3. 服务器发送事件&#xff08;Server-Sent Events, SSE&#xff09; 4. WebSocket…

博途 TIA Portal之1200做从站与汇川EASY的TCP通讯

上篇我们写到了博途做主站与汇川EASY的通讯。通讯操作起来很简单,当然所谓的简单,也是相对的,如果操作成功一次,那么后面就很容易了, 如果操作不成功,就会很遭心。本篇我们将1200做从站,与汇川EASY做主站进行TCP的通讯。 1、硬件准备 1200PLC一台,带调试助手的PC机一…

【数据结构_6下篇】有关链表的oj题

思路&#xff1a; 1.分别求出这两个链表的长度 2.创建两个引用&#xff0c;指向两个链表的头节点&#xff1b;找到长度长的链表&#xff0c;让她的引用先走差值步数 3.让这两个引用&#xff0c;同时往后走&#xff0c;每个循环各自走一步 然后再判定两个引用是否指向同一个…

vscode+wsl 运行编译 c++

linux 的 windows 子系统&#xff08;wsl&#xff09;是 windows 的一项功能&#xff0c;可以安装 Linux 的发行版&#xff0c;例如&#xff08;Ubuntu&#xff0c;Kali&#xff0c;Arch Linux&#xff09;等&#xff0c;从而可以直接在 windows 下使用 Linux 应用程序&#xf…