BT

Facilitating the Spread of Knowledge and Innovation in Professional Software Development

Write for InfoQ

Topics

Choose your language

InfoQ Homepage News Vue 3 Reactivity Internals - Sarah Drasner at Vue.JS Amsterdam

Vue 3 Reactivity Internals - Sarah Drasner at Vue.JS Amsterdam

This item in japanese

Sarah Drasner, Vue.js core team member, gave an overview of Vue 3 reactivity internals. Vue’s reactivity functionality is isolated in a separate package and can be used standalone.

Vue 3, the new major iteration for the Vue.js framework, updated its reactivity model, and released its reactivity module in a separate package. The Vue 3 composition API adds reactive and ref APIs to declare reactive entities. The reactivity engine which was previously implemented with Object.defineProperty in order to ensure better support for older versions of Internet Explorer now leverages native ES6 proxies that are supported by all modern browsers, but not IE11.

Vue’s reactivity model allows developers to create reactive entities from standard JavaScript or other reactive entities. Those reactive entities can then be read and updated, like any other variables. However, updating the value of a reactive entity will trigger the update of all dependent reactive entities. For this to happen, Vue needs to keep track of its reactive entities and their dependencies. This is achieved with ES6 proxies.

ES6 proxies wrap a target JavaScript object and intercept operations that are performed on this object. Given an object obj = {x:0, y:0}, obj.x can be understood as get(obj, 'x'), while the assignment obj.x = 42 can be understood as set(obj, 'x', 42). Proxies are most commonly used to intercept and modify (generally only adding to) the semantics of the set and get operations. Other operations on objects can however be intercepted (object property deletion, instance construction, function call, and more).

Drasner used the following sample code to illustrate how proxies are used in Vue 3:

const dinner = {
  meal: 'tacos'
}

const handler = {
  get(target, key, receiver) {
    track(target, key)
    return Reflect.get(...arguments)
  },
  set(target, key, value, receiver) {
    let oldValue = target[key]
    let result = Reflect.set(...arguments)
    if (oldValue != result) {
      trigger(target, key)
    }
  }
}

The track function creates the list of dependencies for a reactive entity, while the trigger function runs the dependent computations when a reactivity entity is updated. If x = a + b where all variables are reactive entities, the first evaluation of x will identify (track) a and b are dependencies of x. Subsequent updates of a or b will rerun (trigger) the computation of x. Implementation-wise, the data structures used for tracking the dependencies and effects (reran computations) are Maps, Sets, and WeakMaps.

Ryan Carniato, creator of the Solid reactive UI framework lauded the performance of the standalone Vue reactive system (have a look at the vuerx-jsx column):

Vue’s Reactive system performance is very impressive on its own. Here’s a look at it running with my reactive runtime compared to other reactive runtimes, and the usual suspects including Vue 3 beta:

Image

Vue 3’s standalone reactivity package is available on GitHub with an MIT license. While there is not yet any documentation for the standalone package, the source code is reasonably short and can be understood without major difficulties. The Vue 3 composition API RFC can also be used as a documentation source.

The full video for the talk contains plenty of additional information and didactic animations.

Vue.js Amsterdam 2020 is a yearly conference targeted at Vue developers with talks addressing the latest technologies and trends in software development.

Rate this Article

Adoption
Style

BT