一蚯斯、項(xiàng)目需求
用戶登錄后展示條件篩選頁面此再,多層條件篩選何乎,存在單選和多選情況句惯,以及視圖樣式根據(jù)選中情況有相應(yīng)的變,點(diǎn)擊清空按鈕后恢復(fù)初始狀態(tài)支救。效果圖如下:20191215_163317.gif
二抢野、數(shù)據(jù)分析
列表渲染的數(shù)據(jù)部分前端寫死,部分是從后端接口調(diào)雀髂:
// 獲取接口數(shù)據(jù)
mounted () {
let param = {
enableFlag: 'Y',
}
let promise0 = fetchCarBrand(param)
let promise1 = fetchSelectTList('APP.CAR.ENERGY_TYPE')
let promise2 = fetchSelectTList('APP.CAR.DISPLACEMENT')
let promise3 = fetchSelectTList('APP.CAR.CLOUR')
let promise4 = fetchSelectTList('APP.CAR.PASSENGERS')
Promise.all([promise0, promise1, promise2, promise3, promise4]).then(
res => {
console.log(res)
this.carBrandData = res[0].rows
this.newCarBrandData = this.carBrandData.map(item => {
return Object.assign(item, { isPiont: false })
})
this.energyType = res[1].rows
this.displacement = res[2].rows
this.carColor = res[3].rows
this.persons = res[4].rows
}
)
}
(1)三級聯(lián)動(dòng)---以車輛品牌為例:image.png
- dom結(jié)構(gòu):
<!-- 一層列表 -->
<li
:class="{ switch: activeIndex === 1 }"
class="car-model"
@click="handleSwitchLiTwo"
>
<div
:class="{
bluecolor: selectParam.brandList || selectParam.modelList
}"
>
<i
:class="{
bluepoint: selectParam.brandList || selectParam.modelList
}"
/>車輛品牌
</div>
<!-- 二層列表 -->
<ul v-if="isModelShow">
<li
v-for="(item, index) in newCarBrandData"
:key="index"
@click="selectCarModel(item)"
>
<div
:class="{
bluecolor:
selectParam.brandList &&
selectParam.brandList.find(e => e === item.brandId)
}"
>
<i
:class="{
bluepoint: modelMap[item.brandId] && modelMap[item.brandId].length
}"
/>
{{ item.brandName }}
</div>
</li>
</ul>
<!-- 三層列表 -->
<ul v-if="isModel" class="car-model-child">
<li
v-for="(v, i) in newModelData"
:key="i"
:class="{
bluecolor:
modelMap[v.brandId] && modelMap[v.brandId].includes(v.modelId)
}"
@click.stop="handleSelectModel(v)"
>
{{ v.modelName }}
</li>
</ul>
</li>
此處將二層列表和三層列表寫成并列結(jié)構(gòu)指孤,原本寫的是嵌套結(jié)構(gòu),但由于后來屬性控制出現(xiàn)問題,改成了并列結(jié)構(gòu)恃轩。
同時(shí)針對動(dòng)態(tài)類名的控制這里使用的是我點(diǎn)擊選中后生成的條件列表數(shù)組去控制结洼,如果用boolean值就會(huì)有一堆的變量需要在不同階段去改變,很繁瑣叉跛。
首先一層列表的切換通過判斷當(dāng)前點(diǎn)擊下標(biāo)是否等于該元素在列表中的下標(biāo)相等松忍,來控制狀態(tài)。關(guān)于tab切換操作方法可參考vue寫tab切換筷厘。
- 接下來的事件處理才是實(shí)現(xiàn)這個(gè)功能的重點(diǎn):
- 第二級列表的點(diǎn)擊事件
// 品牌選擇
selectCarModel (item) {
this.isModel = true
// 判斷篩選參數(shù)里是否存在該列表屬性鸣峭,若沒有給一個(gè)初始空數(shù)組
if (!this.selectParam.brandList) this.selectParam.brandList = []
// 若存在則先判斷是首次點(diǎn)擊選中還是要再次點(diǎn)擊取消
if (this.selectParam.brandList.indexOf(item.brandId) > -1) {
// 再次點(diǎn)擊取消操作
this.newModelData = [] // 清空第三層列表
// 過濾掉對應(yīng)品牌列表里的當(dāng)前點(diǎn)擊項(xiàng)
this.selectParam.brandList = this.selectParam.brandList.filter(
i => i !== item.brandId
)
} else {
// 點(diǎn)擊選中操作
// 設(shè)置第三層列表項(xiàng)的數(shù)據(jù)
this.newModelData = item.modelList
// 向?qū)?yīng)品牌列表里添加當(dāng)前點(diǎn)擊的品牌id
this.selectParam.brandList.push(item.brandId)
}
// 如果品牌列表為空
if (this.selectParam.brandList.length === 0) {
delete this.selectParam.brandList // 刪除篩選參數(shù)中的品牌列表屬性
this.isModel = false // 隱藏第三層列表
}
this.$forceUpdate() // 強(qiáng)制頁面更新(重點(diǎn))
},
- 第三級列表的點(diǎn)擊事件
其實(shí)實(shí)現(xiàn)該模塊最難得點(diǎn)就在于這第三層列表要與第二層以及第一層列表的關(guān)聯(lián),此處我采用的做法是創(chuàng)建一個(gè)類似Map結(jié)構(gòu)的對象屬性來存選中的數(shù)據(jù)敞掘,利用第三層列表與第二層列表之間的共同的屬性brandId作為屬性,將選中的modelId存到對應(yīng)的brandId中楣铁,每次點(diǎn)擊就判斷該map對象下是否存在該modelId玖雁,存在則過濾掉不存在則添加。當(dāng)某個(gè)brandId為空是則要?jiǎng)h除該屬性盖腕,最終還要將改對象解構(gòu)成數(shù)組拼接到篩選接口的參數(shù)里赫冬。
const mapList = {
brandId1:[modelId1,model2,...],
brandId2:[modelId1,model2,...],
...
}
上代碼:
// 車型選擇
handleSelectModel (item) {
if (!this.selectParam.modelList) this.selectParam.modelList = []
if (!this.modelMap[item.brandId]) this.modelMap[item.brandId] = []
if (this.modelMap[item.brandId].indexOf(item.modelId) > -1) {
this.modelMap[item.brandId] = this.modelMap[item.brandId].filter(
i => i !== item.modelId
)
if (this.modelMap[item.brandId].length === 0) {
delete this.modelMap[item.brandId]
}
} else {
this.modelMap[item.brandId].push(item.modelId)
}
let modelList = Object.values(this.modelMap)
if (modelList.length === 0) {
delete this.selectParam.modelList
} else {
this.selectParam.modelList = [].concat(...modelList)
}
this.$forceUpdate()
},
總結(jié)
當(dāng)拿到一個(gè)復(fù)雜的頁面時(shí)首先要分析業(yè)務(wù)需求理清業(yè)務(wù)邏輯,然后根據(jù)接口數(shù)據(jù)格式去構(gòu)思頁面結(jié)構(gòu)溃列,這樣子寫起來相對輕松一點(diǎn)劲厌。