前端Vue架构

1

理解:

  • 创建视图的函数(render)和数据之间的关联;

  • 当数据发生变化的时候,希望render重新执行;

  • 监听数据的读取和修改;

    • defineProperty:监听范围比较窄,只能通过属性描述符去监听已有属性的读取和赋值;兼容性更好;(要求监听数据是对象)
    • proxy:监听范围更广;兼容性较差,只能兼容支持ES6 的浏览器(要求监听数据是对象)

如何知晓数据对应的函数;

function track(target, key) {console.log(`依赖收集:${key}`, 'color: #f00');
}function trigger(target, key) {console.log(`派发更新:${key}`, 'color: #f00');
}function isObject(value) {return typeof value === 'object' && value !== null;
}
const handlers = {get(target, key) {// 依赖收集track(target, key);return target[key]; // 返回对象的相应属性值},set(target, key, value) {// 派发更新trigger(target, key);// target[key] = value; // 设置对象的相应属性值// return true;// 赋值成功返回true,赋值失败返回false;这里可以使用try catchreturn Reflect.set(target, key, value)// 也可以使用Reflect.set(target, key, value)。它会直接返回true或者false},
}
// 同一个对象,调用两次reactive,会生成不一样的Proxy对象,没有意义
const targetMap = new WeakMap();
function reactive(target) {if (!isObject(target)) {return target; // 如果不是对象,直接返回}if (targetMap.has(target)) {return targetMap.get(target);// 如果已经代理过了,直接返回;}const proxy = new Proxy(target, handlers);targetMap.set(target, proxy);return proxy;
}
const state = reactive({a: 1,b: 2,
});// fn函数中用到了state数据
function fn() {state.a;state.b;
}fn();
state.a++; // 先读取,再赋值

依赖收集:a color: #f00
依赖收集:b color: #f00
依赖收集:a color: #f00
派发更新:a color: #f00

const obj = {a: 1,b: 2,get c() {return this.a + this.b;}
};const state = reactive(obj);
state.c;

这样写的话,依赖收集只能收集到属性c;因为this指向obj;
可以这样操作:

get(target, key, receiver) {// 依赖收集track(target, key);// receiver指的是代理对象return Reflect.get(target, key, receiver) ; // 改变this指向,将this指向为代理对象// return target[key]; // 返回对象的相应属性值
},

下面的用法,只能收集到c,收集不到c1

const obj = {a: 1,b: 2,c: {c1: 1,},
};const state = reactive(obj);
state.c.c1;

可以这样操作
如果访问的属性值还是一个对象,对属性值再次进行代理;

const obj = {
includes: () => {},
indexOf: () => {},
};
const handlers = {get(target, key, receiver) {// 依赖收集track(target, key);// 对于数组来说,无法在代理对象中找到时,去原始数组中重新找一次// const obj = {};// const arr = [1, obj, 3];// const state = reactive(arr);// state.includes(obj);if ((obj.hasOwnProperty(key) && Array.isArray(target)) {return obj[key];}// receiver指的是代理对象const result = Reflect.get(target, key, receiver) ; if (isObject(result)) {return reactive(result);}},
}

简易的模型已经写好;

2 读信息 进行依赖升级

Object.keys和let i in obj用的都是ownKeys;
‘a’ in obj; 用的是has;
obj.a 用的是get;

这里的读不光是通过state.a来读取a属性
还可能通过’e’ in state;来查看’e’属性在不在state中;

const obj = {};
const state = reactive(obj);
'e' in state;

解决办法:新增has方法

const TrackOpTypes = {GET: 'get', // 读取属性值HAS: 'has', // 判断属性是否存在ITERATE: 'iterate', // 迭代对象
};function track(target, trackOpType, key) {console.log(`依赖收集:${key},收集方法:${trackOpType}`, 'color: #f00');
}
const handlers = {get(target, key, receiver) {// 依赖收集track(target, TrackOpTypes.GET, key);// ...},set(target, key, value, receiver) {},has(target, key) {track(target, TrackOpTypes.HAS, key);return Reflect.has(target, key); // 判断对象是否有key属性}
}

在这里插入图片描述

同理

const TriggerOpTypes = {SET: 'set', // 设置属性值ADD: 'add', // 添加属性值DELETE: 'delete', // 删除属性
}function trigger(target, triggerOpType, key) {console.log(`派发更新:${key}, 更改方法:${triggerOpType}`, 'color: #f00');
}

还有一种情况

const handlers = {get,set,has,ownKeys(target) {track(target, TrackOpTypes.ITERATE);return Reflect.ownKeys(target); // 返回对象的所有属性名},
}
function track(target, trackOpType, key) {if (trackOpType === TrackOpTypes.ITERATE) {console.log(`依赖收集方法:${trackOpType}`, 'color: #f00');return;}console.log(`依赖收集:${key},收集方法:${trackOpType}`, 'color: #f00');
}
const obj = { a: '1'};
const obj2 = {}
const state = reactive(obj);
const state2 = reactive(obj2);
for (let i in state) {}
Object.keys(state2);

Object.keys和let i in obj用的都是ownKeys;

依赖收集方法:iterate color: #f00
依赖收集方法:iterate color: #f00

3 新增属性

 set(target, key, value, receiver) {// 派发更新const type = target.hasOwnProperty(key)? TriggerOpTypes.SET: TriggerOpTypes.ADD;trigger(target, type, key);return Reflect.set(target, key, value, receiver);},

在这里插入图片描述

4 删除属性

 deleteProperty(target, key) {trigger(target, TriggerOpTypes.DELETE, key);return Reflect.deleteProperty(target, key); // 删除对象的相应属性}
delete state.a;

5 数据和函数的内在联系

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

博客互动革命:如何打造活跃读者社区并提升参与度

CSDN 的朋友你们好,我是未来,今天给大家带来专栏【程序员博主教程(完全指南)】的第 10 篇文章“与读者互动”。本文揭示了提升技术博客参与度的秘诀。从评论互动到社交媒体策略,本文将指导你如何建立强大的读者社区。掌…

blender 为世界环境添加纹理图像

1、打开世界环境配置项 2、点击颜色右侧的黄色小圆,选择环境纹理 3、打开一张天空图像 4、可以通过调整强度/力度,调整世界环境的亮度

传感网应用开发教程--AT指令访问新大陆云平台(ESP8266模块+物联网云+TCP)

实现目标 1、熟悉AT指令 2、熟悉新大陆云平台新建项目 3、具体目标:(1)注册新大陆云平台;(2)新建一个联网方案为WIFI的项目;(3)ESP8266模块,通过AT指令访问…

用python写算法——队列笔记

1.队列定义 队列是一种特殊的线性表,它只允许在表的前端进行删除操作,在表的后端进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头。队列中没有元素时&#…

部署Discuz论坛项目

DIscuz 是由 PHP 语言开发的一款开源社交论坛项目。运行在典型的LNMP/LAMP 环境中。 安装MySQL数据库5.7 主机名IP地址操作系统硬件配置discuz-db192.168.226.128CentOS 7-mini-20092 Core/4G Memory 修改主机名用来自己识别 hostnamectl set-hostname discuz-db #重连远程…

一键复制:基于vue实现的tab切换效果

需求&#xff1a;顶部栏有切换功能&#xff0c;内容区域随顶部切换而变化 目录 实现效果实现代码使用示例在线预览 实现效果 如下 实现代码 组件代码 MoTab.vue <template><div class"mo-tab"><divv-for"item in options"class"m…

OBS插件--视频回放

视频回放 视频回放是一款源插件&#xff0c;它可以将指定源的视频缓存一段时间&#xff08;时间可以设定&#xff09;&#xff0c;将缓存中的视频添加到当前场景中后&#xff0c;可以快速或慢速不限次数的回放。这个功能在类似体育比赛的直播中非常有用&#xff0c;可以捕获指…

网络基础(三)——网络层

目录 IP协议 1、基本概念 2、协议头格式 2.1、报头和载荷如何有效分离 2.2、如果超过了MAC的规定&#xff0c;IP应该如何做呢&#xff1f; 2.3、分片会有什么影响 3、网段划分 4、特殊的ip地址 5、ip地址的数量限制 6、私有ip地址和公网ip地址 7、路由 IP协议 网络…

C++/Qt 小知识记录6

工作中遇到的一些小问题&#xff0c;总结的小知识记录&#xff1a;C/Qt 小知识6 dumpbin工具查看库导出符号OSGEarth使用编出的protobuf库&#xff0c;报错问题解决VS2022使用cpl模板后&#xff0c;提示会乱码的修改设置QProcess调用cmd.exe执行脚本QPainterPath对线段描边处理…

实验0.0 Visual Studio 2022安装指南

Visual Studio 2022 是一个功能强大的开发工具&#xff0c;对于计算机专业的学生来说&#xff0c;它不仅可以帮助你完成学业项目&#xff0c;还能为你将来的职业生涯打下坚实的基础。通过学习和使用 Visual Studio&#xff0c;你将能够更高效地开发软件&#xff0c;并在编程领域…

picoCTF-Web Exploitation-More SQLi

Description Can you find the flag on this website. Additional details will be available after launching your challenge instance. Hints SQLiLite 先随便输入个账号密码登录一下&#xff0c;得到查询SQL&#xff0c;接下来应该对SQL进行某些攻击来绕过密码登录成功 -- …

Unity Editor 找物体助手

找啊找朋友~ &#x1f371;功能介绍&#x1f959;使用方法 &#x1f371;功能介绍 &#x1f4a1;输入相关字符串&#xff0c;它会帮你找到名称中带有该字符串的所有物体&#xff0c;还会找包含该字符串的Text、TextMeshProUGUI。 &#x1f959;使用方法 &#x1f4a1;导入插…

商场学习之微服务

前言 寒假前在新电脑上配置了java环境&#xff0c;maven仓库&#xff0c;node,js&#xff0c;navicat&#xff0c;MySQL&#xff0c;linux&#xff0c;vmware等环境&#xff0c;创建了6个mysql数据库&#xff0c;77张表。 如此多的表&#xff0c;字段&#xff0c;去手写基础…

加州大学欧文分校英语高级语法专项课程01:Verb Tenses and Passives 学习笔记

Verb Tenses and Passives Course Certificate Course Intro 本文是学习 Verb Tenses and Passives 这门课的学习笔记。 文章目录 Verb Tenses and PassivesWeek 01: Simple, Progressive, and Perfect Verb Tenses ReviewLearning Objectives Present Perfect Tense Review L…

从我的实体书单中,精选这六本书推荐

工作之余偶尔看看书&#xff0c;偏爱翻阅实体书。随着时间的推移&#xff0c;书逐渐变得多了起来。为了给新书腾出空间&#xff0c;同时也为了减轻收藏实体书的经济负担&#xff0c;我决定进行一次书籍的整理和出售。在这一过程中&#xff0c;我特意挑选了六本我个人喜爱的书籍…

《构建智能财务预算与管控技术架构:实现企业财务管理的高效运作》

在当今数字化时代&#xff0c;企业财务预算与管控技术的应用已成为企业管理的关键一环。通过构建智能化的财务预算与管控技术架构&#xff0c;企业能够实现财务管理的精细化、智能化和高效化&#xff0c;从而更好地应对市场竞争和风险挑战&#xff0c;提升企业的竞争力和盈利能…

i春秋-GetFlag

题目 考点 sql注入&#xff0c;md5加密&#xff0c;代码审计&#xff0c;利用eval函数 解题 参考wp https://www.cnblogs.com/qiaowukong/p/13630130.html找md5值 看见验证码中的提示&#xff0c;就是去找一个md5值前六位是指定值的数&#xff08;严格来说不一定是数&…

【C语言项目】贪吃蛇(下)

个人主页~ 源码在Gitee仓库~ 上一篇贪吃蛇&#xff08;上&#xff09;~ 贪吃蛇 四、核心的实现游戏测试1、GameStart&#xff08;1&#xff09;控制台窗口大小和名字设置&#xff08;2&#xff09;光标隐藏&#xff08;3&#xff09;打印欢迎界面&#xff08;4&#xff09;创建…

鸿蒙布局Column/Row/Stack

鸿蒙布局Column/Row/Stack 简介我们以Column为例进行讲解1. Column({space: 10}) 这里的space: 10&#xff0c;表示Column里面每个元素之间的间距为102. width(100%)&#xff0c;height(100%) 表示宽高占比3. backgroundColor(0xffeeeeee) 设置背景颜色4. padding({top: 50}) 设…

Vue报错:TypeError: Cannot read property ‘upgrade‘ of undefined

文章目录 Vue报错&#xff1a;TypeError: Cannot read property upgrade of undefined前言解决办法 Vue报错&#xff1a;TypeError: Cannot read property ‘upgrade’ of undefined 前言 最近打开一个很就之前的开发项目&#xff0c;因为扫描包&#xff0c;所以删除了部分代…