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中定义的数据可能没有用于模版渲染,修改这些 ...
随机推荐
- CentOS7.3下Zabbix3.5之微信报警配置
一.报警脚本放到服务端的 /usr/lib/zabbix/alertscripts/下 属组属主为zabbix zabbix 有执行权限vim weixinbaojing.py # ...
- c# Equals对比忽略大小写
String.Equals(str1,str2,StringComparison.CurrentCultureIgnoreCase); StringComparison.CurrentCultureI ...
- poj 1236 Network of Schools (强连通分量+缩点)
题目大概: 每个学校都可以把软件复制好,交给它名单上的学校. 问题A:把软件复制成几份,然后交给不同的学校,所有学校才能够都有软件. 问题B:添加几条边,能使得这个图变成强连通图. 思路: 找出所有的 ...
- codeforces1016 D. Vasya And The Matrix(思维+神奇构造)
D. Vasya And The Matrix time limit per test 2 seconds memory limit per test 256 megabytes input stan ...
- Restful 4 -- 认证组件、权限组件、频率组件、url注册器、响应器、分页器
一.认证组件.权限组件.频率组件总结: 只有认证通过的用户才能访问指定的url地址,比如:查询课程信息,需要登录之后才能查看,没有登录,就不能查看,这时候需要用到认证组件 1.认证组件格式 写一个认 ...
- eclipse类自动生成注释
1.创建新类时自动生成注释 window->preference->java->code styple->code template 当你选择到这部的时候就会看 ...
- python3 下载 以及 练习1 以及 pycharm 专业版 安装
下载python: https://www.python.org/downloads/release/python-365/ ########sample 1 下载pycharm 社区版本,但是web ...
- man时括号里的数字是啥意思
https://www.cnblogs.com/istarstar/p/7851233.html 具体含义可以man man来查看(自己查自己). MANUAL SECTIONS The standa ...
- 迅雷笔试题 (JAVA多线程)启动三个线程,分别打印A B C,现在写一个程序 循环打印ABCABCABC
题目:http://wenku.baidu.com/view/d66187aad1f34693daef3e8a.html 启动三个线程,分别打印A B C,现在写一个程序 循环打印ABCABCABC. ...
- JS绑定事件和移除事件的处理方法
addEventListener()与removeEventListener()用于处理指定和删除事件处理程序操作.所有的DOM节点中都包含这两种方法,并且它们都接受3个参数:要处理的事件名.作为事件 ...