If I change a property randomly in Vue data, will the view be updated?

If I change a property randomly in Vue data, will the view be updated?
  • Interviewer: Have you read the source code of Vue?
  • Candidate: I have.
  • Interviewer: Then, if we change any property in Vue data , will the view be updated?
  • Candidate: No.
  • Interviewer: why?
  • Candidates: If the property is not used in the template, there is no need to update the view, and doing so frequently will result in poor performance.
  • Interviewer: How do you implement this solution in Vue?
  • Candidates: During instance initialization, use Object.defineProperty to monitor the properties in data. If the properties are used in template , they will be collected by the Dep class, and when the properties are changed, notify will be called to update the view.
  • Interviewer: How do you know which attributes are used in the template?
  • Candidate: WTF. . . This is not very clear, could you explain it?
  • Interviewer: OK, let me explain briefly:

Let's write a simple demo first. There are 4 attributes a, b, c, d in the data, and only a and b are used in the template. See if only a and b will call Dep to collect them?

new Vue({
  el: '#app',
  data() {
    return {
      a: 1,
      b: 2,
      c: 3,
      d: 4,
    };
  },
  created() {
    console.log(this.b);
    this.b = 'aaa';
  },
  template: '<div>Hello World{{a}}{{b}}</div>',
});


In Vueinstance/state.js, proxy will be used to proxy each attribute

const keys = Object.keys(data)
  const props = vm.$options.props
  const methods = vm.$options.methods
  let i = keys.length
  while (i--) {
    const key = keys[i]
    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 instead.`,
        vm
      )
    } else if (!isReserved(key)) {
      //Properties of the proxy object proxy(vm, `_data`, key)
    }
  }
  // observe data
  observe(data, true /* asRootData */)


Use defineReactive to hijack each attribute in data

observe(data, true /* asRootData */);

// observe
const keys = Object.keys(obj);
for (let i = 0; i < keys.length; i++) {
  defineReactive(obj, keys[i]);
}

// defineReactive
Object.defineProperty(obj, key, {
  enumerable: true,
  configurable: true,
  get: function reactiveGetter() {
    const value = getter ? getter.call(obj) : val;
    // The key point is here. If the attributes are used in the template later, the reactiveGetter function will be executed // Collected by the Dep class if (Dep.target) {
      console.log(`${key} property is collected by Dep class`)
      dep.depend();
      if (childOb) {
        childOb.dep.depend();
        if (Array.isArray(value)) {
          dependArray(value);
        }
      }
    }
    return value;
  },
  set: function reactiveSetter(newVal) {
    const value = getter ? getter.call(obj) : val;
    /* eslint-disable no-self-compare */
    if (newVal === value || (newVal !== newVal && value !== value)) {
      return;
    }
    if (setter) {
      // Here is the computed set function setter.call(obj, newVal);
    } else {
      val = newVal;
    }
    childOb = !shallow && observe(newVal);
    // If we change the property, we will call notify to asynchronously update the view dep.notify();
  },
});

Execute $mount to mount the view

if (vm.$options.el) {
  vm.$mount(vm.$options.el);
}


$mount is a method that calls the Vue prototype. The key point is the last sentence mount.call(this, el, hydrating)

Vue.prototype.$mount = function (
  el?: string | Element,
  hydrating?: boolean
): Component {
  el = el && query(el);

  const options = this.$options;
  // resolve template/el and convert to render function
  /**
   * Check if the render function exists? If it does not exist, parse the template template* When Vue renders a page, there are two ways: 1. template, 2. render. Ultimately, all template classes need to be rendered using render*/
  if (!options.render) {
    let template = options.template;
    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.innerHTML;
      } else {
        if (process.env.NODE_ENV !== 'production') {
          warn('invalid template option:' + template, this);
        }
        return this;
      }
    } else if (el) {
      // If the template does not exist, create a default html template template = getOuterHTML(el);
    }
  }
  // Rewrite Vue.prototype.$mount, and finally call the cached mount method to complete the mounting of $mount return mount.call(this, el, hydrating);
};

Here mount calls the mountComponent(this, el, hydrating) method, and mountComponent executes the _render function, and finally _render calls render to generate a vnode.

const { render, _parentVnode } = vm.$options;
vnode = render.call(vm._renderProxy, vm.$createElement);


The last picture shows that render function is rendering template in our demo . In the end, only the two attributes a and b will be collected by the Dep class.

If there are any mistakes in the article, please point them out and I will continue to improve them. Thank you. If you need to debug the source code, click here and follow the readme. Hope star

This is the end of this article about changing a property in Vue data at will update the view? For more relevant Vue data content, please search for previous articles on 123WORDPRESS.COM or continue to browse the related articles below. I hope you will support 123WORDPRESS.COM in the future!

You may also be interested in:
  • Do you know why vue data is a function?
  • vue modifies data problems and displays operations in real time
  • Vue subcomponent modifies data or calls operations
  • Solution steps for real-time synchronization after vue data variables are assigned to each other

<<:  Import CSS files using judgment conditions

>>:  HTML+CSS3 code to realize the animation effect of the solar system planets

Recommend

Detailed steps to install JDK and Tomcat in Linux environment

Table of contents 1. Install JDK Manual Installat...

MySQL 5.7.27 installation and configuration method graphic tutorial

MySQL 5.7.27 detailed download, installation and ...

Example code for converting http to https using nginx

I am writing a small program recently. Because th...

A brief discussion on the implementation principle of Webpack4 plugins

Table of contents Preface know Practice makes per...

Docker commands are implemented so that ordinary users can execute them

After installing docker, there will usually be a ...

How to block and prohibit web crawlers in Nginx server

Every website usually encounters many non-search ...

How to package the project into docker through idea

Many friends have always wanted to know how to ru...

Javascript destructuring assignment details

Table of contents 1. Array deconstruction 2. Obje...

Timeline implementation method based on ccs3

In web projects we often use the timeline control...

A brief discussion on whether too many MySQL data queries will cause OOM

Table of contents Impact of full table scan on th...

Architecture and component description of docker private library Harbor

This article will explain the composition of the ...