Vue源码学习二 ———— Vue原型对象包装
Vue原型对象的包装
在Vue官网直接通过 script 标签导入的 Vue包是 umd模块的形式。在使用前都通过 new Vue({})。记录一下 Vue构造函数的包装。
在 src/core/instance/index.js 这个文件是 Vue构造函数的出生地。
import { initMixin } from './init'
import { stateMixin } from './state'
import { renderMixin } from './render'
import { eventsMixin } from './events'
import { lifecycleMixin } from './lifecycle'
import { warn } from '../util/index'
function Vue (options) {
// 使用安全模式来提醒要使用new操作符来调用Vue
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)
}
/**
* 在执行npm run dev构建运行时执行, 包装Vue.prototype。为其添加一些属性和方法
*/
initMixin(Vue)
stateMixin(Vue)
eventsMixin(Vue)
lifecycleMixin(Vue)
renderMixin(Vue)
export default Vue
首先导入了五个方法
- initMixin
- stateMixin
- renderMixin
- eventsMixin
- lifecycleMixin
如果不是在生产环境下,且不通过 new 来调用Vue 会得到警告。
接下来执行 initMixin方法, 到 initMixin来源文件看。
export function initMixin (Vue: Class<Component>) {
Vue.prototype._init = function (){}
}
首先会在 Vue这个构造函数的原型对象上定义一个 _init方法。这个方法是在通过 new Vue({})的时候执行。在 Vue 构造函数中可以看到 this._init(options)。
接着将 Vue构造函数作为参数传递给下一个 stateMixin方法, 到stateMixin来源文件看。
export function stateMixin (Vue: Class<Component>) {
// flow somehow has problems with directly declared definition object
// when using Object.defineProperty, so we have to procedurally build up
// the object here.
const dataDef = {}
dataDef.get = function () { return this._data }
const propsDef = {}
propsDef.get = function () { return this._props }
// 设置两个只读的属性 $data $props
if (process.env.NODE_ENV !== 'production') {
dataDef.set = function () {
warn(
'Avoid replacing instance root $data. ' +
'Use nested data properties instead.',
this
)
}
propsDef.set = function () {
warn(`$props is readonly.`, this)
}
}
Object.defineProperty(Vue.prototype, '$data', dataDef)
Object.defineProperty(Vue.prototype, '$props', propsDef)
Vue.prototype.$set = set
Vue.prototype.$delete = del
Vue.prototype.$watch = function (){}
}
其中
Object.defineProperty(Vue.prototype, '$data', dataDef)
Object.defineProperty(Vue.prototype, '$props', propsDef)
这是在 Vue的原型对象上定义了两个属性 $data 和 $props。其中分别代理了 _data 和 _props。看 dataDef 这个对象上定义了一个 get 方法, 最终返回当前实例对象的 _data。props 也是这样子的。
if (process.env.NODE_ENV !== 'production') {
dataDef.set = function () {
warn(
'Avoid replacing instance root $data. ' +
'Use nested data properties instead.',
this
)
}
propsDef.set = function () {
warn(`$props is readonly.`, this)
}
}
当你在非生产环境时, 如果修改 $data 和 $props会得到警告信息。
最后在 Vue.prototype上还定义了 $set、$delete以及 $watch。。
接下来是 eventMixin方法, 进入这个方法的来源文件
export function eventsMixin (Vue: Class<Component>) {
Vue.prototype.$on = function(){};
Vue.prototype.$once = function(){};
Vue.prototype.$off = function(){};
}
又再 Vue.prototype 上定义了三个方法, 分别是 $on、$once和$off。
接下来执行 lifecycleMixin 方法, 看lifecycleMixin方法的来源文件:
export function lifecycleMixin (Vue: Class<Component>) {
Vue.prototype._update = function() {}
Vue.prototype.$forceUpdate = function() {}
Vue.prototype.$destroy = function(){}
在 lifecycleMixin 方法中又向 Vue的原型对象 prototype上添加了三个方法。分别是 _update、$$forceUpdate和$$destroy。
$forceUpdate: 迫使 Vue 实例重新渲染。注意它仅仅影响实例本身和插入插槽内容的子组件,而不是所有子组件。
最后一个执行 renderMixin方法。在renderMixin来源文件可以到。
首先执行了一个 installRenderHelpers(Vue.prototype),这个方法的主要作用也是向 Vue.prototype上添加方法, 看它源文件是:
// 这个函数主要在Vue.prototype上面添加一些方法
export function installRenderHelpers (target: any) {
target._o = markOnce
target._n = toNumber
target._s = toString
target._l = renderList
target._t = renderSlot
target._q = looseEqual
target._i = looseIndexOf
target._m = renderStatic
target._f = resolveFilter
target._k = checkKeyCodes
target._b = bindObjectProps
target._v = createTextVNode
target._e = createEmptyVNode
target._u = resolveScopedSlots
target._g = bindObjectListeners
}
紧接着又向 Vue.prototype对象上添加了 $nextTick和_render方法。
export function renderMixin (Vue: Class<Component>) {
// install runtime convenience helpers
installRenderHelpers(Vue.prototype)
Vue.prototype.$nextTick = function (fn: Function) {
return nextTick(fn, this)
}
Vue.prototype._render = function (): VNode {}
执行完 renderMixin这个方法, Vue构造函数的出生文件也运行完了。也就是指在 npm run dev命令构建时运行。这里的每一个方法 *Mixin的作用就是包装 Vue.prototype, 对其挂载一些属性和方法。最后 export default Vue将其导出这个构造函数。此时 Vue.prototype上添加的属性和方法有这些。
然后在哪里用到了呢。在 src/core/index.js中导入了Vue的出生文件。看Vue源码学习三 ———— Vue构造函数包装
Vue源码学习二 ———— Vue原型对象包装的更多相关文章
- Vue源码学习1——Vue构造函数
Vue源码学习1--Vue构造函数 这是我第一次正式阅读大型框架源码,刚开始的时候完全不知道该如何入手.Vue源码clone下来之后这么多文件夹,Vue的这么多方法和概念都在哪,完全没有头绪.现在也只 ...
- Vue源码学习三 ———— Vue构造函数包装
Vue源码学习二 是对Vue的原型对象的包装,最后从Vue的出生文件导出了 Vue这个构造函数 来到 src/core/index.js 代码是: import Vue from './instanc ...
- Vue源码分析(二) : Vue实例挂载
Vue源码分析(二) : Vue实例挂载 author: @TiffanysBear 实例挂载主要是 $mount 方法的实现,在 src/platforms/web/entry-runtime-wi ...
- vue 源码学习二 实例初始化和挂载过程
vue 入口 从vue的构建过程可以知道,web环境下,入口文件在 src/platforms/web/entry-runtime-with-compiler.js(以Runtime + Compil ...
- vue 源码学习三 vue中如何生成虚拟DOM
vm._render 生成虚拟dom 我们知道在挂载过程中, $mount 会调用 vm._update和vm._render 方法,vm._updata是负责把VNode渲染成真正的DOM,vm._ ...
- Vue源码学习一 ———— Vue项目目录
Vue 目录结构 可以在 github 上通过这款 Chrome 插件 octotree 查看Vue的文件目录.也可以克隆到本地.. Vue 是如何规划目录的 scripts ------------ ...
- Vue源码学习(二)$mount() 后的做的事(1)
Vue实例初始化完成后,启动加载($mount)模块数据. (一)Vue$3.protype.$mount 标红的函数 compileToFunctions 过于复杂,主要是生 ...
- 手牵手,从零学习Vue源码 系列二(变化侦测篇)
系列文章: 手牵手,从零学习Vue源码 系列一(前言-目录篇) 手牵手,从零学习Vue源码 系列二(变化侦测篇) 陆续更新中... 预计八月中旬更新完毕. 1 概述 Vue最大的特点之一就是数据驱动视 ...
- 【Vue源码学习】依赖收集
前面我们学习了vue的响应式原理,我们知道了vue2底层是通过Object.defineProperty来实现数据响应式的,但是单有这个还不够,我们在data中定义的数据可能没有用于模版渲染,修改这些 ...
随机推荐
- 阿里maven镜像配置
setting.xml<mirrors> <mirror> <id>alimaven</id> <name>aliyun maven< ...
- Luogu P2391 白雪皑皑 && BZOJ 2054: 疯狂的馒头 并查集
4月的时候在luogu上做过 白雪皑皑 这道题,当时一遍AC可高兴了qwq,后来去了个厕所,路上忽然发现自己的做法是错的qwq...然后就咕咕了qwq 今天看到了 疯狂的馒头 ,发现一毛一样OvO.. ...
- P2746 [USACO5.3]校园网Network of Schools
传送门 把所有学校的关系构成一个图,显然一个强联通分量的所有学校只要有一个有新软件,其他学校也都会有 考虑缩点,发现入度为 0 的块一定要给,因为没有其他人给它 入度不为 0 的块一定有其他人给,我们 ...
- FileChannel与ByteBuffer的使用示例
DirectByteBuffer直接内存的使用场景和作用 生命周期长的大对象, 减少java堆GC, 减少内存copy http://www.importnew.com/26334.html publ ...
- 16-----client、offset、scroll 系列
1.client 代码如下: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> ...
- Lecture--9 Sorting
1/排序算法:冒泡排序bubble sort,插入排序 insertion sort,选择排序 selection sort,快速排序 quick sort,归并排序 merge sort;堆排序 h ...
- Sqoop概述
sqoop Sqoop 是传统数据库与 Hadoop 之间数据同步的工具,它是 Hadoop 发展到一定程度的必然产物,它主要解决的是传统数据库和Hadoop之间数据的迁移问题.这节课我们将详细介绍 ...
- AssetDatabase的方法总结
AssetDatabase的方法总结 1.AssetDatabase.FindAssets public static string[] FindAssets(string filter);publi ...
- java中过滤器、监听器、拦截器的区别
1.过滤器:所谓过滤器顾名思义是用来过滤的,在java web中,你传入的request,response提前过滤掉一些信息,或者提前设置一些参数,然后再传入servlet或者struts的actio ...
- Ashx增删改查_动软
1.首先展示列表 ashx 讲究的是个替换 这些就是属于ashx麻烦的地方 public void ProcessRequest(HttpContext context) { context.Resp ...