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?

MPAMulti-page applications.

  • Composition: There are multiple pageshtmlComposition,
  • Jump mode: A page jumps from one page to another
  • Refresh method: full page refresh
  • Page data jump: dependencyURL/cookie/localStorage
  • Resources after the jumpWill reload
  • Advantages: More friendly to SEO, low difficulty in development.

SPASingle 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 jumpDoes 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 layerview.

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:modelData 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 examplesviewModelVueThe main thing to do. In other words: as long as willData Model layer ModelData mount toViewModelVueTwo-way data binding can be implemented.
  • addvuex/reduxCan be used as aVue and reactmodelThe 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 layercontrollerBelong to one-way link. MVVM hides the control layercontrollerSo 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

  • vueOne is implemented indefinedReactiveMethod, method internal borrowingObject.definedProperty()Each attribute is addedget/setProperties.
  • definedReactiveOnly the outermost objects can be monitored, and the inner objects need to be recursively hijacked.
  • The array is seven rewrittenpush pop shift unshift reverse sort spliceTo 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 arraydefinedProperty()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 = 2They’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 owndepProperty to store the dependentWatcherIs notified when the property changesWatcherTo update.
  • In user acquisition (getterVue adds data to each attributedepAttribute to collect as DependencyWatcher. In the usersettingWhen setting the property valuedep.notify()noticeCollect the WatcherRe-render. See above for detailsdefineReactive()
  • Dep relies on collection classesThe andWatcher classIs a many-to-many bidirectional storage relationship
  • There can be more than one attribute for eachWatcher classBecause properties can be used in different components.
  • At the same time aWatcher classIt 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 toTemplate templateString conversion toAst syntax treeParser), which uses a lot of re’s to match tag names, attributes, text, etc.
  • The second step is to statically node the ASTstaticThe optimize optimizer for the virtual DOM, which iterates through all the child nodes and makes static markup
  • The third step is useAst syntax treeTo regenerate theRender functionCode 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.
  • useVue.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 observationobserverIt was called before, it hasn’t been created yetdata/methodsAttributes such as
  • created: Vue instance initialization is complete, all attributes have been created.
  • beforeMountThe render function fires when the hook is triggered before vue mounts data to the page.
  • mounted: el is createdvm.$elInstead, 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.
  • beforeDestroyThis hook is called before the instance is destroyed, while the instance is still there.vm.$destroyTrigger 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: callmergeOptions()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,dataA function returns a different reference address to ensure that data from different components does not contaminate each other.
  • Vue.mixin()If mixed withdataProperty, thendataIt also has to be a function. becauseVue.mixin()It can also be used in multiple places.
  • In the instancedataIt 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 aftersetMethod notifyWatcherUpdate, will need to updateWatcherPut it in an asynchronous queue,nexTickThe callback function of theWatcherWait for the main thread to execute the synchronous code overnight and then empty the queue in turn, sovm.nextTick(callback)Is in thedomExecuted 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

  • computedThe inside is based onObject.definedProperty()Implementation of the
  • computedWith caching function, the dependent value does not change, will not recalculate.
  • watchIs to monitor the change of the value and execute the corresponding callback function when the value changes.
  • computedwatchAre based onWatcher classTo 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.