Прямо в точку
Как показано ниже, что мне делать, если я хочу обновить шаблон таблицы дочернего компонента в 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开发》殷荣桧
《前端技术架构与工程》周俊鹏