Table of Contents
Dep
Watcher
Observer
Core Process
Code
Home Web Front-end Vue.js What is the responsiveness principle of Vue?

What is the responsiveness principle of Vue?

Jul 29, 2021 pm 05:42 PM
javascript vue.js front end

I have read a lot of articles on Vue principles recently. With the help of these articles, I have tried many times to understand the source code of Vue myself. Finally, I think it’s time to output the content myself. I hope I can familiarize everyone with Vue from a different perspective than other articles.

What is the responsiveness principle of Vue?

Dep

var Dep = function Dep() {
  this.id = uid++
  this.subs = []
}

The meaning of Dep is naturally dependency (that is, dependence, a noun in the computer field).

Just like writing a node.js program, dependencies from the npm warehouse are often used. In Vue, dependencies specifically refer to reactively processed data. As will be mentioned later, one of the key functions of reactive processing is defineReactive, which is mentioned in many Vue principle articles.

After Dep is bound to each responsive data, the responsive data will become a dependency (noun). When introducing Watcher below, it will be mentioned that responsive data may be watched, computed, or in the template. Use 3 cases of dependence (verb).

#subs

There is a subs attribute under the Dep object, which is an array. It is easy to guess that it means the subscriber list. Subscribers may be watch functions, computed functions, or view update functions.

Watcher

Watcher is the subscriber mentioned in Dep (not to be confused with the Observer observer later).

Because the function of Watcher is to respond to Dep updates in a timely manner, just like the subscription push of some apps. If you (Watcher) subscribe to certain information (Dep), you will be reminded to read when the information is updated.

deps

Similar to Dep having the subs attribute, the Watcher object also has the deps attribute. This constitutes a many-to-many relationship between Watcher and Dep. The reason for recording each other is that when one party is cleared, the related objects can be updated in time.

How to generate Watcher

The watch, computed, and rendering templates mentioned many times above generate Watcher, which are all concise and easy to understand in the Vue source code:

  • mountComponent's vm._watcher = new Watcher(vm, updateComponent, noop);
  • initComputed's watchers[key] = new Watcher(vm, getter || noop, noop, computedWatcherOptions)
  • $watcher's var watcher = new Watcher(vm, expOrFn, cb, options);

Observer

Observer is an observer, he is responsible for recursively observing (or processing) reactive objects (or arrays). In the printed example, you can notice that the reactive objects will have an __ob__, which is proof of what has been observed. Observers are not as important as Dep and Watcher above, just a little understanding is enough.

walk

Observer.prototype.walk is the core method of recursive processing during Observer initialization, but this method is used to process objects, and there is also Observer.prototype.observeArray Process arrays.

Core Process

According to the relationship between the above concepts, how to match them and how to achieve responsive data update?

First set our goal: naturally when the data is updated, the view will be automatically refreshed to display the latest data.

This is the relationship between Dep and Watcher mentioned above. The data is Dep, and Watcher triggers the page rendering function (this is the most important watcher).

But a new question arises, how does Dep know that any Watchers depend on him?

Vue adopts a very interesting method:

  • Before running the Watcher's callback function, first write down what the current Watcher is (through Dep.target)

  • If responsive data is used in the running callback function, the getter function of the responsive data will inevitably be called.

  • In the getter function of the responsive data You can write down the current Watcher and establish the relationship between Dep and Watcher

  • After that, when the responsive data is updated, the setter function of the responsive data will inevitably be called

  • Based on the previously established relationship, the callback function corresponding to the Watcher can be triggered in the setter function

Code

The above logic is in the defineReactive function middle. There are many entrances to this function. Let’s talk about the more important observe function first.

In the observe function, a new Observer object will be created, in which Observer.prototype.walk is used to process the values ​​in the object one by one in a responsive manner, and the defineReactive function is used.

Because the defineReactive function is so important and not long, it is more convenient to post it here directly.

function defineReactive(obj, key, val, customSetter, shallow) {
  var dep = new Dep()
  depsArray.push({ dep, obj, key })
  var property = Object.getOwnPropertyDescriptor(obj, key)
  if (property && property.configurable === false) {
    return
  }

  // cater for pre-defined getter/setters
  var getter = property && property.get
  var setter = property && property.set

  var childOb = !shallow && observe(val)
  Object.defineProperty(obj, key, {
    enumerable: true,
    configurable: true,
    get: function reactiveGetter() {
      var value = getter ? getter.call(obj) : val
      if (Dep.target) {
        dep.depend()
        if (childOb) {
          childOb.dep.depend()
          if (Array.isArray(value)) {
            dependArray(value)
          }
        }
      }
      return value
    },
    set: function reactiveSetter(newVal) {
      var value = getter ? getter.call(obj) : val
      // 后半部分诡异的条件是用于判断新旧值都是 NaN 的情况
      if (newVal === value || (newVal !== newVal && value !== value)) {
        return
      }
      // customSetter 用于提醒你设置的值可能存在问题
      if ('development' !== 'production' && customSetter) {
        customSetter()
      }
      if (setter) {
        setter.call(obj, newVal)
      } else {
        val = newVal
      }
      childOb = !shallow && observe(newVal)
      dep.notify()
    },
  })
}

First of all, each responsive value is a "dependency", so in the first step, we use the ability of closure to create a Dep for each value. (With Vue 3, there is no need for closures)

Then look at the three core parameters:

  • obj The object where the value currently needs to be processed responsively

  • key value key

  • val current value

This value may have been defined before own getters and setters, so when doing Vue’s responsive processing, the original getters and setters are processed first.

As mentioned above in the core process, the getter function will establish the relationship between Dep and Watcher, specifically relying on dep.depend().

Below are several methods for Dep and Watcher to call each other:

Dep.prototype.depend = function depend() {
  if (Dep.target) {
    Dep.target.addDep(this)
  }
}
Watcher.prototype.addDep = function addDep(dep) {
  var id = dep.id
  if (!this.newDepIds.has(id)) {
    this.newDepIds.add(id)
    this.newDeps.push(dep)
    if (!this.depIds.has(id)) {
      dep.addSub(this)
    }
  }
}
Dep.prototype.addSub = function addSub(sub) {
  this.subs.push(sub)
}

通过这几个函数,可以领略到了 Dep 和 Watcher 错综复杂的关系……不过看起来迂回,简单来说,其实做的就是上面说的互相添加到多对多列表。

你可以在 Dep 的 subs 找到所有订阅同一个 Dep 的 Watcher,也可以在 Watcher 的 deps 找到所有该 Watcher 订阅的所有 Dep。

但是里面还有一个隐藏问题,就是 Dep.target 怎么来呢?先放一放,后会作出解答。先接着看看 setter 函数,其中的关键是 dep.notify()。

Dep.prototype.notify = function notify() {
  // stabilize the subscriber list first
  var subs = this.subs.slice()
  for (var i = 0, l = subs.length; i < l; i++) {
    subs[i].update()
  }
}

不难理解,就是 Dep 提醒他的订阅者列表(subs)里的所有人更新,所谓订阅者都是 Watcher,subs[i].update() 调用的也就是 Watcher.prototype.update。

那么来看一下 Watcher 的 update 做了什么——

Watcher.prototype.update = function update() {
  if (this.lazy) {
    this.dirty = true
  } else if (this.sync) {
    this.run()
  } else {
    queueWatcher(this)
  }
}

在这里我觉得有两个点比较值得展开,所以挖点坑

The above is the detailed content of What is the responsiveness principle of Vue?. For more information, please follow other related articles on the PHP Chinese website!

Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undress AI Tool

Undress AI Tool

Undress images for free

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

PHP and Vue: a perfect pairing of front-end development tools PHP and Vue: a perfect pairing of front-end development tools Mar 16, 2024 pm 12:09 PM

PHP and Vue: a perfect pairing of front-end development tools. In today's era of rapid development of the Internet, front-end development has become increasingly important. As users have higher and higher requirements for the experience of websites and applications, front-end developers need to use more efficient and flexible tools to create responsive and interactive interfaces. As two important technologies in the field of front-end development, PHP and Vue.js can be regarded as perfect tools when paired together. This article will explore the combination of PHP and Vue, as well as detailed code examples to help readers better understand and apply these two

Exploring Go language front-end technology: a new vision for front-end development Exploring Go language front-end technology: a new vision for front-end development Mar 28, 2024 pm 01:06 PM

As a fast and efficient programming language, Go language is widely popular in the field of back-end development. However, few people associate Go language with front-end development. In fact, using Go language for front-end development can not only improve efficiency, but also bring new horizons to developers. This article will explore the possibility of using the Go language for front-end development and provide specific code examples to help readers better understand this area. In traditional front-end development, JavaScript, HTML, and CSS are often used to build user interfaces

Vue.js vs. React: Project-Specific Considerations Vue.js vs. React: Project-Specific Considerations Apr 09, 2025 am 12:01 AM

Vue.js is suitable for small and medium-sized projects and fast iterations, while React is suitable for large and complex applications. 1) Vue.js is easy to use and is suitable for situations where the team is insufficient or the project scale is small. 2) React has a richer ecosystem and is suitable for projects with high performance and complex functional needs.

Questions frequently asked by front-end interviewers Questions frequently asked by front-end interviewers Mar 19, 2024 pm 02:24 PM

In front-end development interviews, common questions cover a wide range of topics, including HTML/CSS basics, JavaScript basics, frameworks and libraries, project experience, algorithms and data structures, performance optimization, cross-domain requests, front-end engineering, design patterns, and new technologies and trends. . Interviewer questions are designed to assess the candidate's technical skills, project experience, and understanding of industry trends. Therefore, candidates should be fully prepared in these areas to demonstrate their abilities and expertise.

Combination of Golang and front-end technology: explore how Golang plays a role in the front-end field Combination of Golang and front-end technology: explore how Golang plays a role in the front-end field Mar 19, 2024 pm 06:15 PM

Combination of Golang and front-end technology: To explore how Golang plays a role in the front-end field, specific code examples are needed. With the rapid development of the Internet and mobile applications, front-end technology has become increasingly important. In this field, Golang, as a powerful back-end programming language, can also play an important role. This article will explore how Golang is combined with front-end technology and demonstrate its potential in the front-end field through specific code examples. The role of Golang in the front-end field is as an efficient, concise and easy-to-learn

Is vue.js hard to learn? Is vue.js hard to learn? Apr 04, 2025 am 12:02 AM

Vue.js is not difficult to learn, especially for developers with a JavaScript foundation. 1) Its progressive design and responsive system simplify the development process. 2) Component-based development makes code management more efficient. 3) The usage examples show basic and advanced usage. 4) Common errors can be debugged through VueDevtools. 5) Performance optimization and best practices, such as using v-if/v-show and key attributes, can improve application efficiency.

Is Vue used for frontend or backend? Is Vue used for frontend or backend? Apr 03, 2025 am 12:07 AM

Vue.js is mainly used for front-end development. 1) It is a lightweight and flexible JavaScript framework focused on building user interfaces and single-page applications. 2) The core of Vue.js is its responsive data system, and the view is automatically updated when the data changes. 3) It supports component development, and the UI can be split into independent and reusable components.

Understanding React's Primary Function: The Frontend Perspective Understanding React's Primary Function: The Frontend Perspective Apr 18, 2025 am 12:15 AM

React's main functions include componentized thinking, state management and virtual DOM. 1) The idea of ​​componentization allows splitting the UI into reusable parts to improve code readability and maintainability. 2) State management manages dynamic data through state and props, and changes trigger UI updates. 3) Virtual DOM optimization performance, update the UI through the calculation of the minimum operation of DOM replica in memory.

See all articles