This is the sixth day of my participation in Gwen Challenge
beforeCreated
Before initializing the bounds
export function initMixin (Vue: Class<Component>) {
Vue.prototype._init = function (options? :Object) {
const vm: Component = this. Set unique uid of Vue element, set _isVue of Vue object to avoid being observed... Parameter merge... Initialize thethisThe._renderProxy property, _self points to itselfthis
initLifecycle(vm) // Initialize some parameters
initEvents(vm) // Initialize the event
initRender(vm) // Initialize the render function
callHook(vm, 'beforeCreate')}}Copy the code
initLifecycle
The implementation of the
export function initLifecycle (vm: Component) {
const options = vm.$options
let parent = options.parent
// Find the parent node and associate the current element with the parent node
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
}
Copy the code
initLifecycle
The main is to initialize some parameters, mainly for the currentvue
The object’sparent
The element is bound and has been set$root
The properties of the
initEvents
The implementation of the
export function initEvents (vm: Component) {
vm._events = Object.create(null)
vm._hasHookEvent = false
const listeners = vm.$options._parentListeners
if (listeners) {
updateComponentListeners(vm, listeners) // Update the component's time monitor}}Copy the code
-
export function updateComponentListeners ( vm: Component, listeners: Object, oldListeners: ?Object ) { target = vm updateListeners(listeners, oldListeners || {}, add, remove, createOnceHandler, vm) // Update the listener target = undefined } Copy the code
-
Effect: Updates the component’s event listener
initRender
The implementation of the
export function initRender (vm: Component) {
vm._vnode = null
vm._staticTrees = null
const options = vm.$options
const parentVnode = vm.$vnode = options._parentVnode
const renderContext = parentVnode && parentVnode.context
vm.$slots = resolveSlots(options._renderChildren, renderContext)
vm.$scopedSlots = emptyObject
// Set the corresponding methods for the _c attribute and the $createElement attribute
vm._c = (a, b, c, d) = > createElement(vm, a, b, c, d, false)
vm.$createElement = (a, b, c, d) = > createElement(vm, a, b, c, d, true)
const parentData = parentVnode && parentVnode.data
// Add a responsive object to the VM object and verify the prompt
if(process.env.NODE_ENV ! = ='production') {
defineReactive(vm, '$attrs', parentData && parentData.attrs || emptyObject, () = > {
!isUpdatingChildComponent && warn(`$attrs is readonly.`, vm)
}, true)
defineReactive(vm, '$listeners', options._parentListeners || emptyObject, () = > {
!isUpdatingChildComponent && warn(`$listeners is readonly.`, vm)
}, true)}else {
defineReactive(vm, '$attrs', parentData && parentData.attrs || emptyObject, null.true)
defineReactive(vm, '$listeners', options._parentListeners || emptyObject, null.true)}}Copy the code
To sum up: inbeforeCreated
The previous initialization was mainly for some parameters, so data and this in options were not bound at this time
created
The data is already bound to this
initInjections(vm)
initState(vm)
initProvide(vm)
callHook(vm, 'created')
Copy the code
-
initInjections
The implementation of the-
export function initInjections (vm: Component) { const result = resolveInject(vm.$options.inject, vm) // Decompose the inject object if (result) { toggleObserving(false) Object.keys(result).forEach(key= > { if(process.env.NODE_ENV ! = ='production') { defineReactive(vm, key, result[key], () = > { warn( `Avoid mutating an injected value directly since the changes will be ` + `overwritten whenever the provided component re-renders. ` + `injection being mutated: "${key}"`, vm ) }) } else { defineReactive(vm, key, result[key]) } }) toggleObserving(true)}}Copy the code
- The loop will decompose
inject
Bound to thethis
On instance objects
- The loop will decompose
-
export function resolveInject (inject: any, vm: Component): ?Object { if (inject) { const result = Object.create(null) const keys = hasSymbol ? Reflect.ownKeys(inject) : Object.keys(inject) for (let i = 0; i < keys.length; i++) { const key = keys[i] if (key === '__ob__') continue const provideKey = inject[key].from // What is the private key used for? let source = vm // This _provided provides a function while (source) { if (source._provided && hasOwn(source._provided, provideKey)) { result[key] = source._provided[provideKey] break } source = source.$parent } if(! source) {if ('default' in inject[key]) { const provideDefault = inject[key].default result[key] = typeof provideDefault === 'function' ? provideDefault.call(vm) : provideDefault } else if(process.env.NODE_ENV ! = ='production') { warn(`Injection "${key}" not found`, vm) } } } return result } } Copy the code
- This function is basically a decomposition
inject
Object, specific intermediate content needs to be sorted out later
- This function is basically a decomposition
-
-
initState
The implementation of the-
export function initState (vm: Component) { vm._watchers = [] const opts = vm.$options if (opts.props) initProps(vm, opts.props) if (opts.methods) initMethods(vm, opts.methods) if (opts.data) { initData(vm) } else { observe(vm._data = {}, true /* asRootData */)}if (opts.computed) initComputed(vm, opts.computed) if(opts.watch && opts.watch ! == nativeWatch) { initWatch(vm, opts.watch) } }Copy the code
$options
Parameters of theprops
|methods
|data
|computed
|initWatch
Property to directly sum the data in these objectsthis
Instance object for binding
-
function initProps (vm: Component, propsOptions: Object) {...for (const key in propsOptions) { const value = validateProp(key, propsOptions, propsData, vm) // Gets the value of the specified format if(process.env.NODE_ENV ! = ='production') {... Format the key and validate it// Set the keys in props to be listened to defineReactive(props, key, value, () = > { if(! isRoot && ! isUpdatingChildComponent) { warn(`Avoid mutating a prop directly since the value will be ` + `overwritten whenever the parent component re-renders. ` + `Instead, use a data or computed property based on the prop's ` + `value. Prop being mutated: "${key}"`, vm ) } }) } else { defineReactive(props, key, value) } if(! (keyin vm)) { proxy(vm, `_props`, key) } } toggleObserving(true)}Copy the code
-
function initMethods (vm: Component, methods: Object) { const props = vm.$options.props for (const key inmethods) { .... [key] = and verify the vmtypeofmethods[key] ! = ='function' ? noop : bind(methods[key], vm) // Bind the method to this instance object}}Copy the code
-
function initData (vm: Component) { let data = vm.$options.data const keys = Object.keys(data) ... Verify the data in data to check whether it has been registered in other methods/props. If it has been registered, a message is displayed indicating that the data in data is registeredthis. _data while forming [key] observe (data,true /* asRootData */) // Observe the data in data } Copy the code
-
function initComputed (vm: Component, computed: Object) { const watchers = vm._computedWatchers = Object.create(null) const isSSR = isServerRendering() //TODO:Determine if it was rendered by the service for (const key in computed) { const userDef = computed[key] const getter = typeof userDef === 'function'? userDef : userDef.get ... Check the}if(! isSSR) {// Create a listener for computed watchers[key] = new Watcher( vm, getter || noop, noop, computedWatcherOptions //{ lazy: true })}if(! (keyin vm)) { // Directly bind attributes in computed to this object defineComputed(vm, key, userDef) // Add a property for a computed key to the vUE instance object to listen for set and GET events}... Verify with other attributes to see if the name is duplicated}}Copy the code
- Loop fetch first
computed
The custom execution function in, and then listens for each property setting - And then each
computed
Property bound tothis
On instance objects
- Loop fetch first
-
function initWatch (vm: Component, watch: Object) { for (const key in watch) { const handler = watch[key] if (Array.isArray(handler)) { for (let i = 0; i < handler.length; i++) { createWatcher(vm, key, handler[i]) // Generate a listener}}else { createWatcher(vm, key, handler)// Call the $watch method to implement the function to listen on the element}}}function createWatcher ( vm: Component, expOrFn: string | Function, handler: any, options? :Object ) { if (isPlainObject(handler)) { options = handler handler = handler.handler } if (typeof handler === 'string') { handler = vm[handler] } return vm.$watch(expOrFn, handler, options) } Copy the code
-
To sum up: foroptions
Properties in thethis
Instance object, and reactive processing is set for the properties