当前位置: 首页 > article >正文

vue 中的数据代理

在 Vue 中,数据代理(Data Proxy) 是 Vue 实现 MVVM 模式 的关键技术之一。Vue 使用数据代理让你可以通过 this.message 访问 data.message,而不需要写 this.data.message —— 这大大简化了模板和逻辑代码。

我们来深入理解它的本质、实现原理和源码体现。

🔹 什么是数据代理?

Vue 实例将 data、props、computed 等属性“代理”到 vm(Vue 实例)自身上,从而让我们能直接通过 this.xx 访问,而不必每次访问 this._data.xx。

✅ 示例:数据代理的使用效果

const vm = new Vue({data: {message: 'hello'}
})console.log(vm.message) // 实际上是 vm._data.message

🧠 数据代理的实现原理(以 Vue 2 为例)

Vue 2 中通过 Object.defineProperty 实现数据代理。

👉 源码简化模拟:

function proxy(target, sourceKey, key) {Object.defineProperty(target, key, {get() {return target[sourceKey][key]},set(val) {target[sourceKey][key] = val}})
}

Vue 实例化时,会遍历 data 中的所有属性,调用 proxy(vm, ‘_data’, key) 将它们挂载到实例 vm 上。

🔧 Vue 2 中相关源码(core/instance/state.js)

function initData(vm) {const data = vm.$options.datavm._data = typeof data === 'function' ? data.call(vm, vm) : data || {}// 数据代理const keys = Object.keys(vm._data)let i = keys.lengthwhile (i--) {proxy(vm, '_data', keys[i])}observe(vm._data)
}

📌 Vue 3 的处理方式

Vue 3 中由于响应式改为使用 Proxy,所以数据代理并不是必须通过 defineProperty 显式定义,而是由 reactive() 和 ref() 本身提供的响应式代理能力。

import { reactive } from 'vue'const state = reactive({ count: 0 })console.log(state.count) // 已被代理,无需显式挂载到组件实例上

Vue 3 更加模块化,组件实例并不自动把数据代理到 this 上,尤其在

🧠 为什么要用数据代理?

简化访问:

  • 不用写 this._data.xxx,直接 this.xxx

实现双向绑定:

  • v-model 语法简洁,背后依赖于代理 + 响应式

方便调试和语法提示:

  • IDE 能提示实例属性;不用深层嵌套对象路径

🔄 数据代理 vs 响应式代理

特性数据代理响应式代理
实现技术Object.defineProperty(Vue 2)Proxy(Vue 3)
目的让你能通过 this.key 访问 data.key追踪依赖、触发视图更新
是否双向绑定否,单纯转发 getter/setter是,配合响应式系统自动更新视图
使用位置Vue 实例、组件所有响应式状态(ref、reactive)

✅ 小结

  • 数据代理是为了简化访问方式,不是响应式的根本机制。
  • Vue 2 中通过 Object.defineProperty 将 data 的属性代理到 Vue 实例上。
  • Vue 3 中响应式是通过 Proxy 实现,数据代理的需求被弱化(但原理仍然存在)。
  • 它是 MVVM 中 ViewModel 作为桥梁的一部分。

小型 Vue 响应式系统(含数据代理)

// 1. 数据代理
function proxy(vm, sourceKey, key) {Object.defineProperty(vm, key, {get() {return vm[sourceKey][key]},set(val) {vm[sourceKey][key] = val}})
}// 2. 响应式转换(核心 Observer)
function defineReactive(obj, key, val) {const dep = new Dep()Object.defineProperty(obj, key, {get() {dep.depend()return val},set(newVal) {val = newValdep.notify()}})
}// 3. 对整个 data 对象做响应式处理
function observe(obj) {Object.keys(obj).forEach(key => defineReactive(obj, key, obj[key]))
}// 4. 依赖收集器
class Dep {constructor() {this.subscribers = new Set()}depend() {if (activeEffect) {this.subscribers.add(activeEffect)}}notify() {this.subscribers.forEach(effect => effect())}
}let activeEffect = null
function watchEffect(effect) {activeEffect = effecteffect() // 立即执行一次activeEffect = null
}// 5. 模拟 Vue 实例
function Vue(options) {this._data = options.dataobserve(this._data)// 代理 _data 到 thisObject.keys(this._data).forEach(key => {proxy(this, '_data', key)})
}
// 创建 Vue 实例
const vm = new Vue({data: {message: 'Hello',count: 1}
})// 绑定“视图更新”逻辑
watchEffect(() => {console.log('视图更新:', vm.message, vm.count)
})// 修改数据,自动触发“视图更新”
vm.message = 'Hello Vue'
vm.count++

Vue 3 响应式系统简易实现(模拟核心功能)

// 1. 依赖收集器
const targetMap = new WeakMap()
let activeEffect = nullfunction track(target, key) {if (!activeEffect) returnlet depsMap = targetMap.get(target)if (!depsMap) {depsMap = new Map()targetMap.set(target, depsMap)}let deps = depsMap.get(key)if (!deps) {deps = new Set()depsMap.set(key, deps)}deps.add(activeEffect)
}function trigger(target, key) {const depsMap = targetMap.get(target)if (!depsMap) returnconst deps = depsMap.get(key)if (deps) {deps.forEach(effect => effect())}
}// 2. 创建响应式对象
function reactive(target) {return new Proxy(target, {get(obj, key) {track(obj, key)return Reflect.get(obj, key)},set(obj, key, value) {const result = Reflect.set(obj, key, value)trigger(obj, key)return result}})
}// 3. 注册副作用(自动运行函数)
function effect(fn) {activeEffect = fnfn()activeEffect = null
}
const state = reactive({count: 0,name: 'Vue3'
})effect(() => {console.log('视图更新:', state.count, state.name)
})state.count++     // 触发更新
state.name = 'Vue3 Proxy'

相关文章:

vue 中的数据代理

在 Vue 中,数据代理(Data Proxy) 是 Vue 实现 MVVM 模式 的关键技术之一。Vue 使用数据代理让你可以通过 this.message 访问 data.message,而不需要写 this.data.message —— 这大大简化了模板和逻辑代码。 我们来深入理解它的本…...

ubuntu安装Go SDK

# 下载最新版 Go 安装包(以 1.21.5 为例) wget https://golang.google.cn/dl/go1.21.5.linux-amd64.tar.gz # 解压到系统目录(需要 root 权限) sudo tar -C /usr/local -xzf go1.21.5.linux-amd64.tar.gz # 使用 Go 官方安装脚本…...

【C++】学习、项目时Debug总结

这里写目录标题 1. 内存问题1.1. 内存泄漏1.1.1. 内存泄漏案例检查方法1.1.2. 主线程提前退出导致【控】1.1.3. PostThreadMessage失败导致的内存泄漏**【控】**1.1.4. SendMessage 时关闭客户端【控】1.1.5. 线程机制导致【**控】**1.1.6. exit(0)导致【…...

26考研——中央处理器_指令流水线_指令流水线的基本概念 流水线的基本实现(5)

408答疑 文章目录 六、指令流水线指令流水线的基本概念流水线的基本实现流水线设计的原则流水线的逻辑结构流水线的时空图表示 八、参考资料鲍鱼科技课件26王道考研书 六、指令流水线 前面介绍的指令都是在单周期处理机中采用串行方法执行的,同一时刻 CPU 中只有一…...

Flutter——数据库Drift开发详细教程(三)

目录 参考正文核心API写入(更新、插入、删除)1.更新和删除2.使用 SQL 表达式更新3.插入件4.更新插入5.返回 参考 https://drift.simonbinder.eu/dart_api/writes/#updating-with-sql-expressions 正文核心API 写入(更新、插入、删除&#…...

AI Agent-基础认知与架构解析

定义 AI Agent 可以理解为一种具备感知、决策和行动能力的智能实体,能够在复杂的环境中自主运行,并根据环境变化动态调整自身行为,以实现特定目标。与传统的人工智能程序相比,AI Agent 具有更强的自主性、交互性和适应性。它不仅能…...

privateGPT和RAGflow之间的区别

PrivateGPT和RAGFlow都是基于RAG(检索增强生成)技术的开源项目,但它们在设计目标、技术架构和应用场景上有显著差异。以下是两者的详细对比分析: 1. 核心定位与设计目标 PrivateGPT 隐私优先:专注于完全离线的私有化部署,确保用户数据不离开本地环境,适合对隐私要求极高…...

C语言--字符函数

C语言--字符函数 一、字符函数1.1 iscntrl1.2 isspace1.3 isdigit1.4 isxdigit1.5 islower1.6 isupper1.7 isalpha1.8 isalnum1.9 ispunct1.10 isgraph1.11 isprint 在编程的过程中,我们会经常处理字符,为了方便操作,C语言标准库中提供了一系…...

Android对工程中的String中文字符的整理

​ 本文主要介绍使用python快速整理工程中的中文字符,为app国际化提供便利。 1. 查找Android工程中的所有中文字符串(find_chinese.py) import os import re import argparsedef is_comment_line(line, file_ext):"""判断一行是否是注释:param lin…...

菜鸟之路Day30一一MySQL之DMLDQL

菜鸟之路Day30一一MySQL之DML&DQL 作者:blue 时间:2025.5.8 文章目录 菜鸟之路Day30一一MySQL之DML&DQL一.DML0.概述1.插入语句(insert)2.更新语句(update)3.删除语句(delete&#xf…...

集团云解决方案:集团企业IT基础架构的降本增效利器

在当今数字化飞速发展的时代,集团企业面临着诸多挑战,尤其是IT基础架构的管理和运营成本居高不下,效率却难以提升。别担心,集团云解决方案的出现为集团企业带来了全新的曙光,真正实现了降本增效! 一、集团…...

基 LabVIEW 的多轴电机控制系统

在工业自动化蓬勃发展的当下,多轴伺服电机控制系统的重要性与日俱增,广泛应用于众多领域。下面围绕基于 LabVIEW 开发的多轴伺服电机控制系统展开,详细阐述其应用情况。 一、应用领域与场景 在 3D 打印领域,该系统精确操控打印头…...

SD06_前后端分离项目部署流程(采用Nginx)

本文档详细描述了如何在Ubuntu 20.04服务器上从零开始部署Tlias前后端分离系统。Tlias系统由Spring Boot后端(tlias-web-management)和Vue前端(vue-tlias-management)组成。 目录 环境准备安装MySQL数据库部署后端项目部署前端项…...

【kubernetes】通过Sealos 命令行工具一键部署k8s集群

一、前言 1、sealos安装k8s集群官网:K8s > Quick-start > Deploy-kubernetes | Sealos Docs 2、本文安装的k8s版本为v1.28.9 3、以下是一些基本的安装要求: 每个集群节点应该有不同的主机名。主机名不要带下划线。所有节点的时间需要同步。需要…...

《Go小技巧易错点100例》第三十二篇

本期分享: 1.sync.Map的原理和使用方式 2.实现有序的Map sync.Map的原理和使用方式 sync.Map的底层结构是通过读写分离和无锁读设计实现高并发安全: 1)双存储结构: 包含原子化的 read(只读缓存,无锁快…...

怎么判断是不是公网IP?如何查看自己本地路由器是内网ip还是公网?

在网络世界中,IP 地址如同每台设备的 “门牌号”,起着至关重要的标识作用。而 IP 地址又分为公网 IP 和私网 IP,准确判断一个 IP 属于哪一类,对于网络管理、网络应用开发以及理解网络架构等都有着重要意义。接下来,我们…...

【上位机——MFC】单文档和多文档视图架构

单文档视图架构 特点&#xff1a;只能管理一个文档(只有一个文档类对象) #include <afxwin.h> #include "resource.h"//文档类 class CMyDoc :public CDocument {DECLARE_DYNCREATE(CMyDoc) //支持动态创建机制 }; IMPLEMENT_DYNCREATE(CMyDoc,CDocument) //…...

需求分析阶段测试工程师主要做哪些事情

在软件测试需求分析阶段&#xff0c;主要围绕确定测试范围、明确测试目标、细化测试内容等方面开展工作&#xff0c;为后续测试计划的制定、测试用例的设计以及测试执行提供清晰、准确的依据。以下是该阶段具体要做的事情&#xff1a; 1. 需求收集与整理 收集需求文档&#x…...

Web 实时通信技术:WebSocket 与 Server-Sent Events (SSE) 深入解析

一、WebSocket&#xff1a; &#xff08;一&#xff09;WebSocket 是什么&#xff1f; WebSocket 是一种网络通信协议&#xff0c;它提供了一种在单个 TCP 连接上进行全双工通信的方式。与传统的 HTTP 请求 - 响应模型不同&#xff0c;WebSocket 允许服务器和客户端在连接建立…...

项目模拟实现消息队列第二天

消息应答的模式 1.自动应答: 消费者把这个消息取走了&#xff0c;就算是应答了&#xff08;相当于没有应答) 2.手动应答: basicAck方法属于手动应答(消费者需要主动调用这个api进行应答) 小结 1.需要实现生产者,broker server&#xff0c;消费者这三个部分的 2.针对生产者和消费…...

5.Redission

5.1 前文锁问题 基于 setnx 实现的分布式锁存在下面的问题&#xff1a; 重入问题&#xff1a;重入问题是指 获得锁的线程可以再次进入到相同的锁的代码块中&#xff0c;可重入锁的意义在于防止死锁&#xff0c;比如 HashTable 这样的代码中&#xff0c;他的方法都是使用 sync…...

c#数据结构 线性表篇 非常用线性集合总结

本人能力有限,使用了一些Ai的结论,如有不足还请斧正 目录 1.HashSet <> Dictionary 2.SortedSet <>提供升序方法的List 3.ArrayList<>List 4.BitArray <> Bit[] array 5.StringCollection <>List 6.StringDictionary<>Dictionary 1…...

dify 部署后docker 配置文件修改

1&#xff1a;修改 复制 ./dify/docker/.env.example ./dify/docker/.env 添加一下内容 # 启用自定义模型 CUSTOM_MODEL_ENABLEDtrue# 将OLLAMA_API_BASE_URL 改为宿主机的物理ip OLLAMA_API_BASE_URLhttp://192.168.72.8:11434# vllm 的 OPENAI的兼容 API 地址 CUSTOM_MODE…...

数据结构——排序(万字解说)初阶数据结构完

目录 1.排序 2.实现常见的排序算法 2.1 直接插入排序 ​编辑 2.2 希尔排序 2.3 直接选择排序 2.4 堆排序 2.5 冒泡排序 2.6 快速排序 2.6.1 递归版本 2.6.1.1 hoare版本 2.6.1.2 挖坑法 2.6.1.3 lomuto前后指针 2.6.1.4 时间复杂度 2.6.2 非递归版本 2.7 归并排序…...

SQLite3介绍与常用语句汇总

SQLite3简介 SQLite3是一款轻量级的、基于文件的开源关系型数据库引擎&#xff0c;由 D. Richard Hipp 于 2000 年首次发布。它遵循 SQL 标准&#xff0c;但与传统的数据库系统不同&#xff0c;SQLite 并不运行在独立的服务器进程中&#xff0c;而是作为一个嵌入式数据库引擎直…...

快速入门深度学习系列(3)----神经网络

本文只针对图进行解释重要内容 这就是入门所需要掌握的大部分内容 对于不懂的名词或概念 你可以及时去查 对于层数 标在上面 对于该层的第几个元素 标在下面 输入层算作第0层 对于第一层的w b 参数 维度如下w:4*3 b:4*1 这个叫做神经元 比如对于第一层的神经元 这里说的很…...

在线工具源码_字典查询_汉语词典_成语查询_择吉黄历等255个工具数百万数据 养站神器,安装教程

在线工具源码_字典查询_汉语词典_成语查询_择吉黄历等255个工具数百万数据 养站神器&#xff0c;安装教程 资源宝分享&#xff1a;https://www.httple.net/154301.html 一次性打包涵盖200个常用工具&#xff01;无论是日常的图片处理、文件格式转换&#xff0c;还是实用的时间…...

ORB-SLAM3和VINS-MONO的对比

直接给总结&#xff0c;整体上orbslam3&#xff08;仅考虑带imu&#xff09;在初始化阶段是松耦合&#xff0c;localmap和全局地图优化是紧耦合。而vins mono则是全程紧耦合。然后两者最大的区别就在于vins mono其实没有对地图点进行优化&#xff0c;为了轻量化&#xff0c;它一…...

大数据处理利器:Hadoop 入门指南

一、Hadoop 是什么&#xff1f;—— 分布式计算的基石 在大数据时代&#xff0c;处理海量数据需要强大的技术支撑&#xff0c;Hadoop 应运而生。Apache Hadoop 是一个开源的分布式计算框架&#xff0c;致力于为大规模数据集提供可靠、可扩展的分布式处理能力。其核心设计理念是…...

Docker容器网络架构深度解析与技术实践指南——基于Linux内核特性的企业级容器网络实现

第1章 容器网络基础架构 1 Linux网络命名空间实现原理 1.1内核级隔离机制深度解析 1.1.1进程隔离的底层实现 通过clone()系统调用创建新进程时&#xff0c;设置CLONE_NEWNET标志位将触发内核执行以下操作&#xff1a; 内核源码示例&#xff08;linux-6.8.0/kernel/fork.c&a…...