前端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 catch
    return 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 数据和函数的内在联系

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

QX---mini51单片机学习---(8)8*8点阵屏

目录 1LED点阵屏简绍 2 8*8点阵屏电路图74 3 74HC595芯片 4实践编程 1LED点阵屏简绍 2 8*8点阵屏电路图74 怎么点亮,正极给高负极给低 不能同时静态显示,跟数码管动态显示一样,反复横跳,利用视觉效果 3 74HC595芯片 …

kilimall非洲电商培训,基础版+进阶版+高阶版 从0-1个人可入驻的平台(12节)

亲爱的朋友们,你们知道吗?有一个神奇的电商平台——kilimall,它可以帮助你实现创业梦想,让你走上财富之路! 首先,让我给大家介绍kilimall的基础版。基础版针对的是0经验的小白,提供了详细的教程…

有没有适合女生或者宝妈下班后可以做的副业?

宝妈与上班族女生的新篇章:水牛社副业兼职之旅 在繁忙的职场和温馨的家庭之间,不少女性渴望找到一种既能兼顾家庭又能实现自我价值的兼职方式。对于上班族女生和宝妈们来说,水牛社这样的线上任务平台为她们提供了一个全新的选择。 上班族女…

MFC的CPen与CBush画图对象使用步骤

在MFC中,CPen和CBrush是两个常用的绘图对象,分别用于定义画笔和画刷,可以用于绘制图形、填充区域等。下面我会详细介绍如何在MFC中使用CPen和CBrush来绘制和填充图形。 使用 CPen 绘制图形: 创建 CPen 对象: 首先&am…

2000-2022年各地级市知识产权审判结案数数据

2000-2022年各地级市知识产权审判结案数数据 1、时间:2000-2022年 2、指标:城市知识产权审判结案数 3、来源:整理自北大法宝 4、范围:287个地级市 5、用途:可用于衡量地级市知识产权保护水平 6、指标解释&#x…

第五步->手撕spring源码之资源加载器解析到注册

本步骤目标 在完成 Spring 的框架雏形后,现在我们可以通过单元测试进行手动操作 Bean 对象的定义、注册和属性填充,以及最终获取对象调用方法。但这里会有一个问题,就是如果实际使用这个 Spring 框架,是不太可能让用户通过手动方式…

数据结构·一篇搞定栈!

好久不见,超级想念 废话不多说,直接看 引言 在数据结构的大家族中,栈(Stack)是一种非常重要的线性数据结构,它的特点是后进先出(LIFO,Last In First Out)。栈在程序设…

Star15.3k,开源数据可视化分析工具项目

好东西来了,这是一个人人可用的开源数据可视化分析工具项目,V 哥迫不及待的要给大家推荐这个项目,帆软、Tableau 等商业 BI 工具的开源替代,已在 Github 上被 Star了15.3k了,大家一起来了解一下。自己搭建起来可用&…

consul启动Error_server_rejoin_age_max (168h0m0s) - consider wiping your data dir

consul 启动报错: consul[11880]: 2024-05-12T08:37:51.095-0400 [ERROR] agent: startup error: error"refusing to rejoin cluster because server has been offline for more than the configured server_rejoin_age_max (168h0m0s) - consider wiping you…

MFC桌面应用中窗口的客户区与非客户区的

在MFC(Microsoft Foundation Class)中,窗口被分为客户区和非客户区。理解这两个概念对于设计和开发Windows应用程序至关重要。 客户区(Client Area): 客户区是窗口中用于显示应用程序内容的区域。它是窗口…

机器学习周报第三十八周 iTransformer

文章目录 week38 iTransformer摘要Abstract一、文献阅读1. 题目2. abstract3. 网络架构**转置Embedding:****LayerNorm(层归一化)****Feed-forward network(前馈网络)****Multivariate-Attention(多变量注意…

深度学习中的一些概念

训练术语 欠拟合 欠拟合是指模型没有很好地捕获到数据特性,不能完整地表示数据的全部信息,也就是模型的复杂度低于应有的水平。例如,假设一个数据集实际上服从二阶多项式分布,但我们使用一阶线性模型去拟合它,这样的…

WebView基础知识以及Androidx-WebKit的使用

文章目录 摘要WebView基础一、启动调整模式二、WebChromeClient三、WebViewClient四、WebSettings五、WebView和Native交互 Androidx-WebKit一、启动安全浏览服务二、设置代理三、安全的 WebView 和 Native 通信支持四、文件传递五、深色主题的支持六、JavaScript and WebAssem…

全国药品价格目录数据库-药品价格查询

药品定价是一个复杂且多维的问题,它涉及到医疗保健系统、政府政策、市场需求、研发成本以及药品效果等多个因素。随着中国医疗改革的不断深入,药品定价机制也在逐步调整和完善。本文将详细探讨我国药品定价机制,包括其发展历程、定价方法、影…

微信小程序 17:小程序使用 npm 包和组件应用

目前,小程序中已经支持实用 npm 安装第三方包,从而提高小程序的开发效率,但是在小程序中使用 npm 包有三个限制: 不支持 Node.js内置库的包不支持依赖于浏览器内置对象的包不支持依赖于 C插件的包 Vant Weapp Vant Weapp是有赞…

Verilog复习(四)| 组合逻辑

一位全加器结构描述: 数据流描述: 行为描述: 只要有事件发生(列表中任何 信号有变化),就执行begin…end 的语句 。 always的事件控制方式 边沿触发 always (posedge clk) // clk从低电平->高&#x…

io_uring的使用示例及其解释

io_uring的使用示例及其解释 1 io_uring机制1.1 io_uring机制1.2 io_uring系统调用接口功能介绍1.2.1 io_uring_setup():1.2.2 io_uring_enter():1.2.3 io_uring_register(): 2 liburing2.1 liburing简介2.2 liburing编译2.2.1 liburing的代码…

ACM实训冲刺第五天

第一道题 注意&#xff1a;tmp<z #include<stdio.h> int main(){int flag[26];for(int i0;i<26;i){flag[i]0;}char tmp;while(tmp!}){scanf("%c",&tmp);if(tmp}) break;if(tmp<z&&tmp>a){flag[tmp-a];}}int cnt0;for(int i0;i<26…

深度学习UNet网络

DDPM主干模型&#xff1b; UNet是一种分类网络架构&#xff0c;输入一张图片&#xff0c;网络进行分类是目标物体还是背景像素&#xff1f; 像素级的判断。 最终输出是单通道388*388 但是输入是572&#xff0c;输入572是填充过来的 而且UNet使用的是镜像填充 镜像填充目的是…

实现字符串复制(C语言)

一、N-S流程图&#xff1b; 二、运行结果&#xff1b; 三、源代码&#xff1b; # define _CRT_SECURE_NO_WARNINGS # include <stdio.h>int main() {//初始化变量值&#xff1b;int i 0;char a[100], b[100];//获取字符串&#xff1b;printf("请为数组a输入字符串…