初步读完vue(v2.6.10)
的源码,现将读后感记录以下,故事就是由此开始。vue
小提示:配合源码食用更佳美味。node
开始的开始,vue就是一个简单的函数。web
src/core/instance/index.js设计模式
function Vue (options) {
this._init(options)
}
复制代码
设计模式之混入模式,对Vue进行扩展,很值得学习的一种方式。api
定义了_init方法,是入口函数,在new Vue()时第一时间执行的方法。缓存
src/core/instance/init.jsbash
Vue.prototype._init = function (options?: Object){}
复制代码
数据相关的扩展。dom
src/core/instance/state.js函数
Vue
实例观察的数据对象和当前组件接收到的props
对象。 其实是代理到_data
和_props
工具
Object.defineProperty(Vue.prototype, '$data', {
get(){
return this._data
}
})
Object.defineProperty(Vue.prototype, '$props', {
get(){
return this._props
}
})
复制代码
是 Vue.set
和Vue.delete
的别名
Vue.prototype.$set = set
Vue.prototype.$delete = del
复制代码
实现了$watch
方法,观察Vue
实例变化的一个表达式或计算属性函数。
Vue.prototype.$watch = function () {}
复制代码
事件相关的扩展
src/core/instance/events.js
监听当前实例上的自定义事件。
Vue.prototype.$on = function (event: string | Array<string>, fn: Function): Component{}
复制代码
监听一个自定义事件,可是只触发一次。一旦触发以后,监听器就会被移除。
Vue.prototype.$once = function (event: string, fn: Function): Component{}
复制代码
移除自定义事件监听器。
Vue.prototype.$off = function (event?: string | Array<string>, fn?: Function): Component{}
复制代码
触发当前实例上的事件。
Vue.prototype.$emit = function (event: string): Component {}
复制代码
生命周期相关的扩展
src/core/instance/lifecycle.js
私有方法,更新dom节点流程的重要函数
Vue.prototype._update = function (vnode: VNode, hydrating?: boolean) {}
复制代码
迫使 Vue 实例从新渲染。简单粗暴
Vue.prototype.$forceUpdate = function (){ // 触发更新}
复制代码
彻底销毁一个实例。
Vue.prototype.$destroy = function (){ // 移除事件 指令等 }
复制代码
render相关的扩展
src/core/instance/render.js
定义render函数有关的方法,在执行render时使用
src/core/instance/render-helpers/index.js
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
target._d = bindDynamicKeys
target._p = prependModifier
}
复制代码
将回调延迟到下次 DOM 更新循环以后执行。跟Vue.nextTick
同样,可是绑定了实例的this
Vue.prototype.$nextTick = function (fn: Function) {
return nextTick(fn, this)
}
复制代码
私有方法,建立vnode流程的重要函数
Vue.prototype._render = function (): VNode{}
复制代码
src/core/index.js
全局api
src/core/global-api/index.js
vue 全局配置 代理到vue的config,在new Vue()以前能够修改
全局配置 src/core/config.js
import config from '../config'
Object.defineProperty(Vue, 'config', {
get() {
return config
}
})
复制代码
vue的工具函数
Vue.util = {
warn,
extend,
mergeOptions,
defineReactive
}
复制代码
Vue.set = set // 向响应式对象中添加一个属性
Vue.delete = del // 删除对象的属性。
Vue.nextTick = nextTick // 在下次 DOM 更新循环结束以后执行延迟回调。
复制代码
让一个对象可响应。
Vue.observable = <T>(obj: T): T => {
observe(obj)
return obj
}
复制代码
默认的options
Vue.options = Object.create(null)
复制代码
组件、指令、过滤器实际上就是在options中建立了三个属性。
ASSET_TYPES.forEach(type => {
Vue.options[type + 's'] = Object.create(null)
})
// Vue.options.components
// Vue.options.directives
// Vue.options.filters
复制代码
私有属性,缓存Vue
Vue.options._base = Vue
复制代码
定义了内部组件KeepAlive
extend(Vue.options.components, builtInComponents)
复制代码
定义了Vue.use方法, 安装 Vue.js 插件。
src/core/global-api/use.js
Vue.use = function (plugin: Function | Object) {}
复制代码
定义了Vue.mixin方法, 全局注册一个混入
src/core/global-api/mixin.js
Vue.mixin = function (mixin: Object) {}
复制代码
定义了Vue.extend方法, Vue 构造器,建立一个“子类”。
src/core/global-api/extend.js
Vue.extend = function (extendOptions: Object): Function
复制代码
用于实现组件、指令、过滤器方法
Vue.directive 注册或获取全局指令。
Vue.filter 注册或获取全局过滤器。
Vue.component 注册或获取全局组件。
src/core/global-api/assets.js
ASSET_TYPES.forEach(type => {
Vue[type] = function (
id: string,
definition: Function | Object
): Function | Object | void {
if (!definition) {
return this.options[type + 's'][id]
} else {
if (type === 'component' && isPlainObject(definition)) {
definition.name = definition.name || id
definition = this.options._base.extend(definition)
}
if (type === 'directive' && typeof definition === 'function') {
definition = { bind: definition, update: definition }
}
this.options[type + 's'][id] = definition
return definition
}
}
})
复制代码
版本号
Vue.version = '__VERSION__'
复制代码
再次之上是vue的核心代码,与平台无关。如下是web平台有关代码。 咱们一般用cli
写的代码是不须要编译器的,由于vue-loader有一个编译过程,这个版本一般较小,可是不带编译器。
仅运行时的版本
src/platforms/web/entry-runtime.js
实际上就是src/platforms/web/runtime/index.js
Vue.config.mustUseProp = mustUseProp
Vue.config.isReservedTag = isReservedTag
Vue.config.isReservedAttr = isReservedAttr
Vue.config.getTagNamespace = getTagNamespace
Vue.config.isUnknownElement = isUnknownElement
复制代码
平台相关 定义内部指令v-model
和v-show
extend(Vue.options.directives, platformDirectives)
复制代码
平台相关 定义内部组件Transition
和TransitionGroup
,上面提到过平台无关的内部组件KeepAlive
extend(Vue.options.components, platformComponents)
复制代码
打补丁方法,平台不同打补丁的方法也不同,设计很巧妙。
Vue.prototype.__patch__ = inBrowser ? patch : noop
复制代码
若是 Vue 实例在实例化时没有收到 el 选项,则它处于“未挂载”状态,没有关联的 DOM 元素。可使用 vm.$mount()
手动地挂载一个未挂载的实例。
最后执行了实际上是src/core/instance/lifecycle.js
中的mountComponent
方法。也就是对mountComponent
的一次封装
Vue.prototype.$mount = function (
el?: string | Element,
hydrating?: boolean
): Component {
el = el && inBrowser ? query(el) : undefined
return mountComponent(this, el, hydrating)
}
复制代码
这个版本比较大,由于带有编译器。
src/platforms/web/entry-runtime-with-compiler.js
const mount = Vue.prototype.$mount
Vue.prototype.$mount = function (
el?: string | Element,
hydrating?: boolean
): Component {
el = el && query(el)
const options = this.$options
// 其实所谓的编译就是讲模板编译成render函数
// 存在render将直接使用render函数,则不须要编译
// 不存在render则读取template template有害几种配置方法也是在此到处理
if (template) {
const { render, staticRenderFns } = compileToFunctions(template, {
outputSourceRange: process.env.NODE_ENV !== 'production',
shouldDecodeNewlines,
shouldDecodeNewlinesForHref,
delimiters: options.delimiters,
comments: options.comments
}, this)
options.render = render
options.staticRenderFns = staticRenderFns
}
// 实际仍是调用了$mount
return mount.call(this, el, hydrating)
}
复制代码
在 render 函数中编译模板字符串 编译器版本特有。
Vue.compile = compileToFunctions
复制代码
感谢各位的阅读,错误是在所不免的,如有错误,或者有更好的理解,请在评论区留言,再次感谢。但愿你们相互学习,共同进步。