前端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.mzph.cn/web/10995.shtml

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

相关文章

Docker 直接运行一个 Alpine 镜像

由于镜像很小,下载时间往往很短,读者可以直接使用 docker run 指令直接运行一个 Alpine 容器,并指定运行的 Linux 指令,例如: PS C:\Users\yhu> docker run alpine echo 123 Unable to find image alpine:latest lo…

Commit failed (details follow):is out of date

Commit failed (details follow):is out of date 关于SVN提交时报out-of-date错误的解决方法 提交项目文件时,报如下的信息: Item is out-of-date svn: Commit failed (details follow): svn: Item ‘/xxx/xxx/xxx/xxx/xxx/xxx’ is out of date 原因&…

手写Spring5【笔记】

Spring5【笔记】 前言前言推荐Spring5【笔记】1介绍2手写 最后 前言 这是陈旧已久的草稿2022-12-01 23:32:59 这个是刷B站的时候,看到一个手写Spring的课程。 最后我自己好像运行不了,就没写。 现在2024-5-12 22:22:46,发布到[笔记]专栏中…

队列(详解)

一.队列的概念 队列(Queue)是一种常见的数据结构,它按照先进先出的原则管理数据。这意味着最先进入队列的元素将被最先移出队列,类似于现实生活中排队的场景。 在队列中,数据项被添加到队列的一端,称为队尾…

cmu15445 2023fall project3 详细过程(下)QUERY EXECUTION

QUERY EXECUTION task3/task4 Task #3 - HashJoin Executor and Optimization1、HashJoin1.1 思路1.2 代码 2 NestedLoopJoin优化为HashJoin2.1 思路2.2 代码 Task #4 Sort Limit Executors Top-N Optimization Window Functions1、Sort1.1 思路1.2 代码 2、Limit Executors2…

数据可视化第五天(读取文件获得男生女生身高信息,并且可视化在一个图像)

文件 需要学生文件的可以私信我 过程 利用numpy的loadtxt文件读取学号,性别,和身高。 import numpy as np import matplotlib.pyplot as pltfilename/Users/oommnn/Desktop/python学习/数据分析/网课资料/第04天/student-data.txtuser_infonp.dtype(…

文献阅读——LPPLS(2)

A study on the bursting point of Bitcoin based on the BSADF and LPPLS methods 文献来源[2] Yao, Can-Zhong, and Hong-Yu Li. “A study on the bursting point of Bitcoin based on the BSADF and LPPLS methods.” The North American Journal of Economics and Financ…

猫头虎分享已解决Bug || **Vue.js脚手架安装失败** Error: unable to fetch template`

猫头虎分享已解决Bug 🐯 || Vue.js脚手架安装失败 🚫Error: unable to fetch template 博主猫头虎的技术世界 🌟 欢迎来到猫头虎的博客 — 探索技术的无限可能! 专栏链接: 🔗 精选专栏: 《面试题…

CodeTop 高频笔试题总结(持续更新)

🏆 频率从高到低排序 👨‍🏫 参考的频率数据:CodeTop 👨‍🏫 力扣hot100 无重复字符的最长子串 双指针 滑动窗口 哈希👨‍🏫 力扣hot100 反转链表 指针 递归 一题多解👨‍…

7. path路径绘制:使用path绘制曲线

曲线在SVG中通常是通过贝塞尔曲线命令来绘制的,包括二次贝塞尔曲线(Q)和三次贝塞尔曲线(C)。这些命令允许我们创建平滑的曲线路径。 贝塞尔曲线的原理 贝塞尔曲线的基本原理是通过控制点和锚点来定义一条曲线的形状。…

命名规范总结Java

小驼峰命名 主要用于变量和方法的命名,当标识符是一个单词时首字母小写,当标识符为多个单词时第一个单词首字母小写,其他单词首字母大写 大驼峰命名 主要用于类(Class)名等。标识符各个单词首字母大写。 全部大写命名 常量名 全部小写命…

持续总结中!2024年面试必问 100 道 Java基础面试题(四十一)

上一篇地址:持续总结中!2024年面试必问 100 道 Java基础面试题(四十)-CSDN博客 八十一、Java内存模型是什么? Java内存模型(Java Memory Model, JMM)是Java虚拟机(JVM)…

海豚知道知识付费平台,大V都在用,新手也能做,网络营销是什么?如何向销售转化?

我国的市场营销已经全面步入互联网时代,教育行业也逐渐网络化,通过互联网发家壮大的机构比比皆是,然而仍旧有很多中小型教育培训机构,没有从事网络营销推广,或者从事了效果非常不理想。网络营销是什么,如何…

流畅的python-学习笔记_对象引用、可变性、垃圾回收

变量不是盒子 即变量是引用,而不是实际内存,多个标识赋值相同变量时,多余标识是引用 标识、相等性、别名 比较对象的值,is比较对象的id。实际调用对象的__eq__方法。is速度比快,因为is不能重载,省去了寻…

UNIT6,NFS网络文件系统的应用

实验要求: 1.配置2台服务器要求如下: a)服务器1: 主机名:user-server.timinglee.org ip地址: 172.25.254.100 配置好软件仓库 b)服务器2: 主机名:storage-server.timing…

力扣 300. 最长递增子序列 python AC

动态规划 dp[i]表示到当前位置为止最多个数的递增子序列 简单的对每个位置从头遍历 class Solution:def lengthOfLIS(self, nums):size len(nums)dp [1] * sizefor i in range(1, size):for j in range(i):if nums[i] > nums[j]:dp[i] max(dp[i], dp[j] 1)return max…

数据结构与算法学习笔记之线性表二---顺序表的静态存储表示和实现(C++)

目录 前言 1.什么是顺序表 2.顺序表的静态存储表示 1.初始化 2.长度 3.数据元素 4.长度 5.获取元素下标 6.前驱节点 7.后继节点 8.插入 9.删除 10.遍历 11.测试代码 前言 这篇文章讲的是顺序表的两种实现方式。 1.什么是顺序表 线性表的顺序表示指的是用一组地址…

Double 4 VR情景智能互动教学系统在商务旅行课堂中的应用

一、提高学生的学习兴趣 传统的商务旅行课堂教学方式往往是教师讲授理论知识,学生被动接受。这种方式很难激发学生的学习兴趣,而Double 4 VR情景智能互动教学系统则可以通过虚拟现实技术,将商务旅行的场景生动地展示给学生,让学生…

医院如何做好漏费管理?什么是控费系统?控费系统现在成熟吗?

在中国深厚的人情土壤之中,某些医院里的医技科室,宛如隐秘的灰色地带,悄然滋生着利用职务之便谋取私利的暗流。这些科室的医务人员,以低于医院明文规定的收费标准,私下里为熟识的患者提供检查服务,仿佛形成…

【碎碎念4】向上社交

好久没写碎碎念系列了,最近关注到身边一些社交关系,想要和大家聊聊向上社交这件事情。首先小田认为向上社交或者仅仅是社交本身是无论什么年纪都需要关注的,因为处理好关系不仅仅会帮助我们把握好机会,同时也能让我们更好的建立自…