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

景洪市新农村建设网站/整站seo

景洪市新农村建设网站,整站seo,xampp本地搭建网站,可信赖的手机网站设计UI render(state) VUE的特点是数据驱动视图,在这里可以把数据理解为状态,而视图就是用户可以看到的页面,页面是动态变化的,而他的变化或是用户操作引起,或是后端数据变化引起,这些都可以说是数据的状态变…

UI = render(state)

VUE的特点是数据驱动视图,在这里可以把数据理解为状态,而视图就是用户可以看到的页面,页面是动态变化的,而他的变化或是用户操作引起,或是后端数据变化引起,这些都可以说是数据的状态变了,导致页面随之变化。

把顶部公式拆为三部分:UI、render、state。state和UI都是用户定的,不变的是render,所以VUE就担任了这个角色,当VUE发现state变化后,就通过一系列操作,把他反应在了UI上。

那么VUE是如何发现state变化的?引出了VUE的变化侦测:

JS为我们提供了object.defineProperty()方法,通过此方法我们可以知道数据什么时候发生了变化。

1.Object数据变得可观测

数据每次读写能够被我们看到,我们能知道数据什么时候发生了变化,将其称为数据的可观测。通过使用上述对象方法,可以实现。如下

let person = {}
let nameval = 'lwh'
Object.defineProperty(person,name,{get() {console.log('name被读取了')return nameval}set(newval) {console.log('name被修改了')nameval = newval
}
})

通过Object.defineProperty()方法定义了person的Name属性,并把这个属性的读写分别使用get和set方法进行拦截,每当该属性进行读或写操作时候就会触发这两个方法,意味着person的数据对象已经是可观测的了

但是为了将此对象的所有属性都变得可观测,可以编写以下代码: 

export class Observe {constructor(value) {this.value = value//给value新增一个__ob__属性,值为该value的observe实例//相当于给value打上标记,表示他已经转化为响应式了def(value,'__ob__',this)if (Array.isArray(value)) {//为数组的逻辑} else {this.walk(value)}}walk(obj: Object) {const keys = Object.keys(obj)for (let i = 0; i < keys.length; i++) {defineReactive(obj,key[i])}}
}
​
function defineReactive(obj, key, val) {if(typeof val === 'object') {new Observable(val)}object.defineProperty(obj, key, {enumerable: true,configurable: true,get() {console.log(`${key}属性被读取`)return val;},set(newval) {if(val === newval) {return}console.log(`${key}属性被修改了`)val = newval}})
}

上面的代码中,我们定义了observe类,用来将一个普通的Object转化为可观测的object。并且给value新增一个ob属性,表示这个已经被转化成响应式了。

然后判断数据类型,只有Object 类型才会调用walk方法将每一个属性都转换成getter/setter形式来侦测变化,最后在defineReactive中当传入的属性值还是一个object时使用new observe(val)来递归子属性,这样我们就可以把obj中所有属性都变为可观测型的,只要将object传入observe中,那么这个object就会变成可观测,响应式的Object.

observer类位于Vue2源码的src/core/observer/index.ts中。

2.依赖收集

当Object变得可观测后,我们就能知道数据什么时候发生了变化,发生了什么变化,这样就可以通知视图更新。但是问题来了,我们怎么知道哪些视图需要更新?总不能一个数据变化全部视图全部更新一次吧。所以,应该是视图里哪个使用到了这个数据的就更新。

视图里谁用到了这个数据谁更新,说官方一点就是谁依赖了这个数据谁更新。我们建立一个依赖数组(因为一个数据可能被多个地方使用,所以需要建立数组),谁依赖了这个数据就把谁放进这个数组。当数据变化时,就根据它的依赖数组去通知哪些视图需要更新。这个过程就是依赖收集。

那么我们该如何进行依赖收集,如何知道哪些依赖这个数据?

谁用了这个数据,那么当这个数据变化时就通知谁,所谓谁用了这个数据,就是谁获取了这个数据。根据上文可观测数据在被获取时会调用get方法,那么我们就可以在get中收集这个依赖。同样,数据变化会触发Set,所以,我们就在set中通知更新。

所以,我们应该给每个数据都配置一个依赖数组,谁依赖了它就放入谁。不过,单单使用数组的话,功能可能有点欠缺且代码有点耦合。所以拓展一下的话,我们给每一个数据建立一个类,用作依赖管理。所以在vue2源码中有了这个依赖管理器Dep类,代码如下:

// 源码位置:src/core/observer/dep.ts    
export default class Dep {constructor () {this.subs = []}addSub (sub) {this.subs.push(sub)}// 删除一个依赖removeSub (sub) {remove(this.subs, sub)}// 添加一个依赖depend () {if (window.target) {this.addDep(window.target)}}// 通知所有依赖更新notify () {const subs = this.subs.slice()for (let i = 0, l = subs.length; i < l; i++) {subs[i].update()}}
}
​
/*** Remove an item from an array*/
export function remove (arr, item) {if (arr.length) {const index = arr.indexOf(item)if (index > -1) {return arr.splice(index, 1)}}
}

在上面依赖管理器中,初始化了一个sub数组用来存放依赖,并且定义了几个附加方法。

有了依赖管理器后,我们就可以在getter中收集依赖,setter中通知更新了

function defineReactive (obj,key,val) {if(typeof val === 'object'){new Observable(val)}const dep = new Dep()  //实例化一个依赖管理器,生成一个依赖管理数组depObject.defineProperty(obj, key, {enumerable: true,configurable: true,get(){dep.depend()    // 在getter中收集依赖return val;},set(newVal){if(val === newVal){return}val = newVal;dep.notify()   // 在setter中通知依赖更新}})
}

接下来需要知道的是,我们收集的依赖到底是谁?

谁用到了这个数据谁就是依赖,那代码上该如何描述这个谁呢?

在Vue中还实现了一个叫做Watcher的类,这个类的实例就是我们上面说的那个谁。换句话说,谁用到了数据,我们就为谁创建一个Watcher实例。在之后数据变化时,我们不直接去通知依赖更新,而是去通知依赖对应的watch实例,由watcher实例去通知真正的视图

类的具体实现如下:

export default class Watcher {constructor (vm,expOrFn,cb) {this.vm = vm;this.cb = cb;this.getter = parsePath(expOrFn)this.value = this.get()}get () {window.target = this;const vm = this.vmlet value = this.getter.call(vm, vm)window.target = undefined;return value}update () {const oldValue = this.valuethis.value = this.get()this.cb.call(this.vm, value, oldValue)}
}
​
/*** Parse simple path.* 把一个形如'data.a.b.c'的字符串路径所表示的值,从真实的data对象中取出来* 例如:* data = {a:{b:{c:2}}}* parsePath('a.b.c')(data)  // 2*/
const bailRE = /[^\w.$]/
export function parsePath (path) {if (bailRE.test(path)) {return}const segments = path.split('.')return function (obj) {for (let i = 0; i < segments.length; i++) {if (!obj) returnobj = obj[segments[i]]}return obj}
}

分析代码:

1.实例化Watcher类时,会先执行其构造函数;

2.在构造函数中调用了this.get()实例方法;

3.在get()方法中,首先通过window.target = this 把实例自身赋给了全局的一个唯一对象window.target上,然后通过let value = this.getter.call(vm,vm)获取一下被依赖的数据,这里的目的是触发该数据的getter,在上文说过,调用getter会随之调用dep.depend()方法收集依赖,而在dep.depend()上取到挂载到window.target的值并将其存到依赖数组中,在get()方法最后需要将window.target释放掉

4.当数据变化时,会触发setter,在其中执行了dep.notify()方法,在这个方法中,遍历所有的依赖(即watcher实例),执行依赖的update()方法,在方法中调用数据变化的更新回调函数,从而更新视图。

3.不足之处

通过defineProperty方法实现了对Object数据的观测,但是这个方法仅仅只能观测到其中数据及设置值,如果向Object中添加或删除值时,他是无法观察到的,导致添加或者删除值时,无法通知依赖,无法驱动视图更新。vue也注意到了这一点,所以为了解决这个问题,vue添加了两个全局api:$set $delete,在后面学习全局API时会说到。

4.总结

通过Object.defineProperty方法实现了对object数据的可观测,并且封装了Observer类,让我们能够方便的把object数据中的所有属性(包括子属性)都转换成getter/seter的形式来侦测变化。

接着,知道了在getter中收集依赖,在setter中通知依赖更新,以及封装了依赖管理器Dep,用于存储收集到的依赖。

最后,我们为每一个依赖都创建了一个Wtcher实例,当数据发生变化时,通知Watcher实例,由Watcher实例去做真实的更新操作。

其整个流程大致如下:

  1. Data通过observer转换成了getter/setter的形式来追踪变化。

  2. 当外界通过Watcher读取数据时,会触发getter从而将Watcher添加到依赖中。

  3. 当数据发生了变化时,会触发setter,从而向Dep中的依赖(即Watcher)发送通知。

  4. Watcher接收到通知后,会向外界发送通知,变化通知到外界后可能会触发视图更新,也有可能触发用户的某个回调函数等。

相关文章:

根据源码解析Vue2中对于对象的变化侦测

UI render(state) VUE的特点是数据驱动视图&#xff0c;在这里可以把数据理解为状态&#xff0c;而视图就是用户可以看到的页面&#xff0c;页面是动态变化的&#xff0c;而他的变化或是用户操作引起&#xff0c;或是后端数据变化引起&#xff0c;这些都可以说是数据的状态变…...

爬虫技术深潜:探究 JsonPath 与 XPath 的语法海洋与实战岛屿

Python爬虫中JSON与XML字符串的XPath和JsonPath过滤语法区别对比 在信息爆炸的互联网时代&#xff0c;数据抓取成为了获取宝贵信息的关键技能。对于技术爱好者&#xff0c;特别是Python程序员来说&#xff0c;熟练掌握JSON和XML数据解析方法至关重要。本文旨在深入探讨这两种格…...

纠删码参数自适应匹配问题ECP-AMP实验方案(一)

摘要 关键词&#xff1a;动态参数&#xff1b;多属性决策&#xff1b;critic权重法&#xff1b;DBSCA聚类分析 引言 云服务存储系统是一种基于互联网的数据存储服务&#xff0c;它可以为用户提供大规模、低成本、高可靠的数据存储空间。云服务存储系统的核心技术之一是数据容…...

五、人物持有武器攻击

一、手部添加预制体&#xff08;武器&#xff09; 1、骨骼&#xff08;手&#xff09; 由于人物模型有骨骼和动画&#xff0c;在添加预制体后&#xff0c;会抓握武器 建一个预制体在手部位置 二、添加武器拖尾 下载拖尾特效 赋值特效中的代码&#xff0c;直接使用 清空里面…...

mysql索引 -- 全文索引介绍(如何创建,使用),explain关键字

目录 全文索引 引入 介绍 创建 使用 表数据 简单搜索 explain关键字 使用全文索引 mysql索引结构详细介绍 -- mysql索引 -- 索引的硬件理解(磁盘,磁盘与系统),软件理解(mysql,与系统io,buffer pool),索引结构介绍和理解(page内部,page之间,为什么是b树)-CSDN博客 全文…...

Wayfair封号的常见原因及解决方案解析

近期关于Wayfair账号封禁的问题引发了广泛讨论。许多用户报告称&#xff0c;他们的Wayfair账户被突然封禁&#xff0c;这一现象不仅影响了用户的购物体验&#xff0c;也对Wayfair的品牌形象造成了一定的冲击。本文将深入探讨Wayfair封号的原因&#xff0c;并提出相应的解决方案…...

计算机视觉方面的一些模块

# __all__ 是一个可选的列表&#xff0c;定义在模块级别。当使用 from ... import * 语句时&#xff0c;如果模块中定义了 # __all__&#xff0c;则只有 __all__ 列表中的名称会被导入。这是模块作者控制哪些公开API被导入的一种方式。 # 使用 * 导入的行为 # 如果模块中有 __a…...

进阶美颜功能技术开发方案:探索视频美颜SDK

视频美颜SDK&#xff08;SoftwareDevelopmentKit&#xff09;作为提升视频质量的重要工具&#xff0c;越来越多地被开发者关注与应用。接下俩&#xff0c;笔者将深入探讨进阶美颜功能的技术开发方案&#xff0c;助力开发者更好地利用视频美颜SDK。 一、视频美颜SDK的核心功能 …...

【重学 MySQL】三十八、group by的使用

【重学 MySQL】三十八、group by的使用 基本语法示例示例 1: 计算每个部门的员工数示例 2: 计算每个部门的平均工资示例 3: 结合 WHERE 子句 WITH ROLLUP基本用法示例注意事项 注意事项 GROUP BY 是 SQL 中一个非常重要的子句&#xff0c;它通常与聚合函数&#xff08;如 COUNT…...

SSM框架VUE电影售票管理系统开发mysql数据库redis设计java编程计算机网页源码maven项目

一、源码特点 smm VUE电影售票管理系统是一套完善的完整信息管理类型系统&#xff0c;结合SSM框架和VUE、redis完成本系统&#xff0c;对理解vue java编程开发语言有帮助系统采用ssm框架&#xff08;MVC模式开发&#xff09;&#xff0c;系 统具有完整的源代码和数据库&#…...

基于Hive和Hadoop的白酒分析系统

本项目是一个基于大数据技术的白酒分析系统&#xff0c;旨在为用户提供全面的白酒市场信息和深入的价格分析。系统采用 Hadoop 平台进行大规模数据存储和处理&#xff0c;利用 MapReduce 进行数据分析和处理&#xff0c;通过 Sqoop 实现数据的导入导出&#xff0c;以 Spark 为核…...

【软考】高速缓存的组成

目录 1. 说明2. 组成 1. 说明 1.高速缓存用来存放当前最活跃的程序和数据。2.高速缓存位于CPU 与主存之间。3.容量般在几千字节到几兆字节之间。4.速度一般比主存快 5~10 倍&#xff0c;由快速半导体存储器构成。5.其内容是主存局部域的副本&#xff0c;对程序员来说是透明的。…...

UniApp基于xe-upload实现文件上传组件

xe-upload地址&#xff1a;文件选择、文件上传组件&#xff08;图片&#xff0c;视频&#xff0c;文件等&#xff09; - DCloud 插件市场 致敬开发者&#xff01;&#xff01;&#xff01; 感觉好用的话&#xff0c;给xe-upload的作者一个好评 背景&#xff1a;开发中经常会有…...

以太网交换安全:端口隔离

一、端口隔离 以太交换网络中为了实现报文之间的二层广播域的隔离&#xff0c;用户通常将不同的端口加人不同的 VLAN大型网络中&#xff0c;业务需求种类繁多&#xff0c;只通过 VLAN实现报文的二层隔离&#xff0c;会浪费有限的VLAN资源。而采用端口隔离功能&#xff0c;则可…...

望繁信科技CTO李进峰受邀在上海外国语大学开展流程挖掘专题讲座

2023年&#xff0c;望繁信科技联合创始人兼CTO李进峰博士受邀在上海外国语大学国际工商管理学院&#xff08;以下简称“上外管院”&#xff09;开展专题讲座&#xff0c;畅谈流程挖掘的发展及对企业数字化转型的价值。演讲吸引了上外教授和来自各行各业的领军企业学员百余人。 …...

nicegui组件button用法深度解读,源代码IDE运行和调试通过

传奇开心果微博文系列 前言一、button 组件基本用法1. 最基本用法示例2. 创建带图标按钮 二、button按钮组件样式定制1. 按钮的尺寸调整2. 改变颜色示例3. 按钮的自定义字体大小4. 圆角形状示例5. 自定义边框6. 添加阴影7. 复合按钮8. 浮动按钮9. 可扩展浮动操作按钮QFAB10. 按…...

数据结构:树(并查集)

并查集&#xff08;Union-Find Disjoint Sets 或 Disjoint Set Union&#xff0c;简称DSU&#xff09;是一种树型的数据结构&#xff0c;主要用于处理一些不相交集合&#xff08;Disjoint Sets&#xff09;的合并及查询问题。在并查集中&#xff0c;通常将n个对象划分为不相交的…...

校园二手交易平台的小程序+ssm(lw+演示+源码+运行)

摘 要 随着社会的发展&#xff0c;社会的方方面面都在利用信息化时代的优势。互联网的优势和普及使得各种系统的开发成为必需。 本文以实际运用为开发背景&#xff0c;运用软件工程原理和开发方法&#xff0c;它主要是采用java语言技术和mysql数据库来完成对系统的设计。整个…...

代码随想录训练营第46天|回文子序列

647. 回文子串 class Solution { public:int count0;void check(string& s, int left, int right){while(left>0&&right<s.length()&&s[left]s[right]){count;left--;right;}}int countSubstrings(string s) {for(int i0; i<s.length(); i){chec…...

使用 PowerShell 命令更改 RDP 远程桌面端口(无需修改防火墙设置)

节选自原文&#xff1a;Windows远程桌面一站式指南 | BOBO Blog 原文目录 什么是RDP&#xfffc;开启远程桌面 检查系统版本启用远程桌面连接Windows 在Windows电脑上在MAC电脑上在Android或iOS移动设备上主机名连接 自定义电脑名通过主机名远程桌面使用Hosts文件自定义远程主…...

bilibili实现批量发送弹幕功能

代码如下&#xff1a; import random import time import requests from tkinter import *# 弹幕内容列表 # lis_text [ # 京口瓜洲一水间&#xff0c;钟山只隔数重山。,君不见黄河之水天上来&#xff0c;奔流到海不复回。,起舞弄清影&#xff0c;何似在人间! # ] lis_te…...

如何查看上网记录及上网时间?5种按步操作的方法分享!【小白也能学会!】

“知己知彼&#xff0c;百战不殆”&#xff0c;在数字时代&#xff0c;了解自己的上网行为和时长&#xff0c;不仅能帮助我们更好地管理时间&#xff0c;还能提升工作效率和生活质量。 今天&#xff0c;我们就来分享五种简单易懂的方法&#xff0c;即便是网络小白也能轻松学会…...

Nisshinbo日清纺pvs1114太阳模拟器手测

Nisshinbo日清纺pvs1114太阳模拟器手测...

多线程复杂系统调试利器——assert()

调试复杂系统时&#xff0c;最大的难点在于定位问题&#xff0c;如果弄清楚了问题产生的机理&#xff0c;那么就能有针对性的进行解决。 调试复杂系统时&#xff0c;遇到不好定位的问题&#xff0c;就要大胆去猜、去怀疑、去假设&#xff0c;尤其是应该重点怀疑多线程访问&…...

【2024.9.28练习】青蛙的约会

题目描述 题目分析 由于两只青蛙都在跳跃导致变量多&#xff0c;不妨采用物理题中的相对运动思想&#xff0c;设青蛙A不动&#xff0c;青蛙B每次跳米&#xff0c;两只青蛙的距离为米。正常来说&#xff0c;只要模拟青蛙B与青蛙A的相对运动过程&#xff0c;最终当青蛙B与青蛙A距…...

Python入门:类的异步资源管理与回收( __del__ 方法中如何调用异步函数)

文章目录 📖 介绍 📖🏡 演示环境 🏡📒 文章内容 📒📝 使用上下文管理器📝 使用 `__del__` 方法📝 结合使用上下文管理器与 `__del__`📝 资源回收的重要性⚓️ 相关链接 ⚓️📖 介绍 📖 在编程中,资源的管理和回收至关重要,尤其是在处理网络请求时。频…...

Android开发中的ViewModel

在Android应用开发中&#xff0c;ViewModel作为架构组件之一&#xff0c;扮演着管理UI数据和生命周期的关键角色。本文将深入探讨ViewModel如何感知View的生命周期&#xff0c;并分析其内核原理&#xff0c;帮助开发者更好地利用ViewModel优化应用架构。 一、ViewModel简介 在…...

Vue 3 文件编译流程详解与 Babel 的使用

文章目录 一、背景二、结论三、vitejs/plugin-vue 插件调试前物料准备vuePlugin 入口buildStart 方法transform 方法 四、vue/compiler-sfc 核心包parse 方法compileScript、rewriteDefault 方法compileTemplate 方法 五、整体架构六、总结参考资料 一、背景 最近正在研究 rea…...

Android常用C++特性之std::chrono

声明&#xff1a;本文内容生成自ChatGPT&#xff0c;目的是为方便大家了解学习作为引用到作者的其他文章中。 std::chrono 是 C11 引入的标准库中的时间处理工具&#xff0c;提供了以多种精度进行时间测量、处理和操作的功能。它允许开发者处理时间点&#xff08;time_point&am…...

[Oracle] ORA-04036: 实例使用的 PGA 内存超出 PGA_AGGREGATE_LIMIT

有说该问题是因为触发了Oracle的BUG导致&#xff0c;最直接的解决方法就是重启数据库实例&#xff1b; Linux下数据库实例重启...