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

A brief talk on responsive design

1. What is responsive design? Responsive design i...

Should I use distinct or group by to remove duplicates in MySQL?

Preface About the performance comparison between ...

How to choose the format when using binlog in MySQL

Table of contents 1. Three modes of binlog 1.Stat...

How to add a column to a large MySQL table

The question is referenced from: https://www.zhih...

Example of implementing element table row and column dragging

The element ui table does not have a built-in dra...

Use of Linux chkconfig command

1. Command Introduction The chkconfig command is ...

How to hide the version number in Nginx

Nginx hides version number In a production enviro...

Detailed steps to install RabbitMQ in docker

Table of contents 1. Find the mirror 2. Download ...

A brief discussion on four solutions for Vue single page SEO

Table of contents 1.Nuxt server-side rendering ap...

Detailed application of Vue dynamic form

Overview There are many form requirements in the ...

Summary of changes in the use of axios in vue3 study notes

Table of contents 1. Basic use of axio 2. How to ...

Using JavaScript difference to implement a comparison tool

Preface At work, I need to count the materials su...

mySQL server connection, disconnection and cmd operation

Use the mysql command to connect to the MySQL ser...

MySQL server 5.7.20 installation and configuration method graphic tutorial

This article records the installation and configu...