Web渲染是Web开发中最常用的实战之一。动态列表渲染通常用于简洁友好的格式向用户渲染一系列相似的分组信息。在我们使用的每个Web应用程序中,都可以看到很多内容列表被用于Web应用程序当中。

在这篇文章中,我们将收集有关于Vue中的v-for指令生生动态列表的理解,并通过一些示例来说明为什么在这样做的时候应该使用key属性。

由于我们将在开始编写代码时全面地解释一些事情,本文假设你对Vue或其他JavaScript框架有一定的了解。

案例:Twitter

我将使用 Twitter作为本文的案例。

当登录了Twitter并进入其首页时,我们会看到一个类似下图的一个效果:

在首页上,我们可以看到面页包括了你的趋势,信息列表,推荐关注等模块。在这些列表显示的内容取决于多种因素:Twitter历史,你的关注者和你喜欢的推荐等。因此,我们可以说所有这些数据都是动态的。

尽管这些数据都是动态获取的,但数据显示的方式相同的。这样就可以使用可重用的Web组件。

例如,我们可以将Tweets列表看作是单个的tweet-component组件列表。我们可以把tweet-componet看作是一个Shell,它可以接收各种数据,比如用户外、句柄、tweet和用户头像,以及其他一些片段,它们只是以一致的标记显示这些片段。

假设我们希望从服务器上获取一个大数据用于渲染一个组件列表(例如,tweet-component组件中的列表)。在Vue中,应该首先想到的是v-for指令。

v-for指令

v-for指令用于基于数据源来渲染项目列表。该指令可以在模板元素上使用,并且需要一个特定的语法:

有关于v-for更多的介绍可以点击这里进行了解。

我们来看看这个例子。首先,我们假设我们已经获得一个tweets数据的集合:

const tweets = [

{

id: 1,

name: 'James',

handle: '@jokerjames',

img: 'https://semantic-ui.com/images/avatar2/large/matthew.png',

tweet: "If you don't succeed, dust yourself off and try again.",

likes: 10,

},

{

id: 2,

name: 'Fatima',

handle: '@fantasticfatima',

img: 'https://semantic-ui.com/images/avatar2/large/molly.png',

tweet: 'Better late than never but never late is better.',

likes: 12,

},

{

id: 3,

name: 'Xin',

handle: '@xeroxin',

img: 'https://semantic-ui.com/images/avatar2/large/elyse.png',

tweet: 'Beauty in the struggle, ugliness in the success.',

likes: 18,

}

]

tweets是tweet对象集合,每个tweet包含特定的推特详细信息 —— 一个唯一的标识符、账户名、推特消息等。现在我们尝试使用v-for指令基于这些数据来渲染tweet-component列表。

首先,先创建Vue实例——Vue应用程序的核心。我们把实例挂载到id为app的DOM元素上,并将tweets设置为实例数据对象的一部分。

new Vue({

el: '#app',

data: {

tweets

}

});

现在,我们将创建一个tweet-component组件,通过v-for指令来渲染tweet列表。使用全局的Vue.component构造函数来创建一个名为tweet-component的组件:

Vue.component('tweet-component', {

template: `

{{tweet.name}} {{tweet.handle}}

{{tweet.tweet}}

{{tweet.likes}}

`,

props: {

tweet: Object

}

});

这里有一些有趣的东西值得我们去关注。

tweet-component期望props中的tweet是一个对象(props:{tweet:Object})。如果组件中props的tweet不是一个对象,那么Vue将会发出一个警告信息

使用Mustache语法{{}},将props的tweet对象绑定到组件模板

组件标记与Bulma的Box元素相似,因为它与tweet很类似

在HTML模板中,我们需要把创建的模板挂载到Vue的应用程序中(即,id为app的元素中)。在这个标记中,我们将使用v-for指令来呈现一个tweet列表。因为tweets是我们将要迭代的数据集合,所以tweet将是在指令中使用合适的别名。在每个呈现的tweet-component组件中,将对组件中props的tweet对象做遍历。

不管tweet对象中有多少条信息,我们的设置将总是以我们所期望的相同标记渲染tweet中的每条信息。

添加一些CSS样式之后,我们看到的效果将是这样的:

尽管正如我们所预期的一样,程序能正常运行,但在浏览器的控制台中出现一个Vue的提示信息:

[Vue tip]: : component lists rendered with v-for should have explicit keys...

注意,如果你在Codepen环境下运行此代码,你可能无法看到浏览器控制台报上面的提示信息。

为什么可以按我们预期的运行,但Vue会提示要显式的指定key的值呢?

Key

在使用v-for指令渲染列表,为每个迭代的元素指定一个key属性是很常见的做法。这是因为Vue使用key属性为每个节点的标识创建唯一的绑定。

解释一下。如果我们的列表中有任何动态的UI更改(比如列表项的顺序被打乱),Vue将选择在每个元素中更改数据,而不是相应的移动DOM元素。这在大多数情况下都不是问题。然而,在某此情况下,v-for渲染出来的列表项依赖于DOM状态和(或)子组件状态,这可能会导致一些非预期的渲染效果。

让我们来看一个例子。如果tweet-component组件包含了一个允许用户直接输入消息的字段呢?我们将忽略如何提交信息的响应,并简单地处理新输入字段本身:

把这个新的输入字段添加到tweet-component组件中:

Vue.component('tweet-component', {

template: `

// ...

`,

props: {

tweet: Object

}

});

假设我们想要在我们的应用程序中引入另一个新功能,这个功能包括允许用户随机打乱消息列表。

要做到这一点,我们需要先在HTML模板中添加一个"Shuffle!"按钮。

Shuffle!

我们在按钮元素上添加一个单击事件监听器,在触发时将调用shuffle方法。在我们的Vue实例中需要创建一个shuffle方法,负责在实例中随机打乱tweets集合。我们将使用lodash的_shuffle方法来实现这个功能。

new Vue({

el: '#app',

data: {

tweets

},

methods: {

shuffle() {

this.tweets = _.shuffle(this.tweets)

}

}

});

来试试效果。如果我们点击shuffle按钮几次,我们会注意到,我们的tweet列表元素会被随机分类。

但是,如果我们在每个组件的input中输入一些信息,然后单击shuffle按钮,我们会发现有一些奇怪的事情发生,而且超出我们所预期的效果:

由于我们没有使用key属性,Vue并没有为每个tweet节点创建唯一的绑定。因此,当我们打算重新对tweets排序时,Vue采用了更有效的,更节省的方法简单地在对每个元素进行数据的更改(或修补)。由于临时的DOM状态(即输入的文本)仍然存在,造成给我们的体验就如上图所示的效果一样,文本出现意外的匹配。

下图向我们展示了对每个元素和仍然存在的DOM状态进行数据的修补:

为了避免这种情况,我们不得不为tweet-component组件渲染出来的每个列表项绑定一个key值。我们将使用tweet的id作为唯一标识符,更安全地说,tweet的id不应该等于另一个tweet的id。因为我们使用的是动态值,所以我们将使用v-bind指令将我们的key绑定到tweet.id:

Shuffle!

现在,Vue识别每个tweet的节点的标识。因此,当我们打算对列表进行调整时,将重新对组件进行排序。

由于tweet-component组件中的每个列表项都被相应的移动,因此我们可以使用Vue的transition-group功能把元素重新排序的效果做得更好一些。

为此,我们将把transition-group元素添加到v-for列表中。我们将指定tweets的过渡名称,并声明transition-group应该做为div元素渲染。

Shuffle!

基于过渡的名称,Vue将自动识别是否已指定了CSS的transition或animation。因为我们的目标是调用列表中项目移动时,Vue将会指定CSS的过渡名称tweets-move(给transition-group的名称tweets)。因此,我们将手动引入一个具有指定类型和过渡时间的.tweets-move的类:

#app .tweets-move {

transition: transform 1s;

}

这只是一个简单的效果。如果要应用更复杂的列表过渡效果,就需要阅读Vue的文档,这样可以了解关于Vue中所有不同类型过渡的详细信息。

当调用shuffle时,tweet-component元素将在位置移动时有一个过渡的效果。试一试!在input中输入一些信息,然后多单击几次"Shuffle!"按钮几次。

很酷,对吧?如果没有key属性,就不能使用transition-group元素来创建列表过渡效果,因为元素是修补的而不是被重新排序的。

是否应该始终使用key属性呢?并非如此,Vue文档推荐只有满足下面的情况之下才使用key属性:

出于性能考虑,我们有意地希望使用默认的修补元素的方式

DOM内容非常简单

总结

希望文章描述了v-for指令是如何有用的,并提供了更多的上下文来解释为什么在v-for指令中要使用key属性。如果你有任何想法,或者上文中有任何不对之处,欢迎在下面的评论中指出来。

常用昵称“大漠”,W3CPlus创始人,目前就职于手淘。对HTML5、CSS3和Sass等前端脚本语言有非常深入的认识和丰富的实践经验,尤其专注对CSS3的研究,是国内最早研究和使用CSS3技术的一批人。CSS3、Sass和Drupal中国布道者。2014年出版《图解CSS3:核心技术与案例实战》。

vue列表渲染中key的作用_列表渲染和Vue的v-for指令相关推荐

  1. 26.Vue列表渲染中key的作用与原理(内含虚拟DOM的对比算法详解)

    目录 1.暴露问题,使用index作为key 2.使用唯一标识p.id作为key 3.不写key的配置 4.key的工作原理及虚拟DOM的对比算法 5.总结 25.Vue列表渲染_爱米酱的博客-CSD ...

  2. vue列表渲染中key的作用_vue中:key的作用

    因为不理解 :key(v-bind:key),网上查了一些的资料,这篇写得非常不错,很简洁清楚. 其实不只是vue,react中在执行列表渲染时也会要求给每个组件添加上key这个属性. 要解释key的 ...

  3. 列表渲染 wx:key 的作用、条件渲染 wx:if 与 hidden 的区别

    这是微信小程序踩坑系列的第三篇,想要了解更多关于微信小程序开发的那些事,欢迎关注我的<微信小程序>专栏. 前言 开发微信小程序离不开"页面渲染",对于初学者来说很难理解 ...

  4. 5渲染判断_Vue页面渲染中key的应用实例教程

    引言 在前端项目开发过程中,el-table展示的结果列使用组件形式引入,其中某些字段通过:formatter方法转码,结果栏位的字段显示/隐藏控制也使用组件形式引入,前端在控制字段显示属性时,发现码 ...

  5. 【Vue】中Key的作用

    Vue中key的作用 虚拟DOM 虚拟DOM 本质上是一个js对象 ,通过对象来表示真实的DOM结构. key是虚拟DOM对象的标识,当状态中的数据发生变化时,Vue会根据 新数据 生成 新的虚拟DO ...

  6. 【Day08】请简述虚拟 DOM 中 Key 的作用和好处

    请简述虚拟 DOM 中 Key 的作用和好处 官网地址:https://cn.vuejs.org/v2/api/#key key 的作用 key 的特殊 attribute 主要用在 Vue 的虚拟 ...

  7. 渲染农场优势是什么_云渲染农场怎么用?

    在回答渲染农场的优势这个问题之前,我先申明一下本文中提到的渲染农场/云渲染平台/云渲染农场,都特指CG领域内的专业3D渲染平台,有一些文章会强调这个叫法的区别,但是业内一般都不会分这么细,所以也就不赘 ...

  8. vue 相同的id不合并_vue中key的作用

    摘要 本文结合源码说明了key的作用,给出了一个不写key的反例,并分析了原因. 内容 key的作用 不写key会出的bug及原因分析 key的实践方案 key的作用 在数据变化前后,vue会得到两个 ...

  9. vue中key的作用及案例

    1.key的作用 假设现在有一个需求,在页面循环data中的数组. <div id="app"><ul><li v-for="(item, ...

最新文章

  1. 【软件差错警示钟】一起软件差错造成的多名病人死亡事故
  2. python环境搭建_搭建Python编程环境
  3. Linux--vim的使用
  4. BZOJ 2301 [HAOI2011]Problem b
  5. 什么电脑的牌子好用_你觉得电脑好用还是手机好用?为什么?
  6. linux 密码复杂度,用PAM 搞定Linux 平台密码复杂度问题
  7. Python学习第一天-第2节
  8. meshgrid 的使用方法
  9. 【转】贝叶斯网络+马尔科夫毯 简介
  10. iBATIS date MySQL_LocalDateTime与mysql日期类型的交互(基于mybatis)
  11. python django框架 比php_django 第一感觉对比 php 各大框架
  12. 深入理解React、Redux
  13. SQL Server 2012 下载与安装详细教程
  14. 数电技术基础大恶补05:TTL门电路
  15. Mathematica 分段函数 求导 求积分
  16. Selenium 入门篇
  17. 2022年山东省熔化焊接与热切割作业(特种上岗操作证)模拟试题及答案
  18. 【AR】AR 的几种底层实现方式
  19. 高速数据采集卡“王牌”对“王牌”
  20. Web前端:2022年最佳Javascript动画库

热门文章

  1. PCIe(peripheral component interconnect express)
  2. (七)集成学习中-投票法Voting
  3. 小学生python游戏编程arcade----基本知识1
  4. 吸血鬼 hrbust 1160 并查集
  5. 谷歌seo快速排名优化方法?谷歌seo排名技巧
  6. 一年中重要的节日列表_一年中最重要的节日分别是?
  7. 芯片市场低迷 SK海力士Q1利润大跌69%
  8. Windows ❀ 使用CMD配置或修改IP地址与DNS命令
  9. 应急响应常用命令(Linux)---读书笔记
  10. 未来的全能保姆机器人作文_保姆机器人作文300字共5篇