初學vue.js,請問這兩中代碼有什麼很大的區別嗎?
額,你要是這樣子, 這邊建議先不要學vue, 先學好js好不好。
splice 是按索引去操作數組的,id 不一定是數組的索引。其實可以用 findIndex 找出第一個匹配 id 的索引,然後再 splice。
說明你對數組的splice()與some()還沒理解到位.
splice(pos,num,...items) 不講完整功能,只解釋你代碼里的.
第一個參數,表示要刪除數組元素的起始位置.你的id是表示數組索引,還是你列表(list)的條目id(如文章/評論id).是第二種,你就需要通過console下的方法來查詢該item在list的位置.拿到位置(i)後再刪除.
some()/every(),是一種優化策略.
如果用forEach/map等需要遍歷完數組的所有元素,some/every可以提前終止遍歷,不需要循環整個列表.可自己在some/forEach里console.log一下驗證姑且以那行console為分界線,上方的是第一種,下方的是第二種吧.
首先,兩個方式的邏輯是不一樣的,第一種方式認為id這個形參是數組下標,第二種方式認為id是list這個對象數組中每個對象的一個屬性(第二種的可能性更高一些,畢竟這個形參叫id,而不是叫index)
其次第一種方法...看起來傻乎乎的,但確實不嚴格等價於`this.list.splice(id,1);`
splice函數的第一個參數,是可以為負的,且有實際含義,那種複雜的寫法,可以規避掉這種情況(當然,我們一般是不會這麼極端的,因為這個del函數的調用一般也控制在自己手裡.而且即便要考慮邊界情況,也不會這麼寫.)
最後,這個問題跟vue沒有一毛錢關係
最後的最後,下次貼代碼,不要貼張圖片,很不友好,知乎的富文本編輯器是支持粘貼代碼塊的,就像這樣:
for (let i = 0;i &< list.length; i++){
// ...
}
list 的數組用vue 的語法v-for遍歷, del(id)應該傳list的下標index而不是id,直接通過this.list.splice(index,1);沒必要 這麼麻煩 還要通過js的方法找到對應的下標值。
你的理解是正確的, 第一種和第二種實現的功能點不一樣
第一種: for循環中, 找出第`id`個, 然後刪除
簡化一下就是`this.list.splice(id, 1)`
存在的問題: 一般我們不在對數組的循環中進行刪除元素的操作, 可能會導致元素的丟失, 例如:
for(let i = 0, len = this.list.length; i &< len; i++) {
if(i === id) {
this.list.splice(i, 1)
}
}
// 這串代碼會導致刪除一個元素後, 數組長度縮小, 最後一次取值為undefined, 且跳過了刪除的後一個元素
第二種: 使用了函數式編程`some`, 遍歷中刪除元素`id`屬性為`${id}`的元素
這裡使用了`some`+`return true`, 為的是確保只刪除一個元素, 且函數的返回值表示是否刪除了元素
這裡的替代方法有很多種了
// 1. for循環
let delFlag = false
for(let i = this.list.length; i--;) {
if(this.list[i].id === id) {
this.list.splice(i, 1)
delFlag = true
break
}
}
// 2. 要篩選出元素, 最方便的還是filter(此時可能會刪除多個)
this.list = this.list.filter(v =&> v.id === id)
// 3. some, 確保找到第一個符合條件的就終止
this.list.some((v, i) =&> v.id === id this.list.splice(i, 1))
上面的用遍歷的索引值與傳入的id進行比較
下面的用元素的id與傳入的id進行比較
所以這兩段代碼的邏輯是不一樣的
如果元素有5個,遍歷的索引始終是0 1 2 3 4 但是它們的id可能是1 3 5 6 8
當你傳入的id為1或3時,上下代碼都能刪掉元素,但是如果傳入的元素是8,上面的代碼就不起作用了,因為i的值只遍歷到4,但是下面遍歷的是id可以找到8這個值
啥年代的代碼?Array. findIndex()它不香?
map 才是正解
2中寫法都有問題,應該在循環外刪除數據
如果是我我會這樣做
1、const idx =this.list.findIndex(e=&>e.Id===Id)//找出與傳入id相同的下標 if(idx!==-1) this.list.splice(idx,1)2、this.list=this.list.filter(e=&>e.Id!==Id)//直接過濾與傳入的id不相同的list
這個應該是你js基礎不太好,和vue沒啥關係,第一個刪除的是下標為id的元素,第二個是刪除元素的id為id的元素,而且直接循環刪除數組自身的元素不太好,可以直接用filter感覺會好點
如果del函數接收的id就是數組下標的話,
this.list.splice(id,1)和第一種寫法是一樣的效果,
但是你既然說了第一種寫法有bug,第二種沒問題,那我就姑且認為del函數接收的id並不是數組下標,
其實從語義化來講,兩種寫法也都是有些問題的,
一般情況下不會在循環里操作原數組,
some是用來判斷數組中是否有滿足條件項的,
根據你實現的功能來看我覺得這樣寫更合適一些:
// 這種寫法會將數組裡所有id等於傳入id的項過濾掉
function del(id) {
this.list = this.list.filter(item =&> item.id !== id);
}
// 這種寫法和題目中的第二種寫法效果一致
function del(id) {
const index = this.list.findIndex(item =&> item.id === id);
this.list = [
...this.list.slice(0, index),
...this.list.slice(index + 1)
]
}
你應該傳入i 而不是id
什麼意思,那兩種
建議先findIndex 再splice
首先 del 函數傳入的 id 是指什麼?是 list 中元素的屬性,還是直接對應 list 的索引?
如果是說 id 是 list 中元素的屬性,那第一個循環明顯不對,因為是把索引和 id 比較了。
至於提問描述里說的直接 splice id 也是以 id 對應索引為前提的。
推薦閱讀: