Hello everyone, I am Lin Yiyi, this is an interview question about the principle of VUE, if you can understand it completely, I believe it will be very helpful to you.
1. What are the advantages and disadvantages of MPA/SPA?
MPA
Multi-page applications.
- Composition: There are multiple pages
html
Composition, - Jump mode: A page jumps from one page to another
- Refresh method: full page refresh
- Page data jump: dependency
URL/cookie/localStorage
- Resources after the jump
Will reload
- Advantages: More friendly to SEO, low difficulty in development.
SPA
Single page application
- Page composition: consists of multiple page (component) fragments wrapped in a shell page
- Jump mode: Jump to the shell page and show or hide the fragment page (component)
- Refresh mode: Partial refresh of page fragments
- Data skipping on a page: It is easier to transfer values between components
- Resources after the jump
Does not reload
- Disadvantages: SEO search is not too friendly need to do configuration alone, high difficulty of development need a special development framework
Iframe is actually MPA, but it can achieve some effects of SPA, but it has many problems.
2. Cliche: Why do we need these MVC/MVVM patterns? Talk about your differences between MVC and MVVM patterns,
Purpose: Use backend ideas, responsibility division and layering
- Vue and React are not MVVM in the true sense, let alone MVC. Their core only deals with the view layer
view
.
The MVC pattern
One-way data, each step of the user operation needs to re-request the database to modify the rendering of the view layer, forming a one-way closed loop. Such as jQuery + the underscore + backbone.
- M:
model
Data storage layer - V:
view
: View layer page - C:
controller
: Controller JS logical layer.
The controller control layer will process the data of the data layer model layer and display it in the view layer view layer. Similarly, the view layer view layer can also act on the data layer Model through the control layer Controller. So the downside of MVC is that the view layer can’t interact directly with the data layer.
The MVVM pattern
Hide the Controller layer and directly control the View layer and Model data layer.
- M: Model Data model
- V: view View template
- VM: view-model View data template (vUE layer processing, vUE definedProperty is the logic processing VM layer)
Bidirectional Data binding: The Model Data model layer directly influences the View layer View through Data Bindings, and the View layer View can also change the Data model layer model by listening to Dom listeners.
- Data binding and DOM event listening are examples
viewModel
层Vue
The main thing to do. In other words: as long as willData Model layer Model
Data mount toViewModel
层Vue
Two-way data binding can be implemented. - add
vuex/redux
Can be used as aVue and react
的model
The data layer.
var vm = new Vue()
Copy the code
Vm is the VIEW-Model data model layer, and data: is the data represented by the VM View-Model layer.
- To sum up the differences between the two: MVC view layer and data layer interaction needs to go through the control layer
controller
Belong to one-way link. MVVM hides the control layercontroller
So that the view layer and the data layer can interact directly is a two-way connection.
3. Explain your understanding of responsive data in Vue
Tip: Reactive data is when the data changes and the view can be updated
vue
One is implemented indefinedReactive
Method, method internal borrowingObject.definedProperty()
Each attribute is addedget/set
Properties.definedReactive
Only the outermost objects can be monitored, and the inner objects need to be recursively hijacked.- The array is seven rewritten
push pop shift unshift reverse sort splice
To intercept the array, because these methods change the original array - Properties added to or deleted from an object cannot be monitored by set. Only property changes that already exist on the object are hijacked. Or use vUE provided
$set()
Implement listening. - Extension:
// src\core\observer\index.js
export function defineReactive (
obj: Object,
key: string,
val: any,
customSetter?: ?Function, shallow? : boolean) {
// Ready to add a DEP to the property to rely on the collection Watcher to update the view.
const dep = new Dep()
// some code
// Observe () the type of value to observe. Recursively add 'get/set' to each attribute
letchildOb = ! shallow && observe(val)Object.defineProperty(obj, key, {
enumerable: true.configurable: true.get: function reactiveGetter () {
// Collect data
const value = getter ? getter.call(obj) : val
if (Dep.target) {
dep.depend()
// childOb is a collection dependency on objects
if (childOb) {
childOb.dep.depend()
// There is a recursive collection dependency on the array and the inner array, where the array key and value have deP.
if (Array.isArray(value)) {
dependArray(value)
}
}
}
return value
},
set: function reactiveSetter (newVal) {
// When the property changes, watcher is notified to update the view}})}Copy the code
What is the above Dep(class) used for? A: What is a Watcher for collecting renderings? A: Watcher is a class that updates views
4. How does Vue detect array changes?
- Vue is not used for every item in the array
definedProperty()
To intercept data, but by overriding the array methodpush pop shift unshift reverse sort splice
. - Manually call notify to Render Watcher and perform update
- If the array has an object type (
Objects and Arrays
) will conduct data interception. - So there’s no intercepting by changing the array subscript and the array length, so there’s no responsive change. For example,
arr[0] = 1, arr.length = 2
They’re not going to be responsive - Extension:
// src\core\observer\array.js
const methodsToPatch = ['push'.'pop'.'shift'.'unshift'.'splice'.'sort'.'reverse']
methodsToPatch.forEach(function (method) {
const original = arrayProto[method]
def(arrayMethods, method, function mutator (. args) {
const result = original.apply(this, args)
const ob = this.__ob__
let inserted
switch (method) {
case 'push':
case 'unshift':
inserted = args
break
case 'splice':
inserted = args.slice(2)
break
}
// Observe the new type again
if (inserted) ob.observeArray(inserted)
// Manually call notify to send updates
ob.dep.notify()
return result
})
})
Copy the code
5. How does Vue rely on collections? (What is the relationship between DEP and Watcher?)
Dep is a class that collects the Watcher, which is a class that encapsulates the render view logic to distribute updates. It is important to note that Watcher cannot update the view directly, but also requires a combination of Vnode and the diff algorithm in Patch () to generate the real DOM
- Each attribute has its own
dep
Property to store the dependentWatcher
Is notified when the property changesWatcher
To update. - In user acquisition (
getter
Vue adds data to each attributedep
Attribute to collect as DependencyWatcher
. In the usersetting
When setting the property valuedep.notify()
noticeCollect the Watcher
Re-render. See above for detailsdefineReactive()
Dep relies on collection classes
The andWatcher class
Is a many-to-many bidirectional storage relationship- There can be more than one attribute for each
Watcher class
Because properties can be used in different components. - At the same time a
Watcher class
It can also correspond to multiple attributes.
Each attribute can have multiple dependencies. For example, this attribute might be used in computed, watch, or its own data attribute. These dependencies are collected using Dep for reactive data.
- Watcher is a dependency, like a mediation, that can be collected by the Dep and notified of updates by the Dep.
class Watcher {
addDep() {
// Put a watcher dependency into the Dep
},
update() {
// Dep informs Watcher of the update}},Copy the code
6. Template compilation in Vue
Template compilation in Vue: Essentially converting a template into a render function. Basically, compile a real DOM(template) into a virtual DOM(Vnode)
- The first step is to
Template template
String conversion toAst syntax tree
Parser), which uses a lot of re’s to match tag names, attributes, text, etc. - The second step is to statically node the AST
static
The optimize optimizer for the virtual DOM, which iterates through all the child nodes and makes static markup - The third step is use
Ast syntax tree
To regenerate theRender function
Code string code. (codeGen Code Generator)
Why label nodes statically? If they are static (no binding data, no change between nodes is required) then the diff algorithm is not required for subsequent comparisons.
7. Lifecycle hook implementation principles
- The lifecycle hook in VUE is simply a callback function that is invoked during the creation of a component instantiation.
- use
Vue.mixin({})
A mixin hook or lifecycle defines multiple functions that are called internally by the VUEmergeHook()
Merge hooks into queues and execute them in sequence - extension
// src\core\util\options.js
function mergeHook (
parentVal: ?Array<Function>,
childVal: ?Function|?Array<Function>
): ?Array<Function> {
const res = childVal
? parentVal
? parentVal.concat(childVal) / / merge
: Array.isArray(childVal)
? childVal
: [childVal]
: parentVal
return res
? dedupeHooks(res)
: res
}
Copy the code
8. What is the well-worn VUE lifecycle, and where are requests generally sent?
beforeCreate
: Just initialize vUE instance in data observationobserver
It was called before, it hasn’t been created yetdata/methods
Attributes such ascreated
: Vue instance initialization is complete, all attributes have been created.beforeMount
The render function fires when the hook is triggered before vue mounts data to the page.mounted
: el is createdvm.$el
Instead, the vUe-initialized data has been mounted to the page, where the real DOM can be accessed. This is where you typically request data.beforeUpdate
: called when the data is updated, that is, before the virtual DOM is re-rendered.updated
: occurs after a data change causes the virtual DOM to be re-rendered.beforeDestroy
This hook is called before the instance is destroyed, while the instance is still there.vm.$destroy
Trigger two methods.destroyed
: called after the Vue instance is destroyed. All event listeners will be touched.
The request data depends on the specific business requirements for where to send ajax
9. Application scenarios and principles of vue.mixin ({})
- Usage scenario: Used to separate a common business logic for reuse.
- Implementation principle: call
mergeOptions()
Methods Policy pattern was adopted to merge different attributes. If there is a conflict between mixed data and component data, use the component’s own data. Vue.mixin({})
Defects: 1. It may cause naming conflicts between mixed attribute names and component attribute names; 2. The source of data dependence- extension
export function mergeOptions (
parent: Object,
child: Object, vm? : Component) :Object {
// some code
if(! child._base) {if (child.extends) {
parent = mergeOptions(parent, child.extends, vm)
}
if (child.mixins) {
for (let i = 0, l = child.mixins.length; i < l; i++) {
parent = mergeOptions(parent, child.mixins[i], vm)
}
}
}
// Recursively iterate over merged components and mixin properties
const options = {}
let key
for (key in parent) {
mergeField(key)
}
for (key in child) {
if(! hasOwn(parent, key)) { mergeField(key) } }function mergeField (key) {
const strat = strats[key] || defaultStrat
options[key] = strat(parent[key], child[key], vm, key)
}
return options
}
Copy the code
10. Why does data in vUE components have to be a function?
- It has to do with the mechanics of JS itself,
data
A function returns a different reference address to ensure that data from different components does not contaminate each other. Vue.mixin()
If mixed withdata
Property, thendata
It also has to be a function. becauseVue.mixin()
It can also be used in multiple places.- In the instance
data
It can be an object or a function, since we typically only initialize one Vue instance per page (singleton)
Vue vm.$nextTick(CB) implementation principle and scenario
- Scene:
Called at the end of the DOM update cycle to get updated DOM data
- Implementation principle:
vm.$nextTick(cb)
It’s an asynchronous method that does a lot of downgrading for compatibilityPromise. Then, MutationObserver setImmediate, setTimeout
. Views are not updated immediately after data changes, but afterset
Method notifyWatcher
Update, will need to updateWatcher
Put it in an asynchronous queue,nexTick
The callback function of theWatcher
Wait for the main thread to execute the synchronous code overnight and then empty the queue in turn, sovm.nextTick(callback)
Is in thedom
Executed after the update is complete.
This is the principle of vUE asynchronous batch update. A quick thought: why not just use setTimeout instead? Because setTimeout is a macro task, the performance of multiple macro tasks is also poor. For event loops, see the JS event loop
12. The cliche difference between watch and computed
computed
The inside is based onObject.definedProperty()
Implementation of thecomputed
With caching function, the dependent value does not change, will not recalculate.watch
Is to monitor the change of the value and execute the corresponding callback function when the value changes.computed
和watch
Are based onWatcher class
To execute.
Computed caching relies on a variable called dirty, which is true by default and false, and returns the last value when it is used again.
// SRC \core\instance\state.js computed value function
function createComputedGetter (key) {
return function computedGetter () {
const watcher = this._computedWatchers && this._computedWatchers[key]
if (watcher) {
if (watcher.dirty) { // Check whether the value is dirty
watcher.evaluate()
}
if (Dep.target) {
watcher.depend()
}
return watcher.value
}
}
}
// SRC \core\instance\state.js watch implementation
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
// instantiate watcher
const watcher = new Watcher(vm, expOrFn, cb, options)
if (options.immediate) {
const info = `callback for immediate watcher "${watcher.expression}"`
pushTarget()
invokeWithErrorHandling(cb, vm, [watcher.value], vm, info)
popTarget()
}
return function unwatchFn () {
watcher.teardown()
}
}
Copy the code
reference
Vue template compilation principle
Vue.nextTick principle and use
The end of the
Thank you for reading to this point, if you feel that the writing is ok, welcome sanlian ah, I am Lin Yiyi, see you next time.