Last Friday, I followed a senior teacher to interview a front-end developer with three years of work experience. I watched carefully. I think I have been interviewed by others, now interview others, the feeling is actually the same.

preface

  • What should a Three-year Vue user know?
  • Why is the foundation for years of work getting weaker?
  • How does work find time for learning?

An interview question

We’re not asking you to memorize the answers, but to learn the ideas. Just as you get into a new field like React, you can also refine the basic ideas.

Interview question: how does 👂Vue listen to data?

This is an old question that you can answer with some basic knowledge. My senior sister told me that the problem is not just the problem itself, but the system that comes along with this knowledge. 📝

01 How is object data monitored

In ve2. X, data listening is implemented using the Object.defineProperty API. We can look at an example 🌰

var text = 'vue'; const data = {}; Object.defineProperty(data, 'text', { get() { return text; }, set(newVal) { text = newVal; }}); data.text // 'vue' data.text = 'react' // 'react'Copy the code

Whenever we access or set a property of an object, we fire the corresponding function, which then returns or sets the value of the property. We can of course do what we want when we fire a function, which is called hijacking.

In Vue, we use Object.defineProperty to hijack setters and getters for Object properties and create a listener that notifies when data changes.

var data = { name:'hello', Item.keys (data). ForEach (function(key){item.defineProperty (data,key,{item.defineProperty){item.defineProperty (data,key,{item.defineProperty :true,}) Iterate through in loop or list in object. keys. Get :function(){console.log(' get data '); the 64x works without any additional control system. }, set:function(){console.log(' listen to data change '); }})}); Data. name // The console will print "get data" data.name = 'world' // the console will print "Listen for data change"Copy the code

How is the 02 array data monitored

We know that the above is listening to the data of the object, we cannot “hijack” the data of the array. So what does Vue do?

import { def } from '.. /util/index' const arrayProto = Array.prototype export const arrayMethods = Object.create(arrayProto) 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 } if (inserted) ob.observeArray(inserted) // notify change ob.dep.notify() return result })})Copy the code

The reason Vue can listen on arrays is because it overwrites the array methods. These are the steps:

01 first get the prototype method of the native Array, because we still need the native method to help us implement the Array change after interception.

Do some intercepting of Array’s prototype methods using Object.defineProperty.

Point the Array type data prototype that needs to be intercepted to the modified prototype.

Why can’t Vue detect array changes

This is not to say that JS cannot support reactive arrays; there is no such limitation.

Array in JS is often regarded as stack, queue, collection and other data structure implementation, there will be a batch of data to traverse. And the Runtime optimizes objects and arrays differently.

So the processing of arrays needs to be specialized to improve performance.

Vue implements responsiveness by setting getters/setters for each key. Developers use arrays for traversal purposes. Getters are too expensive to call, so Vue does not set getters for each key in the array. And it replaces the prototype methods like push that affect the original array.

GitHub asked Utah about this, and he replied that he did not listen to arrays in this way because of performance issues. Github.com/vuejs/vue/i…

Source location: SRC/core/observer/index, js

constructor (value: any) {
    this.value = value
    this.dep = new Dep()
    this.vmCount = 0
    def(value, '__ob__', this)
    if (Array.isArray(value)) {
      if (hasProto) {
        protoAugment(value, arrayMethods)
      } else {
        copyAugment(value, arrayMethods, arrayKeys)
      }
      this.observeArray(value)
    } else {
      this.walk(value)
    }
  }

  /**
   * Walk through all properties and convert them into
   * getter/setters. This method should only be called when
   * value type is Object.
   */
  walk (obj: Object) {
    const keys = Object.keys(obj)
    for (let i = 0; i < keys.length; i++) {
      defineReactive(obj, keys[i])
    }
  }
Copy the code

From the source code, we can see that Vue does not set a response for each key of the array. Instead, Vue directly sets a response for the value recursively.

$set can detect array changes

Take a look at the source code to see how vue handles arrays.

Dist /vue.runtime.esm.js

function set (target, key, val) { //... if (Array.isArray(target) && isValidArrayIndex(key)) { target.length = Math.max(target.length, key); target.splice(key, 1, val); return val } if (key in target && ! (key in Object.prototype)) { target[key] = val; return val } //... defineReactive$$1(ob.value, key, val); ob.dep.notify(); return val }Copy the code

  • If target is an array and the index is valid, set the length property.
  • Set value to the target array using the splice method.
  • When set, vUE intercepts the target change and makes the new value responsive
  • And then return value

This is why VUE overrides array methods, using arrays to trigger each item with a value that is responsive.

Answer thought

As mentioned before, it’s not how accurate your answer to an interview question looks, it’s really about context. We go from the shallow to the deep, step by step to decipher the principle, this is the idea of learning.

Source code was resisted before, but now we should try to treat source code as a learning document. The official documentation is mostly about how to use the framework, not so much about principles.

Source address: github.com/vuejs/vue