Vue源码中的数据代理
直接开讲:
由于这个Vue底层封装的函数太多了,我这里只讲思路不说具体的执行了什么函数.
const vm=new Vue({这里写一个data,可以是对象也可以是函数}) 在写这段代码的时候new就已经开始运转了
首先:Vue底层是一个构造函数,然后底层在这个构造函数的原型(prototype)上放了一个_init方法,我们在new的时候,就启动这个方法了,可以知道这个方法的this就是构造函数的实例对象的__proto__,在_init这个方法里面就把this赋值给了一个变量叫做vm,然后往这个vm上面放了一个$options,再把{}赋值给了$options.
其次,延续上面,又调用了一个函数,把vm传过去,在函数里面判断vm.$options.data是否为function,如果是function就涉及到了一个this指向问题,就需要把这个函数的this指向vm,如果是对象那么直接进入下面,下面就是在vm身上添加了一个_data属性,这个再给这个_data赋与vm.$options.data,然后直接将vm.$options.data传入到另外一个函数中,这个函数在这里取个名字叫observe(),到后面会循环使用这个函数,也可以说是一个递归函数;
延续上一段,在另外一个函数中判断传送过来的如果不是一个对象或者说是不是null,满足这其中任意一个条件就return;如果是对象就直接return new Observer(vm.$options.data).
(下面这一段先说一下代理vm.$options.data,调用set方法往里面添加对象和数组的情况,也没有重写数组的7个方法)
这里这个new Observer(data)是vue源码中写的一个类,这个类里面会判断data是不是一个数组,是数组就将这个数组里面的所有元素都遍历一遍,然后在传递到observe(item)对象里面,如果一直嵌套就一直回去这个函数,这里需要说一下,如果是数组里面对应索引处是一个普通数据类型就会在observe函数里return掉.这就表示在vue2中数组中的普通数据类型是不会进行数据代理的
上面的这一段说了是数组的情况,这里说一下是对象的情况,如果传入observe(data)是一个对象,那么直接Object.keys().forEach(item=>{在这里调用一个函数,将目标函数和需要代理的key传送过去}),传送过去就会进行一个判断,如果是对象就继续将这个对象传入到observe(item)里面去,直到他不是一个对象为止.
注:如果使用数组的方法去添加值,只用上面的这些逻辑是不够的,刚添加上的数据不会被检测到.那么如果想解决这个问题,就需要在使用push方法时候吧push进去的东西进行一次数据代理.
vue对数组方法的重写:①将Array的prototype赋值给一个对象②使用Object.create()方法将创建的这个对象的this指向①中的对象,现在从当前这个对象往上推,其实就有三层原型了.(Array.prototype.proto.proto)然后把这个原型给了data.proto,这里要注意,现在data有了三层原型(data.proto.proto.proto)然后data.proto.__proto__这个对象里面有所有的数组的方法,然后vue给data.__proto__上面有加了7个方法('push','pop','shift','unshift','reserve','sort','splice'),然后调用push,肯定是data调的,然后data的原型第一层就能够拿到重写好的push(),还给push进去的数据进行了代理.
总结:
底层给data中的数据进行了数据代理,不会代理数组中存在的基本数据类型元素,对set方法添加的数据进行判断并代理,给数组方法进行重写并代理数组中存在的对象里面的属性.重写后的数组添加新元素会进行判断并代理
Vue源码中的数据代理的更多相关文章
- Vue源码学习之数据初始化
首发地址:CJWbiu's Blog 在这里思考一个问题,使用Vue的时候需要在创建Vue实例时传入一个option,这里包含了我们定义的props.methods.data等.而在methods的方 ...
- 【Vue】VUE源码中的一些工具函数
Vue源码-工具方法 /* */ //Object.freeze()阻止修改现有属性的特性和值,并阻止添加新属性. var emptyObject = Object.freeze({}); // th ...
- vue源码中computed和watch的解读
computed 会基于其内部的 响应式依赖 进行缓存. 只在相关 响应式依赖发生改变 时 它们才会重新求值. 可以在将模板中使用的常量放在计算属性中. watch 监听数据变化,并在监听回调函数中返 ...
- nodeType属性在vue源码中的使用
每个节点都有一个 nodeType 属性,用于表明节点的类型,节点类型由 Node 类型中定义12个常量表示: nodeType在vue中的应用 在vue编译的过程中需要查找html结构中的双大括号 ...
- 了解一下vue源码中vue 的由来
我们之前提到过 Vue.js 构建过程,在 web 应用下,我们来分析 Runtime + Compiler 构建出来的 Vue.js,它的入口是 src/platforms/web/entry-r ...
- Vue源码中compiler部分逻辑梳理(内有彩蛋)
目录 一. 简述 二. 编译流程 三. 彩蛋环节 示例代码托管在:http://www.github.com/dashnowords/blogs 博客园地址:<大史住在大前端>原创博文目录 ...
- 从Vue源码中我学到了几点精妙方法
话不多说,赶快试试这几个精妙方法吧!在工作中肯定会用得到. 立即执行函数 页面加载完成后只执行一次的设置函数. (function (a, b) { console.log(a, b); // 1,2 ...
- Vue源码解析---数据的双向绑定
本文主要抽离Vue源码中数据双向绑定的核心代码,解析Vue是如何实现数据的双向绑定 核心思想是ES5的Object.defineProperty()和发布-订阅模式 整体结构 改造Vue实例中的dat ...
- 【Vuejs】350- 学习 Vue 源码的必要知识储备
前言 我最近在写 Vue 进阶的内容.在这个过程中,有些人问我看 Vue 源码需要有哪些准备吗?所以也就有了这篇计划之外的文章. 当你想学习 Vue 源码的时候,需要有扎实的 JavaScript 基 ...
- vue源码解析之observe
一. vue文档中有"由于 JavaScript 的限制,Vue 不能检测以下数组的变动",是否真是由于JavaScript的限制,还是出于其他原因考虑 当你利用索引直接设置一个数 ...
随机推荐
- ubuntu18.04下联想电脑不能打开wifi
一.问题描述: 本人使用联想拯救者14IFI笔记本在安装Ubuntu系统时会出现无线硬件开关关闭的问题,当然也就无法连网(Wi-Fi). (最好先使用 sudo rfkill unblock all) ...
- 题解 [SCOI2007]压缩
好题. 显然区间 dp,令 \(f_{l, r}\) 为 \([l, r]\) 之间的最短的长度.如果我们要压缩,那么就要考虑 M 与 R 的位置.由于我们大体是从左往右来转移的,所以显然我们只需要记 ...
- Vmware15 + Ubuntu18.0.4 安装教程(史上最详细记录)【多图预警】
转载csdn: Vmware15 + Ubuntu18.0.4 安装教程(史上最详细记录)[多图预警]_亦靈兒的博客-CSDN博客
- CF846E - Chemistry in Berland
题意:有一颗树,每个点上有 \(b_i\) 东西,从叶子往上的汇率是 \(1:1\),从父亲往下的汇率是 \(k:1\),求能否使每个点的东西都不少于 \(a_i\). 我们发现,从上往下肯定是不划算 ...
- 基于Python的OpenGL 05 之坐标系统
1. 引言 本文基于Python语言,描述OpenGL的坐标系统 前置知识可参考: 基于Python的OpenGL 04 之变换 - 当时明月在曾照彩云归 - 博客园 (cnblogs.com) 笔者 ...
- Angular 利用路由快照实现tab
1.定义路由快照 新建文件SimpleReuseStrategy.ts import { RouteReuseStrategy, DefaultUrlSerializer, ActivatedRout ...
- vue2+ts 设计一个扑克牌比大小的游戏
首先
- Supported OPs and DPU Limitations
Currently Supported Operators source:https://www.xilinx.com/html_docs/xilinx2019_2/vitis_doc/zmw1606 ...
- zookeeper要点总结
简述:zookeeper分布式协调服务,节点数据存储在内存,高吞吐,低延时,zkserver cluster组建zookeeper service保证自身高可用 zookeeper数据模型为类文件目录 ...
- lg8935 [JRKSJ R7] 茎 题解
由于标签内包含背包和树形dp,所以考虑用背包dp和树形dp求解. 考虑每次合并2个连通块(一个包含根节点),设\(f_{i,j}\)表示\(i\)子树内,操作\(j\)次的方案数(未合并连通块),设\ ...