一,場景
通過使用checkbox,實現如圖的場景, 點擊某個tag,實現選中和非選中狀態。

二, 官網的例子
通過切換checked值為true或者false來實現,一個checkbox的狀態切換
<template>
<!-- `checked` 為 true 或 false -->
<el-checkbox v-model="checked">備選項</el-checkbox>
</template>
<script>
export default {
data() {
return {
checked: true
};
}
};
</script>
效果如下:

三, 思考。
通過循環li, 給數據添加checked屬性,並綁定到v-model上,來實現 一的場景。模板代碼如下:
<template>
<div class="demo">
<ul>
<li v-for="(item, index) in list" :key="index"> //循環li
<el-checkbox v-model="item.checked"> //v-model綁定到每個item的checked屬性
{{ item.name }}
</el-checkbox>
</li>
</ul>
</div>
</template>
后台返回數據格式(已精簡),如下(沒有checked屬性)
[
{ id: 1, pid: 1, name: '地區' },
{ id: 2, pid: 2, name: '游戲類型' },
{ id: 3, pid: 4, name: '性別' },
{ id: 4, pid: 5, name: '設備類型' },
{ id: 5, pid: 6, name: '休閑時間' },
{ id: 6, pid: 7, name: '王者榮耀' },
{ id: 7, pid: 8, name: '音樂' },
{ id: 8, pid: 9, name: '品牌手表' },
{ id: 9, pid: 10, name: '相機' },
{ id: 10, pid: 12, name: '游戲人群' },
]
我要做的, mounted方法獲取后台數據,再給每條數據循環添加checked屬性,初始值為false。
<script>
export default {
name: 'demo',
data() {
return {
list: [],
allTags: [],
}
},
methods: {
getList() {
//獲取數據用settimeout模擬
setTimeout(() => {
this.allTags = [
{ id: 1, pid: 1, name: '地區' },
{ id: 2, pid: 2, name: '游戲類型' },
{ id: 3, pid: 4, name: '性別' },
{ id: 4, pid: 5, name: '設備類型' },
{ id: 5, pid: 6, name: '休閑時間' },
{ id: 6, pid: 7, name: '王者榮耀' },
{ id: 7, pid: 8, name: '音樂' },
{ id: 8, pid: 9, name: '品牌手表' },
{ id: 9, pid: 10, name: '相機' },
{ id: 10, pid: 12, name: '游戲人群' },
]
this.allTags.map(item => {
item.checked = false
return item
})
this.list = this.allTags
}, 1500)
},
},
mounted() {
this.getList()
},
}
</script>
到這以為實現了功能,看效果發現問題: 點擊時候,沒有勾上,只有框變了顏色。

排查問題.....
(腦補痛苦過程......)
猜測:
1,element不支持這種方法綁定,只能按官網例子中,循環el-checkbox來實現。
2,vue綁定問題
針對問題1: 換成了循環el-checkbox,發現結果是一樣的不行。 否定!
剩下的就是猜測二:
人為把返回數據默認加上checked屬性, 即data格式為:
[
{ id: 1, pid: 1, name: '地區', checked: false},
{ id: 2, pid: 2, name: '游戲類型' , checked: false},
{ id: 3, pid: 4, name: '性別' , checked: false},
{ id: 4, pid: 5, name: '設備類型' , checked: false},
{ id: 5, pid: 6, name: '休閑時間' , checked: false},
{ id: 6, pid: 7, name: '王者榮耀', checked: false },
{ id: 7, pid: 8, name: '音樂', checked: false },
{ id: 8, pid: 9, name: '品牌手表' , checked: false},
{ id: 9, pid: 10, name: '相機' , checked: false},
{ id: 10, pid: 12, name: '游戲人群' , checked: false},
]
測試發現,這樣可以。
迷茫。。。
然后在控制台打印數據,對比了一下結果。
前端添加checked屬性的情況 和 后台返回數據本來就有checked屬性情況 打印出來分別如 1 和 圖2

圖1 圖2
對比一下發現,前端添加checked屬性, vue並沒有添加get set方法,因此,監聽不到checked值變化,進而不能更新view。這點,可以在瀏覽器vue調試中看到,點擊時候 數據的checked屬性 true和false是在交替變化,但是view上沒同步更新。截了個圖

四,解決方法
兩種方法,
1, 拿到值不賦值給data屬性的allTags,而是定義臨時變量let, 操作完之后,賦值給list,即:
<script>
export default {
name: 'demo',
data() {
return {
list: [],
}
},
methods: {
getList() {
//獲取數據用settimeout模擬
setTimeout(() => {
let allTags = [ //這里let定義allTags
{ id: 1, pid: 1, name: '地區' },
{ id: 2, pid: 2, name: '游戲類型' },
{ id: 3, pid: 4, name: '性別' },
{ id: 4, pid: 5, name: '設備類型' },
{ id: 5, pid: 6, name: '休閑時間' },
{ id: 6, pid: 7, name: '王者榮耀' },
{ id: 7, pid: 8, name: '音樂' },
{ id: 8, pid: 9, name: '品牌手表' },
{ id: 9, pid: 10, name: '相機' },
{ id: 10, pid: 12, name: '游戲人群' },
]
allTags.map(item => {
item.checked = false
return item
})
this.list = allTags
}, 1500)
},
},
mounted() {
this.getList()
},
}
</script>
2(推薦),用vue.$set方法,強制vue監聽checked屬性
<script>
export default {
name: 'demo',
data() {
return {
list: [],
}
},
methods: {
getList() {
//獲取數據用settimeout模擬
setTimeout(() => {
this.allTags = [ //這里let定義allTags
{ id: 1, pid: 1, name: '地區' },
{ id: 2, pid: 2, name: '游戲類型' },
{ id: 3, pid: 4, name: '性別' },
{ id: 4, pid: 5, name: '設備類型' },
{ id: 5, pid: 6, name: '休閑時間' },
{ id: 6, pid: 7, name: '王者榮耀' },
{ id: 7, pid: 8, name: '音樂' },
{ id: 8, pid: 9, name: '品牌手表' },
{ id: 9, pid: 10, name: '相機' },
{ id: 10, pid: 12, name: '游戲人群' },
]
this.allTags.map(item => {
//item.checked = false
this.$set(item, 'checked', false) // 這里,給對象添加屬性,用$set方法。
return item
})
this.list = this.allTags
}, 1500)
},
},
mounted() {
this.getList()
},
}
</script>
done!!
五,總結。
這個問題是我在項目中遇到的問題,通過一步一步鎖定問題之后,抽出來做了最精簡版本,故做此總結,也給其他遇到坑的童鞋一點點幫助。
ps,每次用element ui 都會有一些感觸,苦笑。
