Небольшой трюк для обновления компонентов в Vue и его принцип

Прямо в точку

Как показано ниже, что мне делать, если я хочу обновить шаблон таблицы дочернего компонента в Vue?

Например, я изменил значение списка list, и дочерний компонент нужно обновить.

<template>
  <div class="wrapper">
    <table-template
      ref="table"
      :columnData="fieldDetail.column"
      :listData="fieldDetail.list"
    />
  </div>
</template>
复制代码

общий метод

метод 1:

Определите метод перезагрузки в шаблоне таблицы дочернего компонента для обновления данных.

this.$refs['table'].reload()
复制代码

На самом деле я хочу перезагрузить весь подкомпонент и заново пройти жизненный цикл. Что ж, попробуйте директиву v-if.

Способ 2:

директива v-if, элемент и его привязки/компоненты данных уничтожаются и перестраиваются при переключении

<template>
  <div class="wrapper">
    <table-template
      v-if="showFlag"
      ref="table"
      :columnData="fieldDetail.column"
      :listData="fieldDetail.list"
    />
  </div>
</template>
复制代码
this.showFlag = false;
this.$nextTick(()=>{
  this.showFlag = true;
})
复制代码

Советы

Обновите компонент через связанное значение ключа

Полностью активировать хуки жизненного цикла компонентов

<template>
  <div class="wrapper">
    <table-template
      :key="fieldDetail.timer"
      :columnData="fieldDetail.column"
      :listData="fieldDetail.list"
    />
  </div>
</template>
复制代码
this.fieldDetail.list = res.data
this.fieldDetail.timer = new Date().getTime();
复制代码

Советы:

Специальный атрибут ключа в основном используется в алгоритме виртуального DOM Vue для идентификации виртуальных узлов при сравнении старых и новых узлов.

Без ключей Vue использует алгоритм, который сводит к минимуму динамические элементы и пытается максимально модифицировать/повторно использовать элементы одного и того же типа на месте .

При использовании ключа он изменит порядок элементов на основе изменения ключа и удалит элементы, ключ которых не существует.

Дочерние элементы с одним и тем же родительским элементом должны иметь уникальные ключи. Повторяющиеся ключи вызовут ошибки рендеринга.

Наиболее распространенный вариант использования — объединить v-for

<ul>
  <li v-for="item in items" :key="item.id">...</li>
</ul>
复制代码

Его также можно использовать для принудительной замены элемента/компонента вместо его повторного использования. Это может быть полезно, когда вы сталкиваетесь со следующими сценариями:

1. Полностью активировать хуки жизненного цикла компонентов

2. Активируйте переход

Например:

<transition>
  <span :key="text">{{ text }}</span>
</transition>
复制代码

Когда текст изменяется, он всегда заменяется, а не модифицируется, что запускает переход.

Обоснование позади

Принцип, лежащий в основе этого, должен начинаться с алгоритма сравнения виртуального DOM Vue.

Целью алгоритма сравнения виртуального DOM является максимально быстрое отображение каждого изменения на странице браузера.

Например, ремонт дома.

Два варианта:

1. Демонтирован и восстановлен;

2. Уточните сравнение и измените то, что вам нужно изменить.

diff означает уточненное сравнение.

виртуальный DOM

React和Vue都采用虚拟DOM,当数据改变时,不用整体重新渲染,局部刷新变化即可。

简短解说,两句话:

1.通过JavaScript创建虚拟的DOM树结构,呈现至页面。

2.数据改变时,引发DOM树结构改变,生成新的虚拟DOM树,和之前的DOM对比,将变化的部分应用到真实的DOM树中,渲染至页面。

那么,虚拟dom与key值的关系是怎样的呢?

虚拟DOM与key值的关系

首先,我们来看看Vue中的虚拟DOM长啥样,源码如下:

export default class VNode {
  constructor (
    tag?: string,
    data?: VNodeData,
    children?: ?Array<VNode>,
    text?: string,
    elm?: Node,
    context?: Component,
    componentOptions?: VNodeComponentOptions,
    asyncFactory?: Function
  ) {
    this.tag = tag                                /*当前节点的标签名*/
    this.data = data        /*当前节点对应的对象,包含了具体的一些数据信息,是一个VNodeData类型,可以参考VNodeData类型中的数据信息*/
    this.children = children  /*当前节点的子节点,是一个数组*/
    this.text = text     /*当前节点的文本*/
    this.elm = elm       /*当前虚拟节点对应的真实dom节点*/
    this.ns = undefined            /*当前节点的名字空间*/
    this.context = context          /*当前组件节点对应的Vue实例*/
    this.fnContext = undefined       /*函数式组件对应的Vue实例*/
    this.fnOptions = undefined
    this.fnScopeId = undefined
    this.key = data && data.key           /*节点的key属性,被当作节点的标志,用以优化*/
    this.componentOptions = componentOptions   /*组件的option选项*/
    this.componentInstance = undefined       /*当前节点对应的组件的实例*/
    this.parent = undefined           /*当前节点的父节点*/
    this.raw = false         /*简而言之就是是否为原生HTML或只是普通文本,innerHTML的时候为true,textContent的时候为false*/
    this.isStatic = false         /*静态节点标志*/
    this.isRootInsert = true      /*是否作为跟节点插入*/
    this.isComment = false             /*是否为注释节点*/
    this.isCloned = false           /*是否为克隆节点*/
    this.isOnce = false                /*是否有v-once指令*/
    this.asyncFactory = asyncFactory
    this.asyncMeta = undefined
    this.isAsyncPlaceholder = false
  }

  get child (): Component | void {
    return this.componentInstance
  }
}
复制代码
this.key = data && data.key           
/*节点的key属性,被当作节点的标志,用以优化*/
复制代码

key的作用: 辅助判断新旧vdom节点在逻辑上是不是同一个对象。

使用key来给每个节点做一个唯一标识,diff算法就可以正确的识别此节点。

key的作用主要是为了高效的更新虚拟DOM。

接着提问,为什么要使用虚拟DOM呢?

Vue采用虚拟DOM的目的是什么?

这就要从早期的前端开发说起了。

HTML是结构化的文本文档,每一个元素(element)对应HTML中的一段结构化文本,DOM(Document Object Model,文档对象模型)可以理解为这段结构化文本的抽象。

DOM储存于内存中,提供了操作和修改HTML元素的一系列API。

DOM操作是前端开发的核心,最早流行的一些前端框架、工具库大都以优秀的DOM操作闻名,比如prototype.js和jQuery.js。

与JavaScript逻辑相比,DOM操作的性能消耗非常高,在以静态内容为主的WebPage时代,少量DOM操作的性能损耗基本可以忽略不计。然而对于存在丰富动态内容的WebApp而言,大量、频繁的DOM操作逐渐成为性能瓶颈

对于JavaScript而言,虚拟DOM仅仅是一个拥有丰富属性的对象,所有针对DOM的操作被映射为对JavaScript对象的修改,性能上自然大幅优于直接对DOM的操作。

引入虚拟DOM还带来了以下好处:

1.组件高度抽象化。

2.跨平台能力:可以渲染到 DOM 以外的平台。

参考书籍

《深入实战Vue开发》殷荣桧

《前端技术架构与工程》周俊鹏

Je suppose que tu aimes

Origine juejin.im/post/7084058976110772238
conseillé
Classement