As far as we know, key has the following functions.

  • V-for traversal, with id, UUID and other keys as the unique identification node to accelerate virtual DOM rendering
  • The reactive system manually forces the re-rendering of data that is not being listened for, using the timestamp generated by +new Date() as the key

Scenario one is similar and familiar, and scenario two looks like this:

<div :key="rerender"> <span>Hello Vue.js ! </span> <complexComponent :propObj="propObj" :propArr="propArr" ></complexComponent> </div> refresh(){ this.rerender = +  new Date(); }Copy the code

What about keys in VUE?

  • Official API knowledge
  • What is the rationale behind the above two usage scenarios?
  • Besides keys, are there any other ways to force DOM updates?
  • The resources

Official API knowledge

  • In vue.js, key is one of the six special attributes key, ref, is, slot, slot-scope, and scope.
  • The key can be a number or a string.
  • Key mainly acts on the virtual DOM algorithm of Vue and serves as a clue to identify VNodes when diff New Nodes list and old Nodes list.
  • Instead of using a key, Vue uses an algorithm that minimizes the movement of an element and tries to patch or reuse the same type of element as much as possible in the same place.
  • If a key is used, Vue records elements based on the order of keys. Elements that once had a key are removed or destoryed if they no longer appear.
  • Children with the same parent must have unique keys. Duplicate keys cause a Render error.

The most common usage: V-for

<ul>
    <li v-for="item in items" :key="item.id">.</li>
</ul>
Copy the code

Most commonly used: force element or Component replacement

  • Trigger the lifecycle of the component
  • Trigger the transition
<transition>
  <span :key="text">{{ text }}</span>
</transition>
Copy the code

When text changes, will be replaced instead of patched, so transition will be triggered. My understanding: When text changes, the key of the span changes, so the span that used to have the old key no longer appears, and when text is the key that has the new key, the span that has the new key appears, and the old key span is removed, and the old transition is removed. New Key Span triggers render, new Transition triggers.

What is the rationale behind the above two usage scenarios?

Let’s review the scenario presented at the beginning of this article with some knowledge of the official API.

Scenario 1: V-for traversal, using id, UUID and the like as key to uniquely identify the node to accelerate virtual DOM rendering

The answer:

  • Instead of using a key, Vue uses an algorithm that minimizes the movement of an element and tries to patch or reuse the same type of element as much as possible in the same place.
  • If a key is used, Vue records elements based on the order of keys. Elements that once had a key are removed or destoryed if they no longer appear.

Scenario 2: The reactive system manually forces the re-rendering of data that it is not listening to, using the timestamp generated by +new Date() as the key

<div :key="rerender"> <span>Hello Vue.js ! </span> <complexComponent :propObj="propObj" :propArr="propArr" ></complexComponent> </div> refresh(){ this.rerender = +  new Date(); }Copy the code

The answer:

  • If a key is used, Vue records elements based on the order of keys. Elements that once had a key are removed or destoryed if they no longer appear.
  • After the refresh method is called, the key of div containing span and complexComponent changes, that is, the div with the old key no longer appears. When rerender with the new key is used as the key, the div with the new key appears. The old key div is removed, the old Span and complexComponent are removed, the new key div triggers rendering, and the new Span, the new complexComponent with the parent propObj and propArr, renders.

Think about:

  1. Why propObj and propArr?
  2. Render a new complexComponent with the parent propObj and propArr. Why bold?

Since Vue. Js obj and ARR cannot detect data changes, obj is the addition and deletion of attributes (the reason is that neither the addition and deletion trigger setter, watcher does not tell the outside world to update). Arr is a reassignment or modification of the length property of an array element (because the array itself is not changed, the array prototype chain interceptor is not triggered, and Watcher does not tell the outside world about the update). So! Removing old key divs and rendering new key divs by assigning new keys, propObj and propArr within complexComponent components trigger a new life cycle and re-render. ** Now the parent component’s propObj and propArr JS variables have obtained new values, but the DOM is not triggered, and VNode can also re-render. ** You need to refresh the key to force update, and speaking of forceUpdate, you can manually force the DOM update with $forceUpdate().

Besides keys, are there any other ways to force DOM updates?

Scenario: The parent component modifies the data passed to the child component, and the array data is not updated according to this.$set. What to do?

this.productImages.forEach((product) = > {
  if (product.productId in this.productsState) {
    product.status = this.productsState[product.productId]; }});Copy the code

Why can’t rerender assign data without using this.$set? In vue.js, detection of Array changes is implemented by intercepting prototypes. It responds by intercepting push, POP, Shift, unshift, splice, sort, reverse, fill, copyWithin methods that change the contents of the array itself. And the product. The status = this. ProductsState [product. ProductId]; No listening methods that change the array itself are triggered, so rerender is not rerender.

  • Refresh the key of the component
  • $forceUpdate method

Refresh the key of the component

1. Where is the best place to add this key?

Add it to the parent element of this.productImages. If there is no data transfer involved, it can be added directly to the element that needs to be updated.

2. What is the key value?

Now the +new Date() timestamp is rude for the key value. You can also use the bidirectional binding value as the key value, ensuring that the new and old key values are different.

3. What is the principle of key?

When vue. Js virtual DOM algorithm updates vNodes, it needs to find the same vNode as the new vNode from the list of old vNodes to update. If the attribute key is set in this process, the process will be much faster. See above for other details.

$forceUpdate method

This method can only be called in the parent component to manually tell the Vue instance to rerender.

/ / $forceUpdate source code
Vue.prototype.$forceUpdate = function () {
  const vm: Component = this
  if (vm._watcher) {
    vm._watcher.update()
  }
}
/ / update the source code
/** * Subscriber interface. * Will be called when a dependency changes. */
update () {
  /* istanbul ignore else */
  if (this.lazy) {
    this.dirty = true
  } else if (this.sync) {
    this.run()
  } else {
    queueWatcher(this)}}Copy the code
$forceUpdate $forceUpdate $forceUpdate

product.status = this.productsState[product.productId]; In the future, the deP has changed, but the vue. js array responsive implementation does not detect this change because it intercepts the prototype chain method, so it does not rerender automatically and does not trigger update. So we rerender by calling the update method on the watcher containing the DEP via $forceUpdate.

2. Can I listen for events in the child component, the parent component sends events and then only refresh the child component?

Can’t. Because deP is the watcher and DEP of the parent, not the child, it is the parent’s this.productImages that are not detected and updated in real time, not the child’s problem.

The resources

Vuejs.org/v2/api/#key vuejs.org/v2/api/#vm-… Vuejs.org/v2/guide/co…

Original link: github.com/FrankKai/Fr…

I am looking forward to communicating with you and making progress together. Welcome to join the technical discussion group I created which is closely related to front-end development:

  • SegmentFault technosphere :ES new specification syntax sugar
  • SegmentFault column: Be a good front-end engineer while you’re still young
  • Zhihu column: Be an excellent front-end engineer while you are still young
  • Github blog: Personal blog 233 while You’re Still Young
  • Front-end development QQ group: 660634678
  • excellent_developers

Strive to be an excellent front-end engineer!