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的限制,还是出于其他原因考虑 当你利用索引直接设置一个数 ...
随机推荐
- 鼎阳SDS6204示波器的EPICS IOC调试
经过雷雷师弟的努力,该款示波器终于调试成功,相关文件现放在gitee仓库里: https://gitee.com/lup9304/siglent/commit/99ce00d195facd87fa1c ...
- jmeter常见错误(持续更新)
1. jmeter java.net.NoRouteToHostException: Cannot assign requested address (Address not available) 压 ...
- go 神奇的错误 time.Now().Format("2006-01-02 13:04:05") 比北京时间大8小时
困倦的时候写了个个获取本地时间,打印总比当前时间大8小时,找了很久原因 package main import ( "fmt" "time" ) func ma ...
- vue还可以这样写
1.这两种写法都可以: var vm = new Vue({ data(){ return { scaleFlag:'big', } }, //data:{}, created: function ( ...
- Linux:touch 修改文件的时间
修改本文件的时间 参数 描述 例子 -a 只修改访问时间(Access Time) touch -a hello.txt -m 只更新修改时间(Modify Time) touch -m hello. ...
- PostgreSQL数据库运行日志
PostgreSQL运行日志可以实现日志输出记录,默认是没有启动记录.这个日志一般是记录服务器与DB的状态,比如各种Error信息,定位慢查询SQL,数据库的启动关闭信息,发生checkpoint过于 ...
- ding抓回放
fiddler 添加代码 var sToInsert = "<script src='https://cdn.jsdelivr.net/gh/Tencent/vConsole@3.8. ...
- asp多模块功能代码,单调用插入的case方法
function getmodule(arg) select case arg case "pinyin" aaa="123" %><!--#插入页 ...
- PHP实现QQ第三方登录代码
前言: PHP实现QQ快速登录,罗列了三种方法 方法一:面向过程,回调地址和首次触发登录写到了一个方法页面[因为有了if做判断], 方法二,三:面向对象 1.先调用登录方法,向腾讯发送请求,2.腾讯携 ...
- SAP VL02N 字段不允许编辑
METHOD if_ex_le_shp_delivery_proc~change_field_attributes. data: ls_field_attributes type shp_screen ...