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

How to install Windows Server 2008 R2 on Dell R720 server

Note: All pictures in this article are collected ...

Installation and configuration method of vue-route routing management

introduce Vue Router is the official routing mana...

mysql: [ERROR] unknown option '--skip-grant-tables'

MySQL database reports ERROR 1045 (28000): Access...

7 cool dynamic website designs for inspiration

In the field of design, there are different desig...

Five things a good user experience designer should do well (picture and text)

This article is translated from the blog Usability...

How to explain TypeScript generics in a simple way

Table of contents Overview What are Generics Buil...

Solution to the error reported by Mysql systemctl start mysqld

Error message: Job for mysqld.service failed beca...

Example of automatic stop effect after text scrolling

The effect is very simple, just copy the following...

MySQL 5.7 and above version download and installation graphic tutorial

1. Download 1. MySQL official website download ad...

Detailed explanation of CSS3 elastic expansion box

use Flexible boxes play a vital role in front-end...

9 Tips for Web Page Layout

<br />Related articles: 9 practical suggesti...