读 vue 源码一 (为什么this.message能够访问data里面的message)
12月离职后,打算在年后再找工作了,最近陆陆续续的看了黄轶老师的vue源码解析,趁着还有几天过年时间记录一下。
目标:vue如何实现通过this.key,就能直接访问data,props,methods,里面的key。
源码:当我们在项目中new Vue实例后会执行Vue构造函数的_init方法,并执行一些混入
function Vue (options) {
if (process.env.NODE_ENV !== 'production' &&
!(this instanceof Vue)
) {
warn('Vue is a constructor and should be called with the `new` keyword')
}
this._init(options)
}
initMixin(Vue)
stateMixin(Vue)
eventsMixin(Vue)
lifecycleMixin(Vue)
renderMixin(Vue)
_init方法定义在initMixin方法中,在Vue原型上定义了_init方法,其他逻辑暂时不做分析,这里我们看到 将Vue实例赋值给了vm,然后合并options,然后执行了一些初始化方法,最后挂载方法。
export function initMixin (Vue: Class<Component>) {
Vue.prototype._init = function (options?: Object) {
const vm: Component = this
// a uid
vm._uid = uid++
// merge options
if (options && options._isComponent) {
// optimize internal component instantiation
// since dynamic options merging is pretty slow, and none of the
// internal component options needs special treatment.
initInternalComponent(vm, options)
} else {
vm.$options = mergeOptions(
resolveConstructorOptions(vm.constructor),
options || {},
vm
)
}
vm._self = vm
initLifecycle(vm)
initEvents(vm)
initRender(vm)
callHook(vm, 'beforeCreate')
initInjections(vm) // resolve injections before data/props
initState(vm)
initProvide(vm) // resolve provide after data/props
callHook(vm, 'created')
if (vm.$options.el) {
vm.$mount(vm.$options.el)
}
}
}
我们能够通过this.key访问是在initState方法执行时,里面执行了initData方法
export function initState (vm: Component) {
vm._watchers = []
const opts = vm.$options
if (opts.props) initProps(vm, opts.props)
if (opts.methods) initMethods(vm, opts.methods)
if (opts.data) {
initData(vm)
} else {
observe(vm._data = {}, true /* asRootData */)
}
if (opts.computed) initComputed(vm, opts.computed)
if (opts.watch && opts.watch !== nativeWatch) {
initWatch(vm, opts.watch)
}
}
initData方法实现如下,首先将data赋值给vm._data,然后判断data,props,methods里是否重名,然后调用proxy方法,最后调用observe方法将其变成响应式对象,这里暂不分析
function initData (vm: Component) {
let data = vm.$options.data
data = vm._data = typeof data === 'function'
? getData(data, vm)
: data || {}// proxy data on instance
const keys = Object.keys(data)
const props = vm.$options.props
const methods = vm.$options.methods
let i = keys.length
while (i--) {
const key = keys[i]
if (process.env.NODE_ENV !== 'production') {
if (methods && hasOwn(methods, key)) {
warn(
`Method "${key}" has already been defined as a data property.`,
vm
)
}
}
if (props && hasOwn(props, key)) {
process.env.NODE_ENV !== 'production' && warn(
`The data property "${key}" is already declared as a prop. ` +
`Use prop default value instead.`,
vm
)
} else if (!isReserved(key)) {
proxy(vm, `_data`, key)
}
}
// observe data
observe(data, true /* asRootData */)
}
proxy方法实现就是更改defineProperty里的属性,将其的getter和setter,代理到sourceKey上,也就是我们上面说的vm._data上,然后我们就可以通过this.key访问data,props,message里面的key了
const sharedPropertyDefinition = {
enumerable: true,
configurable: true,
get: noop,
set: noop
}
export function proxy (target: Object, sourceKey: string, key: string) {
sharedPropertyDefinition.get = function proxyGetter () {
return this[sourceKey][key]
}
sharedPropertyDefinition.set = function proxySetter (val) {
this[sourceKey][key] = val
}
Object.defineProperty(target, key, sharedPropertyDefinition)
}
读 vue 源码一 (为什么this.message能够访问data里面的message)的更多相关文章
- 读Vue源码 (依赖收集与派发更新)
vue的依赖收集是定义在defineReactive方法中,通过Object.defineProperty来设置getter,红字部分主要做依赖收集,先判断了Dep.target如果有的情况会执行红字 ...
- 读Vue源码二 (响应式对象)
vue在init的时候会执行observer方法,如果value是对象就直接返回,如果对象上没有定义过_ob_这个属性,就 new Observer实例 export function observe ...
- 读懂源码:一步一步实现一个 Vue
源码阅读:究竟怎样才算是读懂了? 市面上有很多源码分析的文章,就我看到的而言,基本的套路就是梳理流程,讲一讲每个模块的功能,整篇文章有一大半都是直接挂源码.我不禁怀疑,作者真的看懂了吗?为什么我看完后 ...
- 【读fastclick源码有感】彻底解决tap“点透”,提升移动端点击响应速度
申明!!!最后发现判断有误,各位读读就好,正在研究中.....尼玛水太深了 前言 近期使用tap事件为老夫带来了这样那样的问题,其中一个问题是解决了点透还需要将原来一个个click变为tap,这样的话 ...
- Vue源码后记-钩子函数
vue源码的马拉松跑完了,可以放松一下写点小东西,其实源码讲20节都讲不完,跳了好多地方. 本人技术有限,无法跟大神一样,模拟vue手把手搭建一个MVVM框架,然后再分析原理,只能以门外汉的姿态简单过 ...
- 大白话Vue源码系列(01):万事开头难
阅读目录 Vue 的源码目录结构 预备知识 先捡软的捏 Angular 是 Google 亲儿子,React 是 Facebook 小正太,那咱为啥偏偏选择了 Vue 下手,一句话,Vue 是咱见过的 ...
- 【vuejs深入三】vue源码解析之二 htmlParse解析器的实现
写在前面 一个好的架构需要经过血与火的历练,一个好的工程师需要经过无数项目的摧残. 昨天博主分析了一下在vue中,最为基础核心的api,parse函数,它的作用是将vue的模板字符串转换成ast,从而 ...
- 【一套代码小程序&Native&Web阶段总结篇】可以这样阅读Vue源码
前言 前面我们对微信小程序进行了研究:[微信小程序项目实践总结]30分钟从陌生到熟悉 在实际代码过程中我们发现,我们可能又要做H5站又要做小程序同时还要做个APP,这里会造成很大的资源浪费,如果设定一 ...
- vue源码逐行注释分析+40多m的vue源码程序流程图思维导图 (diff部分待后续更新)
vue源码业余时间差不多看了一年,以前在网上找帖子,发现很多帖子很零散,都是一部分一部分说,断章的很多,所以自己下定决定一行行看,经过自己坚持与努力,现在基本看完了,差ddf那部分,因为考虑到自己要换 ...
随机推荐
- set和 map 数据结构
set/map数据结构 创建: var s=new Set(); 添加成员 s.add(1) 遍历 for of s.froEach 删除 s.delete() 判断存在 s.has() 清除 s. ...
- Android字符串,颜色,尺寸资源的使用
字符串.颜色.尺寸资源文件这三种文件位于res文件夹的values文件夹中,名称分别为strings.xml , colors.xml , dimens.xml下面是例子,首先来看字符串资源文件str ...
- 64IE无法显示网页
1.碰到如下图情况ie浏览器打开之后显示不了网页,但是试了下电脑上其他的浏览器都可以正常的打开网页. 2.解决办法为:打开浏览器-选择“工具”-“Internet选项”-“高级”-重置,重启浏览器后能 ...
- 构建react项目失败解决办法
1.初始化项目,报下方错误 2.解决方法,更新淘宝镜像 npm config set registry https://registry.npm.taobao.org 3.在初始化项目 create- ...
- esp32固件烧录
正常使用IO0置空即可.烧录时需要en引脚接高电平,IO0接地,使用乐鑫的烧录工具烧录即可.注意如果启用wifi,供电一定要不小于500ma,普通的usb转ttl模块无法满足wifi启动的,被坑的好惨 ...
- idea将maven项目打包成war包
1.单击红色方框处 2.在IDEA右侧出现maven project选项 3.单击maven project选项,出现Spring MVC Basic Feature菜单,选择 其中的Lifecycl ...
- dddquickly
在项目开发最初的时候,他也有过一段狂欢般的快乐时光,不久之后,事情就越来越艰难. 项目的代码越来越难以维护,工作越来越像是一种煎熬,合作的同事对他越来越不满. “该是与这个项目,与这个公司说 bye ...
- 使用pushstate,指定回退地址
history.pushState(null,"testname", window.location.href); window.addEventListener('popstat ...
- RedHat Enterprise Linux 6.4使用网易Centos 6 的yum源
1.首先到http://mirrors.163.com/centos下载软件包 x86 地址:http://mirrors.163.com/centos/6/os/i386/Packages/ x86 ...
- linux运维需要掌握什么知识?linux运维学习路线
linux运维需要掌握什么知识?这个问题算是老生常谈了,但是本人认为知道需要掌握什么知识不是重点,重点是我们需要知道运维是做什么的?再来根据工作需求去讨论需要学习什么知识才是正途,须知知识是学不完的, ...