摘要:上一篇文章我们写到从入口文件一步步找到的构造函数,现在我们要去看看实例化经历的过程的构造函数我们知道的构造函数在中不明白的可以去看上一篇文章源码学习笔记一。
上一篇文章我们写到从入口文件一步步找到Vue的构造函数,现在我们要去看看Vue实例化经历的过程Vue的构造函数
我们知道Vue的构造函数在src/core/instance/index.js中,不明白的可以去看上一篇文章 Vue源码学习笔记一。那我们关注一下Vue的构造函数的内容:
// src/core/instance/index.js import { initMixin } from "./init" // Vue的构造函数 function Vue (options) { //... 验证环境 this._init(options) } // 在Vue原型上绑定实例方法 initMixin(Vue) // init stateMixin(Vue) // $set $delete $watch eventsMixin(Vue) // $on $once $off $emit lifecycleMixin(Vue) // _update $forceUpdate $destroy renderMixin(Vue) // $nextTick _render添加Vue属性和方法
这边我们可以看到Vue的构造函数中执行了init方法,从下方得知init是在srccoreinstanceinit.js中导出的initMixin函数中定义的
initMixinvm即this ,同时为实例添加一个唯一的uid, vm._isVue = true 监听对象变化时用于过滤vm,因为Vue的实例是不需要监听变化的。
// src/core/instance/init.js Vue.prototype._init = function (options?: Object) { const vm: Component = this // 当前实例添加了一个唯一的uid vm._uid = uid++ // ... // 监听对象变化时用于过滤vm vm._isVue = true //... }
参数处理,根据我们的小栗子,我们的options处理直接进入了else,然后对参数进行合并,这里是对vue extend的参数需要进行合并处理,我们这里resolveConstructorOptions 返回的即是constructor.options本身
生命周期相关变量初始化 initLifecycle(vm)
// srccoreinstancelifecycle.js // 为组件挂载相应属性,并初始化 vm.$parent = parent vm.$root = parent ? parent.$root : vm vm.$children = [] vm.$refs = {} vm._watcher = null vm._inactive = null vm._directInactive = false vm._isMounted = false vm._isDestroyed = false vm._isBeingDestroyed = false
4.vm 事件监听初始化 initEvents()
// src/core/instance/events.js export function initEvents (vm: Component) { // 创建事件对象,用于存储事件 vm._events = Object.create(null) // 系统事件标识位 vm._hasHookEvent = false // init parent attached events npm // 将父组件模板中注册的事件放到当前组件实例的listeners const listeners = vm.$options._parentListeners if (listeners) { updateComponentListeners(vm, listeners) } }
initEvents(vm) initRender(vm) callHook(vm, "beforeCreate") initInjections(vm) // vm状态初始化,prop/data/computed/method/watch都在这里初始化完成,vue实例create的关键 initState(vm) initProvide(vm) callHook(vm, "created")stateMixin
Vue实例方法--数据,该文件对应的是Vue的数据的处理,首先对$data进行挂载,然后设置数据$set、删除数据$delete、观测数据$watch方法挂载
// stateMixin(Vue) src/core/instance/state.js export function stateMixin (Vue: ClasseventsMixin) { // data const dataDef = {} dataDef.get = function () { return this._data } // prop const propsDef = {} propsDef.get = function () { return this._props } // ... // 定义$data & prop属性 Object.defineProperty(Vue.prototype, "$data", dataDef) Object.defineProperty(Vue.prototype, "$props", propsDef) // 原型链添加函数set 和 delete Vue.prototype.$set = set Vue.prototype.$delete = del // 原型链添加函数$watch Vue.prototype.$watch = function (){ // ... } }
Vue实例方法--事件,该文件主要挂载Vue实例方法的事件,监听事件on once、移除事件off、触发事件emit的挂载
// eventsMixin(Vue) src/core/instance/events.js export function eventsMixin (Vue: ClasslifecycleMixin) { Vue.prototype.$on = function (event: string, fn: Function): Component { // ... } Vue.prototype.$once = function (event: string, fn: Function): Component { // ... } Vue.prototype.$off = function (event?: string, fn?: Function): Component { // ... } Vue.prototype.$emit = function (event: string): Component { // ... } }
Vue实例方法--生命周期,,该文件主要挂载Vue实例方法中的生命周期方法,重新渲染$forceUpdate()、销毁实例$destroy()
// lifecycleMixin(Vue) src/core/instance/lifecycle.js Vue.prototype._mount = function(){} Vue.prototype._update = function (vnode: VNode, hydrating?: boolean) {} Vue.prototype._updateFromParent = function(){} Vue.prototype.$forceUpdate = function () {} Vue.prototype.$destroy = function () {}renderMixin
文件主要挂载Vue实例方法中的dom更新回调$nextTick及一些其他的render函数,后续我们再的深挖一下
// renderMixin(Vue) src/core/instance/render.js Vue.prototype.$nextTick = function (fn: Function) {} Vue.prototype._render = function (): VNode {} Vue.prototype._s = _toString Vue.prototype._v = createTextVNode Vue.prototype._n = toNumber Vue.prototype._e = createEmptyVNode Vue.prototype._q = looseEqual Vue.prototype._i = looseIndexOf Vue.prototype._m = function(){} Vue.prototype._o = function(){} Vue.prototype._f = function resolveFilter (id) {} Vue.prototype._l = function(){} Vue.prototype._t = function(){} Vue.prototype._b = function(){} Vue.prototype._k = function(){}全局API
上面部分,我们对Vue的构造函数,在src/core/instance/index.js文件中的作用进行了大体的了解,当然这并没有结束,依据我们Vue源码学习笔记一中提到的,我们追溯到上一级src/core/index.js
// src/core/index.js import Vue from "./instance/index" import { initGlobalAPI } from "./global-api/index" import { isServerRendering } from "core/util/env" import { FunctionalRenderContext } from "core/vdom/create-functional-component" // 初始化全局变量 initGlobalAPI(Vue) // 为vue原型定义属性 isServer 判断是否为服务端渲染 Object.defineProperty(Vue.prototype, "$isServer", { get: isServerRendering }) // 为vue原型定义属性 ssrContext Object.defineProperty(Vue.prototype, "$ssrContext", { get () { /* istanbul ignore next */ return this.$vnode && this.$vnode.ssrContext } }) Object.defineProperty(Vue, "FunctionalRenderContext", { value: FunctionalRenderContext }) Vue.version = "__VERSION__" export default VueinitGlobalAPI(Vue)
在Vue 构造函数上挂载静态属性和方法即全局API
// src/core/global-api/index.js export function initGlobalAPI(Vue: GlobalAPI) { const configDef = {} configDef.get = () => config // ... Object.defineProperty(Vue, "config", configDef) Vue.util = { // Vue.util warn, extend, mergeOptions, defineReactive } Vue.set = set Vue.delete = del Vue.nextTick = nextTick Vue.options = Object.create(null) ASSET_TYPES.forEach(type => { Vue.options[type + "s"] = Object.create(null) }) Vue.options._base = Vue extend(Vue.options.components, builtInComponents) initUse(Vue) // Vue.use initMixin(Vue) // Vue.mixin initExtend(Vue) // Vue.extend initAssetRegisters(Vue) // Vue.component Vue.directive Vue.filter }内置组件&命令
在追溯到上一级,在文件src/platforms/web/runtime/index.js,该文件注册了一些 Vue内置的组件:包裹动态组件KeepAlive、元素过渡效果Transition、多个元素过渡TransitionGroup
// src/platforms/web/runtime/index.js 执行后 // 安装平台特定的utils Vue.config.isUnknownElement = isUnknownElement Vue.config.isReservedTag = isReservedTag Vue.config.getTagNamespace = getTagNamespace Vue.config.mustUseProp = mustUseProp // 安装平台特定的 指令 和 组件 Vue.options = { components: { KeepAlive, Transition, TransitionGroup }, directives: { model, show }, filters: {}, _base: Vue } Vue.prototype.__patch__ Vue.prototype.$mountcompiler编译器添加
再上一级为src/platforms/web/entry-runtime-with-compiler.js,该文件对原来的Vue.prototype.$mount进行覆盖定义,并且在Vue上挂载了 compile。给Vue的 $mount 方法添加 compiler 编译器,支持 template。
// src/platforms/web/entry-runtime-with-compiler.js const mount = Vue.prototype.$mount // ... Vue.prototype.$mount = function (){ //... 覆盖 Vue.prototype.$mount } // ... //在 Vue 上挂载 compile //compileToFunctions 函数的作用,就是将模板 template 编译为render函数。 Vue.compile = compileToFunctions总结
至此的话我们从宏观上过了一下从我们一层层找到vue到一层层往外看到对Vue的添加属性方法等,我们有了一个整体的概念
src/core/instance/index.js vue的构造函数,添加Vue属性和方法
src/core/index.js 全局API的挂载
src/platforms/web/runtime/index.js 主要是添加web平台特有的配置、组件和指令
web/entry-runtime-with-compiler.js 给Vue的 $mount 方法添加 compiler 编译器,支持 template
scripts/config.js 编译入口文件
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/99898.html
摘要:其中执行命令是我们当前所关注的,对于项目的文件结构,我们需要去找到项目的启动的入口文件,接下来我们去一步一步的找到分析命令是一个模块打包器。 打算开始学习vue的源码开始,我开始 serach 关键词:vue 源码,可是发现很多都不是我想要看到的东西,所以打算记录下来,学习的记录和日后分享。我在想这个文章的名字时,手把手系列?十分钟系列?小白到大佬系列?都不是,只是单纯的学习笔记 文件...
摘要:一个基于全家桶开发的仿知乎日报单页应用项目地址源码地址项目在线地址在线地址模式下推荐使用移动端模式浏览去观看如果觉得做得还不错或者项目源码对您有帮助希望您小抬右手到右上角点一个您的支持是作者长期更新维护的动力项目起源从二月份开始学习学习了 Vue-News 一个基于vue全家桶开发的仿知乎日报单页应用 项目github地址:源码地址 项目在线地址:在线地址 (PC模式下推荐使用chro...
摘要:很多小伙伴练手都会去仿写豆瓣电影或者网易云音乐,所以,这回干脆把两个集合起来,具体长什么样,请各位看预览或下面图片啦。怎么折腾法呢比如豆瓣部分我使用了,网易云部分则没有,网易的组件则是自己造的轮子,当然在实际开发中肯定不会这么搞啦。。 很多小伙伴练手都会去仿写豆瓣电影或者网易云音乐,所以,这回干脆把两个集合起来,具体长什么样,请各位看预览或下面图片啦。 目的: 做这个项目最主要的目的是...
摘要:介一回聊状态模式,官方描述允许一个对象在其内部状态改变时改变它的行为。有限状态机有限状态机是一个非常有用的模型,可以模拟世界上大部分事物。这个是官方说法,简单说,她有三个特征,状态总数是有限的。,任一时刻,只处在一种状态之中。 本回内容介绍 上一回聊了聊组合模式(Composite),用组合模式模拟了个图片库,聊了递归。介一回聊状态模式(State),官方描述允许一个对象在其内部状态改...
写文章不容易,点个赞呗兄弟 专注 Vue 源码分享,文章分为白话版和 源码版,白话版助于理解工作原理,源码版助于了解内部详情,让我们一起学习吧研究基于 Vue版本 【2.5.17】 如果你觉得排版难看,请点击 下面链接 或者 拉到 下面关注公众号也可以吧 【Vue原理】Compile - 源码版 之 Parse 主要流程 本文难度较繁琐,需要耐心观看,如果你对 compile 源码暂时...
阅读 1340·2023-04-25 23:42
阅读 2805·2021-11-19 09:40
阅读 3519·2021-10-19 11:44
阅读 3528·2021-10-14 09:42
阅读 1859·2021-10-13 09:39
阅读 3820·2021-09-22 15:43
阅读 664·2019-08-30 15:54
阅读 1446·2019-08-26 13:32