大家好,欢迎来到IT知识分享网。
前言:接触vue已经有一段时间了,前面也写了几篇关于vue全家桶的内容,感兴趣的小伙伴可以去看看,刚接触的时候就想去膜拜一下源码~可每次鼓起勇气去看vue源码的时候,当看到几万行代码的时候就直接望而却步了,小伙伴是不是也跟我当初一样呢? 下面分享一下我看vue源码的一些感触,然后记录一下我对源码的理解,欢迎指正,纯属个人笔记,大牛勿喷!
我们直接上一张vue官网的vue的生命周期图:
我们跟着源码结合demo把张图全部跑一遍~~
我们以一个webpack+vue单页面引用为demo
首先我们看一下vue源码文件:
我们首先从我们项目的main.js文件开始:
// The Vue build version to load with the `import` command // (runtime-only or standalone) has been set in webpack.base.conf with an alias. import Vue from 'vue' import App from './App' import router from './router' import store from './store' import LazyImage from './lazy' import {sync} from 'vuex-router-sync' Vue.config.productionTip = false Vue.use(LazyImage) sync(store,router) /* eslint-disable no-new */ new Vue({ el: '#app', router, store, ddd: {name: 'yasin'}, render(h) { return h(App) } })
我们已经默默的开始的我们的旅程,目前已经到达了生命周期的(new Vue())
我们点开vue的源码(/node_modules/vue/src/core),找到构造函数:
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) Object.defineProperty(Vue.prototype, '$isServer', { get: isServerRendering }) Object.defineProperty(Vue.prototype, '$ssrContext', { get () { /* istanbul ignore next */ return this.$vnode && this.$vnode.ssrContext } }) // expose FunctionalRenderContext for ssr runtime helper installation Object.defineProperty(Vue, 'FunctionalRenderContext', { value: FunctionalRenderContext }) Vue.version = '__VERSION__' export default 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) { 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) export default Vue
initMixin(Vue)
/node_modules/vue/src/core/instance/init.js
export function initMixin (Vue: Class<Component>) { Vue.prototype._init = function (options?: Object) { const vm: Component = this // a uid vm._uid = uid++ let startTag, endTag /* istanbul ignore if */ if (process.env.NODE_ENV !== 'production' && config.performance && mark) { startTag = `vue-perf-start:${vm._uid}` endTag = `vue-perf-end:${vm._uid}` mark(startTag) } // a flag to avoid this being observed vm._isVue = true // 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 ) } /* istanbul ignore else */ if (process.env.NODE_ENV !== 'production') { initProxy(vm) } else { vm._renderProxy = vm } // expose real self 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') /* istanbul ignore if */ if (process.env.NODE_ENV !== 'production' && config.performance && mark) { vm._name = formatComponentName(vm, false) mark(endTag) measure(`vue ${vm._name} init`, startTag, endTag) } if (vm.$options.el) { vm.$mount(vm.$options.el) } } }
代码已经有点多了,问题不大~ 我们找重点,我们再看一下生命周期图,看一下我们接下来走哪一步了:
可以看到,我们接下来要走init方法中的events跟lifecyle,字面意思就可以知道是注册“事件”跟“生命周期”的意思:
我们在init方法中找到对应的代码:
Vue.prototype._init = function (options?: Object) { .... // expose real self vm._self = vm initLifecycle(vm) initEvents(vm) initRender(vm) callHook(vm, 'beforeCreate') .... }
export function initLifecycle (vm: Component) { const options = vm.$options // locate first non-abstract parent let parent = options.parent if (parent && !options.abstract) { while (parent.$options.abstract && parent.$parent) { parent = parent.$parent } parent.$children.push(vm) } 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 }
export function initEvents (vm: Component) { vm._events = Object.create(null) vm._hasHookEvent = false // init parent attached events const listeners = vm.$options._parentListeners if (listeners) { updateComponentListeners(vm, listeners) } }
events是啥呢? 就是我们执行vm. o n c e 、 v m . once、vm. once、vm.on、vm.$emit方法发送的一些事件,分为注册事件跟触发事件(观察者模式)
initMixin(Vue) stateMixin(Vue) eventsMixin(Vue) lifecycleMixin(Vue) renderMixin(Vue) export default Vue
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 } if (process.env.NODE_ENV !== 'production') { dataDef.set = function (newData: Object) { 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 ( expOrFn: string | Function, cb: any, options?: Object ): Function { const vm: Component = this if (isPlainObject(cb)) { return createWatcher(vm, expOrFn, cb, options) } options = options || {} options.user = true const watcher = new Watcher(vm, expOrFn, cb, options) if (options.immediate) { cb.call(vm, watcher.value) } return function unwatchFn () { watcher.teardown() } } }
我们在vue项目中代码可能会用到 Vue.prototype. s e t 、 V u e . p r o t o t y p e . set、 Vue.prototype. s
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/129620.html