终于轮到迴圈了(其实也才刚开始三篇而已XD)!说到迴圈大家一定不陌生,除了最初的起点Hello!world!
以外,应该就是九九乘法表了,那当迴圈融入前端框架时,会迸出什么火花,让我们来看看吧!
迴圈
一、for的使用方法
在上一篇文章中大家都知道Vue.js中的if
写作v-if
,那for
呢?
是v-for
吗?
没错!就是v-for
!直接来看用法吧:
<div id="todoList"> <div v-for="list in lists"> {{list.item}} </div></div>
JavaScript
let listData = { //lists属性中存着阵列 lists:[ //阵列中拥有多个相同key的物件 {item:'学Vue.js'}, {item:'学React'}, {item:'学Angular2'} ]}let todoList = new Vue({ el:'#todoList', data:listData,})
这一次从JavaScript
的部分先说,首先像平常一样定义一个listData
物件,可以看到里面有一个纪录阵列的lists
,阵列里面的内容则是一个个拥有相同key
的物件,差别是值不一样,而我们new的Vue物件抓取外层的div
,让该div
的内容都可以绑定listData
的资料。
好的,那再来是HTML
的部分,我们把v-for
写在内层,里面的值是list in lists
这里的语法和JavaScript
一样,v-for
会将lists
也就是listData
中的阵列资料一个一个读取并把值放进list
中,再往更里面看一点,内层的div
目前绑定的资料是list.item
也就是lists
中每一个物件的item
值,所以设定了v-for
的div
会被迴圈重覆输出,唯一会变的只有{{list.item}}
的值而已,来看看绑定后的结果吧!
登愣!原本只有一个的div
也变成了三个,而且里面的值也都被绑定item
了!
当然,只要是在data
中的资料,就算没在lists
里也可以绑定,而且很贴心的是,v-for
还可以有第二个参数,来纪录目前是阵列中的第几项:
HTML
<div id="todoList"> <!--在这里增加了第二个参数index,记得两个参数以上要用括号--> <div v-for="(list,index) in lists"> {{index}}.{{titleText}} - {{list.item}} </div></div>
JavaScript
//增加一个titleText属性let listData = { titleText:'要做的事情', lists:[ {item:'学Vue.js'}, {item:'学React'}, {item:'学Angular2'} ]}
HTML
中为v-for
增加了第二个参数,他会记录着目前是阵列中的第几个索引,记得索引值都是从0开始哦!除此之外我也在JavaScript
中的listData
增加了一的属性titleText
,执行他吧!
内容就分别是索引的index
加上listData
的titleText
还有lists
的item
,这边特别的是字串的组合不需要使用加号,不过说不定其他前端框架也是这样,因为小弟碰过的框架目前只有Vue.js,所以可以请板上大大们留言分享一下XD,那我们继续下去吧!
二、免不了提一下效能问题吧
其实v-for
和v-if
会遇到的问题一样,没办法本是同根身,总会有些习惯相同,就是为了效能,v-for
会在我们调整lists
顺序的时候只对不同的地方做替换而已,我们把今天学到的v-for
用法加进昨天的例子里来看这个状况:
HTML
<div id="formList"> <div v-for="list in lists"> {{titleText}}{{list.item}}: <!--用第一天学到的v-bind绑定placeholder属性为list.item的值--> <input :placeholder="list.item"> </div> <!--昨天是切换输入,今天是反转阵列--> <input type="button" value="反转阵列" @click="changeSort"></div>
JavaScript
let listData = { titleText:'请输入', lists:[ {item:'姓名'}, {item:'信箱'}, {item:'电话'} ]}let listMethods = { changeSort: () => { //反转阵列 listData.lists.reverse() }}let formList = new Vue({ el:'#formList', data:listData, methods:listMethods,})
Vue.js处理过的画面会如下:
看起来也满像样的,对吧?不过这不是重点,让我们来看看以下操作:
我先在第一个input
输入姓名,之后反转阵列lists
中的元素,Vue.js的动态绑定资料会迅速的刷新画面,原本第一个的姓名跑到最后一个,电话跑到第一个,但是有没有一个强烈的既视感,那就是input
的value
值还在啊!因为Vue.js不会重新绘製,而是只刷新了原本input
不同的地方,也就是placeholder
。好的,既然问题发生了,还是得解决,想想昨天v-if
的处理方式,怎么办呢?
设定key
吗?
对!就是他!不过设定方法和昨天稍微有点不同,我们必须用v-bind
的方式去绑定key
值,像下方这样:
HTML
<div id="formList"> <div v-for="list in lists"> {{titleText}}{{list.item}}: <!--增加v-bind设定key值--> <input :placeholder="list.item" :key="list.id"> </div> <input type="button" value="反转阵列" @click="changeSort"></div>
JavaScript
let listData = { titleText:'请输入', //为lists中的各个物件加上id lists:[ {id:'name',item:'姓名'}, {id:'mail',item:'信箱'}, {id:'tel',item:'电话'} ]}
HTML
的部分就像上面说的,用v-bind
绑定一个key
属性,他的值是list.id
,所以在JavaScipt
中要记得在listData
中的lists
中的物件加入id
的资料,加上key
值的他们,如果重新绑定就会进行重新绘製了!
然而因为重新绘製的关係,所以一反转阵列内容,我们输入过的value
自然就不见啦!而官方文件上面也有说建议大家在使用v-for
的时候,除非是有特殊原因需要刻意的让效能提升,不然都尽量绑定key
属性。
三、阵列的异动方式
以下先用上方加入key
的程式码下去说明,重複的部分就不会再打上去了!
首先是增加的push()
增加项目非常简单,直接对listData
内的lists
做push()
,Vue.js就会帮你处理好剩下的事情!
再来是移除的splice()
移除和增加一样,直接对listData
的lists
下splice()
就可以了。
这边我补充一下splice()
的用法,上面我用在移除的时候给他两个参数listData.lists.splice(3,1)
,因为前一次我在lists
中push()
了age
;age
在阵列中的索引为3,所以就是从第3个索引开始移除掉1个,也就是把age
给移除。
循序渐进的替换资料来源
JavaScript
有许多操作阵列的function
,但并不是所有function
都会改变原有的阵列内容,有些是回传新的阵列,例如官网举例筛选资料用的filter()
、合併两个阵列的concat()
或是截取阵列内容的slice()
,怎么办?
其实很简单,非常非常简单,就把处理后的资料指定回去而已。这边我以concat()
说明,其他两个方式的做法也一样。
conosle的第一行我先新增另一个阵列arr1
,之后用concat()
把data
的lists
阵列和arr1
做合併,但是concat()
不会异动原本的lists
,所以我在同时也把他指定回去。
最后的注意事项
当想要调整lists
中第二个索引的值时,千千万万别这么做listData.lists[2] = {id:'test',item:'测试'}
,这样会让Vue.js无法动态刷新画面,解套方法当然是有,可以改成Vue.set(list, index, value)
让Vue.js刷新,以下範例:
小补充一下,上图中的语法也可以用Vue.js的全域方法
$set
写成这样:formList.$set(listData.lists, 2, {id:'test',item:'测试'})
透过设定阵列长度减少元素listData.lists.length = 2
,也不会被Vue.js抓到哦!如果要移除元素,请使用上面提到的splice()
来做处理。刚刚打完文章,顺手看了一下Vue.js官方文件的目录,突然觉得未来的路还好长XD,不过相信It这条路不孤单,大家都会一起走下去的对吧!哈哈哈。
最后感谢各位大大的观看,如果文章中有任何错误或是讲解不清楚的部分,还请留言告诉我,我会尽快修正!谢谢大家