很多人不知道可以使用这种-key-的方式来对-Vue-组件时行重新渲染

3次阅读

共计 2768 个字符,预计需要花费 7 分钟才能阅读完成。

作者:Michael Thiessen
译者:前端小智
来源:medium

点赞再看,养成习惯

本文 GitHub https://github.com/qq44924588… 上已经收录,更多往期高赞文章的分类,也整理了很多我的文档,和教程资料。欢迎 Star 和完善,大家面试可以参照考点复习,希望我们一起有点东西。

在某些情况下,我们必须强制 Vue 重新渲染组件,如果没有,那可能,你做的业务还不够负责,反正我是经常需要重新渲染组件,哈哈。

虽然 Vue 不会自动更新这种情况是相对比较少,但是知道如何在出现这个问题时修复它还是很有用的。

在大多数情况下,此问题根源还是我们对 Vue 的响应式理解还是不够到位。因此,要尽量确保我们要正确使用了 Vue。响应式有时过于棘手,我也经常不知道所措。

这节,我们就来做一些之前很少做过或者没做过的:用 key 来让组件重新渲染。

在这篇文章中,会涉及到这几个知识点:

  • key 是如何改变组件
  • key 如何与多个子组件一起工作
  • 如何强制子组件自己更新

通过改变 key 的值来重新渲染组件

我最喜欢的方法是使用 key 属性,因为使用key 的方式,Vue 就知道了特定组件与特定数据相关。

如果 key保持不变,则不会更改组件。但是,如果 key 发生更改,Vue 知道它应该删除旧组件并创建一个新组件。

下面是一个非常基本的方法:

<template>
  <ComponentToReRender
    :key="componentKey"
  />
</template>

<script>
  export default {data() {
      return {componentKey: 0,};
    },
    methods: {forceRerender() {this.componentKey += 1;}
    }
  }
</script>

每次调用 forceRerender 时,componentKey 的值就会更改。当 componentKey 的值发生改变时,Vue 就知道把ComponentToReRender 组件删除并创建一个新组件。

这样 ComponentToReRender 就会重新渲染并重置里面的状态。nice nice!

强制多个子节点进行更新

同样用这种方式也可以用于多个子组件:

<template>
  <div>
    <Child
      :key="key1"
    />
    <Child
      :key="key2"
    />
  </div>
</template>

<script>
  export default {data() {
      return {
        key1: 0,
        key2: 0,
      };
    },
    methods: {forceRerender(child) {if (child === 1) {this.key1 += 1;} else if(child === 2) {this.key2 += 1;}
      }
    }
  }
</script>

这里我们使用了两个单独 key 来分别控制每个子组件是否重新渲染。将它们分开是为了其中的一个子组件渲染,不会影响到另外另一个。

但如果希望两个子组件总是一起更新,则可以使用相同的 kye。但是,key必须是唯一的,所以下面这种方式,不能工作:

<template>
  <div>
    <Child
      :key="componentKey"
    />
    <Child
      :key="componentKey"
    />
  </div>
</template>

<script>
  export default {data() {
      return {componentKey: 0,};
    },
    methods: {forceRerender(child) {this.componentKey += 1;}
    }
  }
</script>

在这里,仅第一个 Child 组件会被渲染。第二个被忽略,因为它具有重复的key 了。

大家都说简历没项目写,我就帮大家找了一个项目,还附赠【搭建教程】。

为了解决这个问题,我们可以基于 componentKey 为每个孩子构造一个新key

<template>
  <div>
    <Child
      :key="`${componentKey}-1`"
    />
    <Child
      :key="`${componentKey}-2`"
    />
  </div>
</template>

<script>
  export default {data() {
      return {componentKey: 0,};
    },
    methods: {forceRerender(child) {this.componentKey += 1;}
    }
  }
</script>

因为我们每次在 componentKey 后面添加 -1-2,所以这两个 key 始终是唯一的,现在这两个组件都将被重新渲染。

如果是在列表中,则可以使用如下方式:

<template>
  <div>
    <Child
      v-for="(item, index) in list"
      :key="`${componentKey}-${index}`"
    />
  </div>
</template>

<script>
  export default {data() {
      return {
        list: [// ...],
        componentKey: 0,
      };
    },
    methods: {forceRerender(child) {this.componentKey += 1;}
    }
  }
</script>

在这里,我们将 key 构造为 ${componentKey}-${index},因此列表中的每个项目都会获得唯一的key,只要componentKey 一改变,列表中的所有组件将同时重新渲染。

当然,还有更简单的方式,就是用 div 把列表包裹起来,直接对 div重新更新就行了:

<template>
  <div :key="componentKey">
    <Child
      v-for="item in list"
      :key="item.id"
    />
  </div>
</template>

<script>
  export default {data() {
      return {
        list: [// ...],
        componentKey: 0,
      };
    },
    methods: {forceRerender(child) {this.componentKey += 1;}
    }
  }
</script>

这中思路可以用在很多地方,可以为我们摆脱很的困境,大家要牢记起来。

好了,今天就跟大家分享到这里,我们下期在见,谢谢大家的观看。


代码部署后可能存在的 BUG 没法实时知道,事后为了解决这些 BUG,花了大量的时间进行 log 调试,这边顺便给大家推荐一个好用的 BUG 监控工具 Fundebug。

原文:https://morioh.com/p/08963bf0…


交流

文章每周持续更新,可以微信搜索「大迁世界」第一时间阅读和催更(比博客早一到两篇哟),本文 GitHub https://github.com/qq449245884/xiaozhi 已经收录,整理了很多我的文档,欢迎 Star 和完善,大家面试可以参照考点复习,另外关注公众号,后台回复 福利,即可看到福利,你懂的。

正文完
 0