preface
When answering the interviewer asked the QUESTION of Vue, we in addition to the scripted answer, actually can also show according to a small amount of source code, to reflect your depth of understanding of Vue.
This article will be updated in succession. This time, it covers the following issues:
- “What does new Vue() do?”
- “At what stage can I access the DOM?”
- “Talk about your understanding of the Vue lifecycle.”
- Extension: What is the new lifecycle hook serverPrefetch?
- “How many vue-router routing modes are there?”
- “Tell me what you know about Keep-alive?”
- “Understand The new Vue2.6+ global API: Vue.Observable ()?”
1.”new Vue()
Do what?”
The new keyword represent instantiate an object, the Vue is actually a class, source location is/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)
}
Copy the code
Then we jump back to this._init(), which is ue.prototype._init, with a series of init* methods inside the _init() method in SRC \core\instance\init.js
Vue.prototype._init = function(options? : Object) { const vm: Component = this // ... Ignore, from line 45if(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') / /... ignoreif (vm.$options.el) {
vm.$mount(vm.$options.el)
}
}
}
Copy the code
1.1 Here we summarize:
initProxy
, a scoping agent that intercepts data within a component that accesses other components.initLifecycle
, and add some properties and lifecycle identifications to the current instance. Such as:$children
,$refs
,_isMounted
And so on.initEvents
Which is used to store the division@hook: Lifecycle hook name =" Bound function"
Event object. Such as:$on
,$emit
And so on.initRender
For initialization$slots
,$attrs
,$listeners
initInjections
Initialization,inject
, which is generally used for deeper component communication and is equivalent to an enhanced versionprops
. Used for component library development.
As long as the provide is declared at the upper level, the next level no matter how deep the inject can visit the provide data. This also has obvious drawbacks: it can be accessed at any level, making it difficult to track the data, not knowing which level declares it or which level or levels are used.
initState
Is a summary of many option initializations, including:Props, methods, Data, computed, and Watch
And so on.initProvide
Initialization,provide
.vm.$mount
To mount the instance.
2. “At what stage can I access the DOM?”
This answer can be started from the timing of beforeCreate and created. Let’s simplify the code according to the above overview:
callHook(vm, 'beforeCreate'// initialize props, methods, data, computed, and watch // provide callHook(VM,'created') // Mount the instance VM.$mount(vm.$options.el)
Copy the code
So when an interviewer asks you,
beforeCreate
As well ascreated
What data is available or not when called?- At what stage can I access the DOM?
- why
created
Then mount the instance?
You know how to answer that.
3. “Talk about your understanding of Vue’s life cycle”
I’m going to skip the usual answer here and go a little deeper:
created/mounted/updated/destroyed
, and the correspondingbefore
Hook. If create => Mount => Update => Destroy.Vue
One is defined in the source codemergeHook
Function to iterate over a constant arrayLIFECYCLE_HOOKS
, which is actually an array of strings with the same name as the lifecycle hook.
Var LIFECYCLE_HOOKS = ['beforeCreate'.'created'.'beforeMount'.'mounted'.'beforeUpdate'.'updated'.'beforeDestroy'.'destroyed'.'activated'.'deactivated'.'errorCaptured', / / v2.6 +'serverPrefetch'
];
Copy the code
So you can say that Activated and deactivated (keep-alive enabled/disabled) and errorCaptured (a hook that’s available later in V2.5 for handling errors).
3.1 New Lifecycle hooks:serverPrefetch
What is?
As you can see, serverPrefetch was formerly ssrPrefetch. As the name suggests, this is for SSR. Allows us to “wait” for asynchronous data during rendering. Can be used in any component, not just the routing component.
<! -- Item.vue --> <template> <div v-if="item">{{ item.title }}</div> <div v-else>... </div> </template> <script>export default {
computed: {
item () {
return this.$store.state.items[this.$route.params.id]
}
},
serverPrefetch () {
return this.fetchItem()
},
mounted () {
if(! this.item) { this.fetchItem() } }, methods: {fetchItem () {
// return the Promise from the action
return this.$store.dispatch('fetchItem', this.$route.params.id)
}
}
}
</script>
Copy the code
- Most interviewers don’t pay much attention to code records and changes since V2.6 +. Here if you say this
v2.6.10
Change, tut… The interviewer will appreciate you more.
3.2 Merge policy for lifecycle hooks
Take callHook(VM, ‘created’) as an example, first determine whether there is a lifecycle hook with the corresponding name in the component option, and then determine whether there is a parentVal(VM). If parentVal(VM) exists and both have lifecycle hooks, they are concat into an array (parentval.concat (childVal)). So, lifecycle hooks can actually be written as arrays. Such as:
created: [
function () {
console.log('first')},function () {
console.log('second')},function () {
console.log('third')}]Copy the code
The hook functions are executed in sequence.
4. “How many vue-router routing modes are there?
Three “hash” | | “history”, “the abstract” the average person only know two “hash” | “history”.
Here’s the source code:
switch (mode) {
case 'history':
this.history = new HTML5History(this, options.base)
break
case 'hash':
this.history = new HashHistory(this, options.base, this.fallback)
break
case 'abstract':
this.history = new AbstractHistory(this, options.base)
break
default:
if(process.env.NODE_ENV ! = ='production') {
assert(false, `invalid mode: ${mode}`)}}Copy the code
# mode
Type: string
Default value: “hash” (the browser environment) | “the abstract” (Node. Js environment)
Optional value: “hash” | | “history” “the abstract” configuring the routing mode:
hash
Use:URL hash
Value for routing. Support for all browsers, including unsupportedHTML5 History Api
The browser.history
: rely onHTML5 History
API and server configuration. To viewHTML5 History
Mode.abstract
: Supports allJavaScript
Running environment, such asNode.js
Server side. If you find no browserAPI
, the route is automatically forced into this mode.
5. “Talk about your rightkeep-alive
Of?”
Here’s a general answer:
Keep-alive is a component built into Vue that allows included components to retain state or avoid rerendering. Since vue 2.1.0, keep-alive has added two new properties: include(the included component is cached) and exclude(the excluded component is not cached and has a higher priority than include).
Then you can start flirting:
<keep-alive>
isVue
Source code in the implementation of a global abstract component, through the customizationrender
Function and takes advantage of slots for data caching and updating. It’s defined insrc/core/components/keep-alive.js
In:
export default {
name: 'keep-alive',
abstract: true. }Copy the code
- All abstract components are by definition
abstract
Option. Abstract components do not render realityDOM
And does not appear on the path of the parent-child relationship (initLifecycle
Will ignore the abstract component), relevant code snippets:
if(parent && ! Options. Abstract) {// mask. Abstract '//whileLoop through the first non-abstract parent componentwhile (parent.$options.abstract && parent.$parent) {
parent = parent.$parent
}
parent.$children.push(vm)
}
Copy the code
6. “understandingVue2.6 +
The new globalAPI
:Vue.observable()
?”
The new global API for Vue2.6+ is vue.Observable (), which works like this:
import vue from vue;
const state = Vue.observable ({
counter: 0,
});
export default {
render () {
return( <div> {state.counter} <button v-on:click={() => {state.counter ++; }}> Increment counter </ button> </ div> ); }};Copy the code
It is defined in line 48 of/SRC /core/global-api/index.js:
import { observe } from 'core/observer/index'/ /... // 2.6 Explicit Observable API Vue.Observable = <T>(obj: T): T => {observe(obj)return obj
}
Copy the code
Look at the observe import. The last commit was on 12/1/2018. HMM…
The core is to exposeobserve(obj)
The code didn’t change anything after the observation. Got it?
Ask for a push in Shenzhen
At present, I am preparing for job-hopping. I hope that you and HR sister can promote a reliable front-end position in Shenzhen!
- WeChat:
huab119
- Email address:
[email protected]
A collection of the author’s nuggets
- Why do you never understand JavaScript scope chains?
- “Vue Practice” project to upgrade vue-CLI3 correct posture
- “Learn from source code” thoroughly understand the Vue option Props
- “Learn from the source code” Vue source code in JS SAO operation
- “Learn from source code” answers to Vue questions that interviewers don’t know