关于 react 与 vue 中的 key
之前在学习 react 的时候, 常常遇到循环渲染组件时会提示需要在循环组件中加上 key 属性, 比如有一组列表:
- import React, { Component } from 'react';
- export default calss MainApp extends Component {
- state = {
- student: [
- {
- name: 'Jenny',
- id: 'a001'
- },
- {
- name: 'Jerry',
- id: 'a002'
- },
- ]
- }
- render() {
- return (
- <div>
- <ul>
- {
- this.state.student.map(item => {
- // key 是必须的属性, 不然浏览器会抛出错误提示
- return (<li key={item.id}>{item.name}</li>)
- })
- }
- </ul>
- </div>
- )
- }
- }
可能对这个 key 不是太了解, 或者也不许要太深入地去了解它, 只知道在循环渲染组件时, 随手加上这个属性就好. 摘自网上的的文章的总结, key 的作用为
key 的作用主要是为了高效的更新虚拟 DOM
虽然不是很懂, 但也装作大切大悟的样子. key 是一个给框架内部用的, 我们只管给它加上去就好.
Vue 中的 key
同样有一个 vue 的组件:
- <template>
- <div>
- <ul>
- <!-- key 是必须的属性, 不然浏览器会抛出错误提示 -->
- <li v-for="itme in student" :key={item.id}>{{item.name}}</li>
- </ul>
- </div>
- </template>
- <script>
- import vue from 'vue';
- import { Component } from 'vue-property-decorator'
- @Component
- export default calss MainApp extends vue {
- student = [
- {
- name: 'Jenny',
- id: 'a001'
- },
- {
- name: 'Jerry',
- id: 'a002'
- },
- ]
- }
- </script>
同样的, 回到 vue 中的 key, 其实也类似, 解释 key 的作用, 就不得不介绍一下虚拟 DOM 的 diff 算法了... 算了, 我也不是很懂
简单理解就是 react 与 vue 内部判断组件的一个标识, 用于更新或者重用组件的一个重要属性
更新
key 用于更新: 是框架内部的算法实现, 一两句话也说不清楚(主要是我也不懂这个算法), 简单理解为当数据更新了, 框架内部会判断更新页面哪些 DOM 元素需要更新删除等操作;
重用
key 用于组件重用: 其实 key 不止是在 map 或者 v-for 中使用, 我们也也可以在其他组件上使用这个属性(至于哪个组件可以加, 小孩子才做选择, 我们的目标是全都加!), 当然加了貌似也没什么毛病, 只是加了显得有些多余!
在做 SPA 的时候, 我们都会有一个主组件 App.vue:
- <template>
- <div id="app">
- <div>
- <keep-alive>
- <router-view />
- </keep-alive>
- </div>
- </div>
- </template>
- <script>
- import Vue from 'vue'
- import { Component } from 'vue-property-decorator'
- @Component
- export default class MainApp extends Vue {
- }
- </script>
上面代码会把页面全部都缓存下来 (路由切换回来的时候, 页面表单填写的内容没有被清空), 这是应为在 < router-view /> 的外面包裹着 keep-alive 标签, 页面数据都保留下来了, 避免用户切换路由, 数据丢失的情况, 看似很完美!
比如一个产品页面:
当两个路由都使用同一个组件如 Product.vue 这个组件时, 来回切换两个路由, 两个页面填写的东西就会共用! 切换页面时, 发现页面自动填写了上个页面的东西, 这并不是我们想要的!
如果页面比较少, 比如只有 A,B 两个产品, 可以每个页面都定义一个路由地址, 并且 name 属性不一样的值:
- {
- path: '/product',
- name: 'product',
- component: Product,
- children: [
- {
- path: 'a',
- name: 'aProduct',
- component: Detail
- },
- {
- path: 'b',
- name: 'bProduct',
- component: Detail
- },
- ]
- }
这时这样 < router-view :key="$route.name"/>就解决上面的问题了
But, 页面较多的时候, 定义路由就不能像上面这样定义了:
- {
- path: '/product',
- name: 'product',
- component: Product,
- children: [
- {
- path: 'detail/:id',
- name: 'aProduct',
- component: Detail
- },
- ]
- }
此时路由变成了动态的了, 那么, key 就不能取 name 的值了, 此时就需要引入一个变量来存储路由的历史记录了, 当路由切换时, 在历史记录中匹配相应的路由, 在历史记录中保存的一个位置值, 取出来赋值个 key 就可以了
嗯, 前面好像废话有点多, 而且貌似有骗标题的嫌疑, 其实理解 key 这个属性, 对于解决页面缓存, 组件重复不相互影响有重要的作用.
语言表达能力不好, 就当给自己写个笔记吧, 哈哈
来源: https://juejin.im/post/5c6a6276e51d457fd52ee74e