Отказ от ответственности: аннотация на английском языке является оригинальной работой Великого Бога Ю Юйси, а китайский язык переведен для моего собственного понимания. Уровень ограничен, если есть какие-либо недоразумения, пожалуйста, обратитесь к оригинальной работе, пожалуйста, поправьте меня, пожалуйста, простите меня~
Если вы думаете, что это не плохо, дайте мне звезду, нажмите здесьgithub
Vue Происхождение проекта, на самом деле, связано с VUE создали:
new Vue({
el: ...,
data: ...,
....
})
Так что же именно произошло во время этого экземпляра? Давайте узнаем. Откройте файл исходного кода Vue, и его основной код находится в каталоге src/core. Начнем с входного файла index.js:
// 这个应该是实例化的引入
import Vue from './instance/index'
//这个应该是初始化一些全局API
import { initGlobalAPI } from './global-api/index'
// 这个应该是从判断执行环境中的引入是否是ssr环境,是一个Boolea类型
import { isServerRendering } from 'core/util/env'
// 这个应该是virtualDom编译成renderContext的方法
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
}
})
// 为vue原型定义当为ssr环境运行时去加载FunctionalRenderContext方法
// expose FunctionalRenderContext for ssr runtime helper installation
Object.defineProperty(Vue, 'FunctionalRenderContext', {
value: FunctionalRenderContext
})
Vue.version = '__VERSION__'
// 导出Vue
export default Vue
Далее давайте взглянем на каждый файл загрузки:
import Vue from './instance/index'
Содержание следующее:
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
Здесь класс Vue определяется просто и грубо, а затем для инициализации некоторых функций вызывается ряд методов, таких как init и mixin.Мы проанализируем детали позже, но что мы можем подтвердить с помощью кода: Да! Вот действительно функциональный класс Vue, который экспортируется.
import { initGlobalAPI } from './global-api/index'
initglobalapi Эта вещь, на самом деле,
import config from '../config'
import { initUse } from './use'
import { initMixin } from './mixin'
import { initExtend } from './extend'
import { initAssetRegisters } from './assets'
import { set, del } from '../observer/index'
import { ASSET_TYPES } from 'shared/constants'
import builtInComponents from '../components/index'
import {
warn,
extend,
nextTick,
mergeOptions,
defineReactive
} from '../util/index'
export function initGlobalAPI (Vue: GlobalAPI) {
// config
const configDef = {}
configDef.get = () => config
if (process.env.NODE_ENV !== 'production') {
configDef.set = () => {
warn(
'Do not replace the Vue.config object, set individual fields instead.'
)
}
}
Object.defineProperty(Vue, 'config', configDef)
// 这些工具方法不视作全局API的一部分,除非你已经意识到某些风险,否则不要去依赖他们
// exposed util methods.
// NOTE: these are not considered part of the public API - avoid relying on
// them unless you are aware of the risk.
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)
})
// this is used to identify the "base" constructor to extend all plain-object
// components with in Weex's multi-instance scenarios.
Vue.options._base = Vue
extend(Vue.options.components, builtInComponents)
// 定义全局方法
initUse(Vue)
initMixin(Vue)
initExtend(Vue)
initAssetRegisters(Vue)
}
♦] [VUE.UTIL различные коммунальные функции, есть флаг совместимости (WOW, не судить о себе браузер, Vue был судить хорошо) ♦ [vue.set / delete] Этот документ, который вы должны увидеть
♦[Vue.nextTick] Это оптимизация для слияния и обработки изменений данных перед следующим обновлением.
♦[Vue.options] Эти параметры отличаются от параметров, которые мы использовали для создания экземпляра выше. Это ресурс, предоставляемый Vue по умолчанию (фильтр директивы компонента).
♦[Vue.use] Определяется методом initUse.
♦[Vue.mixin] Определяется методом initMixin.
♦[Vue.extend] Определяется методом initExtend.
import { isServerRendering } from 'core/util/env'
// 这个需要用懒加载在vue渲染前
// this needs to be lazy-evaled because vue may be required before
// ssr使用的时候要把VUE_ENV(vue环境)设置成'server'
// vue-server-renderer can set VUE_ENV
let _isServer
export const isServerRendering = () => {
if (_isServer === undefined) {
/* istanbul ignore if */
if (!inBrowser && !inWeex && typeof global !== 'undefined') {
// detect presence of vue-server-renderer and avoid
// Webpack shimming the process
_isServer = global['process'].env.VUE_ENV === 'server'
} else {
_isServer = false
}
}
return _isServer
}
import { FunctionalRenderContext } from 'core/vdom/create-functional-component'
export function FunctionalRenderContext (
data: VNodeData,
props: Object,
children: ?Array<VNode>,
parent: Component,
Ctor: Class<Component>
) {
const options = Ctor.options
// 确保createElement方法在components方法中
// ensure the createElement function in functional components
// 得到一个唯一的context上下文-主要是为了检查是否有重复命名确保唯一性
// gets a unique context - this is necessary for correct named slot check
let contextVm
if (hasOwn(parent, '_uid')) {
// 表示不存在创建
contextVm = Object.create(parent)
// $flow-disable-line
contextVm._original = parent
} else {
// the context vm passed in is a functional context as well.
// in this case we want to make sure we are able to get a hold to the
// real context instance.
contextVm = parent
// $flow-disable-line
parent = parent._original
}
const isCompiled = isTrue(options._compiled)
const needNormalization = !isCompiled
this.data = data
this.props = props
this.children = children
this.parent = parent
this.listeners = data.on || emptyObject
this.injections = resolveInject(options.inject, parent)
this.slots = () => resolveSlots(children, parent)
// 支持把template编译的方法
// support for compiled functional template
if (isCompiled) {
// exposing $options for renderStatic()
this.$options = options
// pre-resolve slots for renderSlot()
this.$slots = this.slots()
this.$scopedSlots = data.scopedSlots || emptyObject
}
if (options._scopeId) {
this._c = (a, b, c, d) => {
const vnode = createElement(contextVm, a, b, c, d, needNormalization)
if (vnode && !Array.isArray(vnode)) {
vnode.fnScopeId = options._scopeId
vnode.fnContext = parent
}
return vnode
}
} else {
this._c = (a, b, c, d) => createElement(contextVm, a, b, c, d, needNormalization)
}
}
installRenderHelpers(FunctionalRenderContext.prototype)
На данный момент наш входной файл почти ясен.Далее давайте начнем понимать конкретную реализацию класса Vue, в которой мы узнаем о знаниях связанного жизненного цикла Vue.
благодарныйmuwooПредоставленные материалы