In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-28 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/02 Report--
This article mainly introduces the relevant knowledge of "what is the method of mounting Vue instances". The editor shows you the operation process through the actual case. The operation method is simple, fast and practical. I hope this article "what is the method of mounting Vue instances" can help you solve the problem.
First, thinking
We have all heard the saying that we know what it is and why it is.
So I wonder if you have thought about what new Vue () has done in the process.
How to bind the data in the process, how to render the data to the view, and so on.
2. Analysis
First find the constructor of Vue
Source location: src/core/instance/index.js
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)}
Options is a common method of configuration items passed by users, such as data, methods and so on.
The Vue builder function calls the _ init method, but we find that there is no such method in this file, but you can carefully see that many initialization methods are defined at the bottom of the file.
InitMixin (Vue); / define _ initstateMixin (Vue); / define $set $get $delete $watch and other eventsMixin (Vue); / / define events $on $once $off $emitlifecycleMixin (Vue); / / define _ update $forceUpdate $destroyrenderMixin (Vue); / / define _ render return virtual dom
First, you can see the initMixin method, which defines the _ init method on the Vue prototype.
Source location: src/core/instance/init.js
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 / / merge attributes To determine whether the initialization is a component, here the method 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, which is mainly mixins or extends, is merged. InitInternalComponent (vm, options)} else {/ / merge vue attribute vm.$options = mergeOptions (resolveConstructorOptions (vm.constructor), options | | {} Vm)} / * istanbul ignore else * / if (process.env.NODE_ENV! = = 'production') {/ / initialize proxy interceptor initProxy (vm)} else {vm._renderProxy = vm} / / expose real self vm._self = vm / / initialize component life cycle flag bit initLifecycle (vm) / / early Initialize component event listening initEvents (vm) / / initialize rendering method initRender (vm) callHook (vm) 'beforeCreate') / / initialize dependency injection Before initializing data and props, initInjections (vm) / / resolve injections before data/props / / initializes props/data/method/watch/methods 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)} / / Mount element if (vm.$options.el) {vm.$mount (vm.$options.el)}}
After reading the above code carefully, we come to the following conclusion:
Before calling beforeCreate, data initialization is not completed, and properties such as data and props cannot be accessed
When it comes to created, the data has been initialized and the attributes such as data and props can be accessed, but the mount of dom is not completed at this time, so the dom element cannot be accessed.
The mount method is to call the vm.$mount method
The initState method completes the initialization of props/data/method/watch/methods.
Source location: src/core/instance/state.js
Export function initState (vm: Component) {/ / initialize the watcher list of components vm._watchers = [] const opts = vm.$options / / initialize props if (opts.props) initProps (vm, opts.props) / / initialize methods method if (opts.methods) initMethods (vm, opts.methods) if (opts.data) {/ / initialize 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)}}
Here we mainly see that the method to initialize data is initData, which is on the same file as initState.
Function initData (vm: Component) {let data = vm.$options.data / / get data data = vm._data = typeof data = = 'function'? GetData (data, vm): data | {} if (! isPlainObject (data)) {data = {} process.env.NODE_ENV! = 'production' & & warn (' data functions should return an object:\ n'+ 'https://vuejs.org/v2/guide/components.html#data-Must-Be-a-Function', Vm)} / / proxy data on instance const keys = Object.keys (data) const props = vm.$options.props const methods = vm.$options.methods let I = keys.length while (iMel -) {const key = keys [I] if (process.env.NODE_ENV! = = 'production') {/ / property name cannot repeat if (methods & & hasOwn (methods) Key) {warn (`Method "${key}" has already been defined as a data property.`, vm)}} / / attribute name cannot be duplicated with state name if (props & & hasOwn (props, key)) {process.env.NODE_ENV! = = 'production' & & warn (`The data property "${key}" is already declared as a prop. `+ ``Use prop default value Einstein.`, vm)} else if (! isReserved (key)) {/ / verify the validity of the key value / mount the data in _ data to the component vm, so that you can access the data on the component proxy (vm, `_ data`, key)}} / / observe data / / responsive listening data is the change observe of the data (data True / * asRootData * /)}
If we read the above code carefully, we can draw the following conclusions:
Initialization order: props, methods, data
When defining data, you can choose either function form or object form (components can only be in function form)
With regard to the data response, it is not shown here that the mount method mentioned above is to call the vm.$mount method.
Source code:
Vue.prototype.$mount = function (el?: string | Element Hydrating?: boolean): Component {/ / get or query element el = el & & query (el) / * istanbul ignore if * / / vue is not allowed to mount directly to body or page document if (el = document.body | | el = document.documentElement) {process.env.NODE_ENV! = = 'production' & & warn (`Do not mount Vue to or-mount to normal elements Einstein. `) return this} Const options = this.$options / / resolve template/el and convert to render function if (! options.render) {let template = options.template / / there is a template template Parse the vue template file if (template) {if (typeof template = 'string') {if (template.charAt (0) =' #') {template = idToTemplate (template) / * istanbul ignore if * / if (process.env.NODE_ENV! = = 'production' & &! template) {warn (`Template element not found or is empty: ${options.template} `) This)} else if (template.nodeType) {template = template[ XSS _ clean]} else {if (process.env.NODE_ENV! = = 'production') {warn (' invalid template option:' + template) This)} return this}} else if (el) {/ / get element content template = getOuterHTML (el)} if (template) {/ * istanbul ignore if * / if (process.env.NODE_ENV! = = 'production' & & config.performance & & mark) {mark (' compile')} / * 1. Parse temmplate to ast tree * 2. Convert ast tree to render syntax string * 3. Generate render method * / 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 / * istanbul ignore if * / if (process.env.NODE_ENV! = = 'production' & & config.performance & & mark) {mark (' compile end') measure (`vue ${this._name} Secrete`, 'compile',' compile end')}} return mount.call (this, el, hydrating)}
By reading the above code, we can come to the following conclusions:
Do not put the root element on body or html
You can define template/render in an object or directly use template or el to represent element selector
Eventually, it will be resolved into a render function, and when compileToFunctions is called, the template will be parsed into a render function.
The steps for parsing template are roughly divided into the following steps:
Parse html document fragments into ast descriptors
Parse ast descriptors into strings
Generate render function
The render function is generated. After it is mounted on the vm, the mount method is called again.
Source location: src/platforms/web/runtime/index.js
/ / public mount methodVue.prototype.$mount = function (el?: string | Element, hydrating?: boolean): Component {el = el & & inBrowser? Query (el): undefined / / rendering component return mountComponent (this, el, hydrating)}
Call the mountComponent rendering component
Export function mountComponent (vm: Component, el:? Element, hydrating?: boolean): Component {vm.$el = el / / if you don't get the parsed render function A warning is thrown that / / render is the if (! vm.$options.render) {vm.$options.render = createEmptyVNode if (process.env.NODE_ENV! = = 'production') {/ * istanbul ignore if * / if ((vm.$options.template & & vm.$options.template.charAt (0)! = =' #') generated by parsing the template file | | vm.$options.el | | el) {warn ( 'You are using the runtime-only build of Vue where the template'+ 'compiler is not available. Either pre-compile the templates into'+ 'render functions, or use the compiler-included build.', vm)} else {/ / did not get the template file warn (' Failed to mount component: template or render function not defined.', vm)} / / execute beforeMount hook callHook (vm) 'beforeMount') let updateComponent / * istanbul ignore if * / if (process.env.NODE_ENV! = =' production' & & config.performance & & mark) {updateComponent = () = > {const name = vm._name const id = vm._uid const startTag = `vue-perf-start:$ {id} `const endTag = `vue-perf-end:$ {id} `mark (startTag) const vnode = vm._render () Mark (endTag) measure (`vue ${name} render` StartTag, endTag) mark (startTag) vm._update (vnode, hydrating) mark (endTag) measure (`vue ${name} patch`, startTag, endTag)}} else {/ / define update function updateComponent = () = > {/ / the actual call is _ render vm._update (vm._render () defined in _ update and renderMixin defined in lifeCycleMixin) Hydrating)} / / we set this to vm._watcher inside the watcher's constructor / / since the watcher's initial patch may call $forceUpdate (e.g. Inside child / / component's mounted hook), which relies on vm._watcher being already defined / / listens to the current component status When there are changes in data Update component new Watcher (vm, updateComponent, noop, {before () {if (vm._isMounted & &! vm._isDestroyed) {/ / component update callHook (vm, 'beforeUpdate')}, true / * isRenderWatcher * /) hydrating = false / / manually mounted instance Call mounted on self / / mounted is called for render-created child components in its inserted hook if (vm.$vnode = = null) {vm._isMounted = true callHook (vm, 'mounted')} return vm}
After reading the above code, we come to the following conclusion:
Will trigger the beforeCreate hook.
Define how updateComponent renders the page view
Listens to the component data and triggers the beforeUpdate life hook once it changes
The updateComponent method mainly executes the render, update methods declared during vue initialization
The main function of render is to generate vnode
Source location: src/core/instance/render.js
/ / define the render method Vue.prototype._render = function () on the vue prototype: the VNode {const vm: Component = this / / render function comes from the component's option const {render, _ parentVnode} = vm.$options if (_ parentVnode) {vm.$scopedSlots = normalizeScopedSlots (_ parentVnode.data.scopedSlots, vm.$slots, vm.$scopedSlots)} / / set parent vnode. This allows render functions to have access / / to the data on the placeholder node. Vm.$vnode = _ parentVnode / / render self let vnode try {/ / There's no need to maintain a stack because all render fns are called / / separately from one another. Nested component's render fns are called / / when parent component is patched. CurrentRenderingInstance = vm / / call the render method, its own unique render method, and pass in the createElement parameter Generate vNode vnode = render.call (vm._renderProxy, vm.$createElement)} catch (e) {handleError (e, vm, `render`) / / return error render result / / or previous vnode to prevent render error causing blank component / * istanbul ignore else * / if (process.env.NODE_ENV! = = 'production' & & vm.$options.renderError) {try {vnode = vm.$options.renderError.call (vm._renderProxy, vm.$createElement, e)} catch (e) {handleError (e, vm) `renderError`) vnode = vm._vnode}} else {vnode = vm._vnode}} finally {currentRenderingInstance = null} / / if the returned array contains only a single node Allow it if (Array.isArray (vnode) & & vnode.length = 1) {vnode = vnode [0]} / / return empty vnode in case the render function errored out if (! (vnode instanceof VNode)) {if (process.env.NODE_ENV! = = 'production' & & Array.isArray (vnode)) {warn (' Multiple root nodes returned from render function. Render function'+ 'should return a single root node.', vm)} vnode = createEmptyVNode ()} / / set parent vnode.parent = _ parentVnode return vnode}
The main function of _ update is to call patch, convert vnode to real DOM, and update it to the page.
Source location: src/core/instance/lifecycle.js
Vue.prototype._update = function (vnode: VNode, hydrating?: boolean) {const vm: Component = this const prevEl = vm.$el const prevVnode = vm._vnode / / sets the currently active scope const restoreActiveInstance = setActiveInstance (vm) vm._vnode = vnode / / Vue.prototype.__patch__ is injected in entry points / / based on the rendering backend used. If (! prevVnode) {/ / initial render / / execute specific mount logic vm.$el = vm.__patch__ (vm.$el, vnode, hydrating, false / * removeOnly * /)} else {/ / updates vm.$el = vm.__patch__ (prevVnode) Vnode)} restoreActiveInstance () / / update _ _ vue__ reference if (prevEl) {prevEl.__vue__ = null} if (vm.$el) {vm.$el.__vue__ = vm} / / if parent is an HOC Update its $el as well if (vm.$vnode & & vm.$parent & & vm.$vnode = vm.$parent._vnode) {vm.$parent.$el = vm.$el} / / updated hook is called by the scheduler to ensure that children are / / updated in a parent's updated hook. } III. Conclusion
The _ init method is called when new Vue
Define $set, $get, $delete, $watch, and so on
Define events such as $on, $off, $emit, $off, etc.
Define _ update, $forceUpdate, $destory lifecycle
Call $mount to mount the page
When mounting, it is mainly through mountComponent method
Define updateComponent update function
Execute render to generate virtual DOM
_ update generates the virtual DOM into a real DOM structure and renders it to the page
This is the end of the content about "what is the method of mounting Vue instances". Thank you for your reading. If you want to know more about the industry, you can follow the industry information channel. The editor will update different knowledge points for you every day.
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.