vue商城中商品“篩選器”功能的實現代碼
在使用vue搭建商城項目的時候,要實現一個商品篩選器的功能,在完成之后,再一次被vue的數據驅動的強大感到震撼!
首先,我們來看一下具體的需求吧。你可以先看下面的這兩張圖,然后再看文字描述,可能會更容易理解。

沒有觸發(fā)時的狀態(tài)

觸發(fā)后的狀態(tài)
我們需求有下面幾點:
1、默認情況下,只顯示一級菜單,二級菜單不顯
2、存在二級菜單的情況下,在二級菜單沒有顯示的情況下,點擊一級菜單,一級菜單的樣式發(fā)生改變,二級菜單不顯示
3、存在二級菜單的情況下,一級菜單已經點擊過之后,再點擊一級菜單,會顯示二級菜單
我們舉例子說明一下,當前的一級菜單有默認、有貨優(yōu)先、直營優(yōu)先,只有默認是含有二級菜單的,比如現在焦點在有貨優(yōu)先上面,那么我們點擊默認的時候,不會彈出默認下面的二級菜單,只會改變一級菜單默認的樣式(字體和三角形的顏色),當再次點擊一級菜單默認的時候,其下面的二級菜單就顯示出來了。
需求分析完成后,我們開始編寫代碼吧。
一、創(chuàng)建篩選器數據結構
跟以前的開發(fā)方式不同,我們首先要創(chuàng)建數據結構,而不是編寫模版代碼。
1、設置篩選器數據結構
// 數據源
optionsDatas: [
{
id: '1',
name: '默認',
subs: [
{
id: '1',
name: '默認',
},
{
id: '1-2',
name: '價格由高到低',
},
{
id: '1-3',
name: '銷量由高到低',
},
]
},
{
id: '2',
name: '有貨優(yōu)先',
subs: []
},
{
id: '3',
name: '直營優(yōu)先',
subs: []
}
]
這個數據結構設計得是非常出彩的,此處您可能還看不到,在下面具體的應用中你就能感覺到它的優(yōu)美呢。
2、設置二級菜單(選中項subs)的數據結構
// 選中的篩選項
selectOption: {},
// 是否展開子篩選項
sShowSubContent: false
當然,我們要在created鉤子函數中對selecOption進行賦值操作,保證其具有初始值。
created: function () {
// 設置初始選中項
this.selectOption = this.optionsDatas[0];
}
二、設置模版代碼
下面是完整模版代碼,內容相對比較多,我們按照功能逐塊進行講解吧。
<div class="goods-options z-index-2">
<ul class="goods-options-list">
<li class="goods-options-item" v-for="(item, index) in optionsDatas" :key="index">
<a class="goods-options-item-content" @click="onOptionsItemClick(item, index)">
<span class="goods-options-item-content-name" :class="{'goods-options-item-content-name-active' : selectOption.id === item.id}">{{item.name}}</span>
<span class="goods-options-item-content-caret caret" v-if="item.subs.length > 0"
:class="[isShowSubContent && selectOption.id === item.id ? 'goods-options-item-content-caret-open' : 'goods-options-item-content-caret-close']"
></span>
</a>
</li>
</ul>
<transition name="fold-height">
<div class="options-sub-content z-index-2" v-show="isShowSubContent">
<ul class="options-sub-content-list">
<li class="options-sub-content-list-item" v-for="(item, index) in selectOption.subs" :key="index" @click="onSubOptionsItemClick(item, index)">
<a class="options-sub-content-list-item-content">
<span class="options-sub-content-list-item-content-name" :class="{'options-sub-content-list-item-content-name-active' : selectOption.id === item.id}">{{item.name}}</span>
<img class="options-sub-content-list-item-content-select" v-show="selectOption.id === item.id" src="@img/options-select.svg" alt="" srcset="">
</a>
</li>
</ul>
</div>
</transition>
<div class="cover" v-show="isShowSubContent" @click="isShowSubContent = false"></div>
</div>
1、渲染一級菜單
<ul class="goods-options-list">
<li class="goods-options-item" v-for="(item, index) in optionsDatas" :key="index">
<a class="goods-options-item-content" @click="onOptionsItemClick(item, index)">
<span class="goods-options-item-content-name" :class="{'goods-options-item-content-name-active' : selectOption.id === item.id}">{{item.name}}</span>
<span class="goods-options-item-content-caret caret" v-if="item.subs.length > 0"
:class="[isShowSubContent && selectOption.id === item.id ? 'goods-options-item-content-caret-open' : 'goods-options-item-content-caret-close']"
></span>
</a>
</li>
</ul>
1.1、一級菜單的樣式變化
一級菜單的文字顏色的變化需要滿足下面的規(guī)則,也就是selectOption.id === item.id。也就是說在當選中是一級菜單是默認的時候,我們就要其文字顏色改編成紅色。
:class="{'goods-options-item-content-name-active' : selectOption.id === item.id}"
相應地,三角形的顏色和箭頭的朝向也需要進行更改。更改的邏輯如下。當然,如果一級菜單沒有對應的二級菜單時,三角形就不應該顯示。
:class="[isShowSubContent && selectOption.id === item.id ? 'goods-options-item-content-caret-open' : 'goods-options-item-content-caret-close']"
v-if="item.subs.length > 0"
1.2、一級菜單的點擊事件onOptionsItemClick(item, index)實現的主要功能是改變一次菜單的樣式和二級菜單的顯示/隱藏。具體的功能如下分析所示:
1、如果子選項視圖處于展開狀態(tài),則關閉掉子選項視圖
2、展示子選項視圖
2.1、選中項包含子選項
2.2、當前篩選項處于選中狀態(tài)
3、設置選中項為用戶點擊的選項
onOptionsItemClick: function (item, index) {
// 如果子選項視圖處于展開狀態(tài),則關閉掉子選項視圖
if (this.isShowSubContent) {
this.isShowSubContent = false;
return;
}
// 1、選中項包含子選項
// 2、當前篩選項處于選中狀態(tài)
// 展示子選項視圖
if (item.subs.length > 0 && this.selectOption.id === item.id) {
this.isShowSubContent = true;
}
// 設置選中項為用戶點擊的選項
this.selectOption = item;
}
2、渲染二級菜單
<transition name="fold-height">
<div class="options-sub-content z-index-2" v-show="isShowSubContent">
<ul class="options-sub-content-list">
<li class="options-sub-content-list-item" v-for="(item, index) in selectOption.subs" :key="index" @click="onSubOptionsItemClick(item, index)">
<a class="options-sub-content-list-item-content">
<span class="options-sub-content-list-item-content-name" :class="{'options-sub-content-list-item-content-name-active' : selectOption.id === item.id}">{{item.name}}</span>
<img class="options-sub-content-list-item-content-select" v-show="selectOption.id === item.id" src="@img/options-select.svg" alt="" srcset="">
</a>
</li>
</ul>
</div>
</transition>
2.1、二級菜單樣式的變化
二級菜單的樣式變化需要滿足下面的規(guī)則。這個規(guī)則基本上跟一級菜單的一致。
:class="{'options-sub-content-list-item-content-name-active' : selectOption.id === item.id}"
對于右側的對勾,需要符合下面的邏輯。
v-show="selectOption.id === item.id"
2.2、二級菜單的點擊事件onSubOptionsItemClick(item, index),這個事件需要實現功能如下:
1、設置選中項為用戶點擊的選項
2、將選中項置頂
3、關閉子選項視圖
onSubOptionsItemClick: function (subItem, index) {
// 遍歷所有的可選項,將選中項置頂
this.optionsDatas.forEach(options => {
options.subs.forEach (subOptions => {
if (subOptions.id === subItem.id) {
options.id = subOptions.id;
options.name = subOptions.name;
}
})
});
// 關閉子選項視圖
this.isShowSubContent = false;
}
2.3、二級菜單動畫的實現
二級菜單動畫的實現,我們采用了vue的過度動畫。其使用到的css動畫如下:
/**
子選項內容區(qū)展開動畫,當 v-if=“true” 的時候調用
當子選項部分展開時,初始狀態(tài)max-height為0,結束狀態(tài)max-height為180
*/
.fold-height-enter-active {
animation-duration: .3s;
animation-name: fold-height-open;
}
@keyframes fold-height-open {
0% {
max-height: 0;
}
100% {
max-height: px2rem(180);
}
}
/**
子選項內容區(qū)關閉動畫,當 v-if=false 的時候調用
當子選項部分關閉時,初始狀態(tài)max-height為180,結束狀態(tài)max-height為0
*/
.fold-height-leave-active {
animation-duration: .3s;
animation-name: fold-height-close;
}
@keyframes fold-height-close {
0% {
max-height: px2rem(180);
}
100% {
max-height: 0;
}
}
2、遮罩的顯示/隱藏
最后就剩下一個遮罩的樣式和邏輯了,這個比較簡單,其邏輯如下:此處不在進行多余的解釋。
<div class="cover" v-show="isShowSubContent" @click="isShowSubContent = false"> </div>
至此,我們所有的邏輯分析和代碼實現都已完成。設計的最巧妙的就是這個數據結構,完全滿足了我們業(yè)務需求。在下面是完整的代碼,希望對您有用。
<template>
<div class="goods-options z-index-2">
<ul class="goods-options-list">
<li class="goods-options-item" v-for="(item, index) in optionsDatas" :key="index">
<a class="goods-options-item-content" @click="onOptionsItemClick(item, index)">
<span class="goods-options-item-content-name" :class="{'goods-options-item-content-name-active' : selectOption.id === item.id}">{{item.name}}</span>
<span class="goods-options-item-content-caret caret" v-if="item.subs.length > 0"
:class="[isShowSubContent && selectOption.id === item.id ? 'goods-options-item-content-caret-open' : 'goods-options-item-content-caret-close']"
></span>
</a>
</li>
</ul>
<transition name="fold-height">
<div class="options-sub-content z-index-2" v-show="isShowSubContent">
<ul class="options-sub-content-list">
<li class="options-sub-content-list-item" v-for="(item, index) in selectOption.subs" :key="index" @click="onSubOptionsItemClick(item, index)">
<a class="options-sub-content-list-item-content">
<span class="options-sub-content-list-item-content-name" :class="{'options-sub-content-list-item-content-name-active' : selectOption.id === item.id}">{{item.name}}</span>
<img class="options-sub-content-list-item-content-select" v-show="selectOption.id === item.id" src="@img/options-select.svg" alt="" srcset="">
</a>
</li>
</ul>
</div>
</transition>
<div class="cover" v-show="isShowSubContent" @click="isShowSubContent = false"></div>
</div>
</template>
<script>
export default {
data: function () {
return {
// 數據源
optionsDatas: [
{
id: '1',
name: '默認',
subs: [
{
id: '1',
name: '默認',
},
{
id: '1-2',
name: '價格由高到低',
},
{
id: '1-3',
name: '銷量由高到低',
},
]
},
{
id: '2',
name: '有貨優(yōu)先',
subs: []
},{
id: '3',
name: '直營優(yōu)先',
subs: []
}
],
// 選中的篩選項
selectOption: {},
// 是否展開子篩選項
isShowSubContent: false
}
},
created: function () {
// 設置初始選中項
this.selectOption = this.optionsDatas[0];
},
methods: {
/**
* 1、如果子選項視圖處于展開狀態(tài),則關閉掉子選項視圖
* 2、展示子選項視圖
* 1、選中項包含子選項
* 2、當前篩選項處于選中狀態(tài)
* 3、設置選中項為用戶點擊的選項
*/
onOptionsItemClick: function (item, index) {
// 如果子選項視圖處于展開狀態(tài),則關閉掉子選項視圖
if (this.isShowSubContent) {
this.isShowSubContent = false;
return;
}
// 1、選中項包含子選項
// 2、當前篩選項處于選中狀態(tài)
// 展示子選項視圖
if (item.subs.length > 0 && this.selectOption.id === item.id) {
this.isShowSubContent = true;
}
// 設置選中項為用戶點擊的選項
this.selectOption = item;
},
/**
* 1、設置選中項為用戶點擊的選項
* 2、將選中項置頂
* 3、關閉子選項視圖
*/
onSubOptionsItemClick: function (subItem, index) {
// 設置選中項為用戶點擊的選項
// this.selectOption = subItem;
// 遍歷所有的可選項,將選中項置頂
this.optionsDatas.forEach(options => {
options.subs.forEach (subOptions => {
if (subOptions.id === subItem.id) {
options.id = subOptions.id;
options.name = subOptions.name;
}
})
});
// 關閉子選項視圖
this.isShowSubContent = false;
},
},
watch: {
/**
* 當選擇項發(fā)生變化的時候,需要通知父組件
*/
selectOption: function (newValue, oldValue) {
this.$emit('optionsChange', newValue);
}
}
}
</script>
<style lang="scss" scoped>
@import '@css/style.scss';
.goods-options {
width: 100%;
border-bottom: 1px solid $lineColor;
&-list {
display: flex;
width: 100%;
height: $goodsOptionsHeight;
background-color: white;
.goods-options-item {
flex-grow: 1;
&-content {
height: 100%;
display: flex;
justify-content: center;
align-items: center;
&-name {
font-size: $infoSize;
margin-right: $marginSize;
&-active{
color: $mainColor;
}
}
// 子選項展開時,三角形的動畫
&-caret {
&-open {
transform:rotate(-180deg);
transition: all .3s;
}
&-close {
transform:rotate(0deg);
transition: all .3s;
}
}
}
}
}
// 子選項內容區(qū)
.options-sub-content {
// 脫離標準文檔流
position: absolute;
width: 100%;
max-height: px2rem(180);
overflow: hidden;
overflow-y: auto;
background-color: white;
&-list {
&-item {
&-content {
display: flex;
align-items: center;
border-top: 1px solid $lineColor;
padding: $marginSize;
height: px2rem(44);
box-sizing: border-box;
&-name {
font-size: $infoSize;
display: inline-block;
flex-grow: 1;
&-active{
color: $mainColor;
}
}
&-select {
width: px2rem(18);
height: px2rem(18);
}
}
}
}
}
/**
子選項內容區(qū)展開動畫,當 v-if=“true” 的時候調用
當子選項部分展開時,初始狀態(tài)max-height為0,結束狀態(tài)max-height為180
*/
.fold-height-enter-active {
animation-duration: .3s;
animation-name: fold-height-open;
}
@keyframes fold-height-open {
0% {
max-height: 0;
}
100% {
max-height: px2rem(180);
}
}
/**
子選項內容區(qū)關閉動畫,當 v-if=false 的時候調用
當子選項部分關閉時,初始狀態(tài)max-height為180,結束狀態(tài)max-height為0
*/
.fold-height-leave-active {
animation-duration: .3s;
animation-name: fold-height-close;
}
@keyframes fold-height-close {
0% {
max-height: px2rem(180);
}
100% {
max-height: 0;
}
}
}
</style>
總結
到此這篇關于vue商城中商品“篩選器”功能的實現代碼的文章就介紹到這了,更多相關vue商品篩選器內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
webpack4+express+mongodb+vue實現增刪改查的示例
這篇文章主要介紹了webpack4+express+mongodb+vue 實現增刪改查的示例,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-11-11
vue使用html2canvas實現將DOM節(jié)點生成對應的PDF
這篇文章主要為大家詳細介紹了vue如何使用html2canvas實現將DOM節(jié)點生成對應的PDF,文中的示例代碼簡潔易懂,感興趣的小伙伴可以學習一下2023-08-08
vue-cli5.0?webpack?采用?copy-webpack-plugin?打包復制文件的方法
今天就好好說說vue-cli5.0種使用copy-webpack-plugin插件該如何配置的問題。這里我們安裝的 copy-webpack-plugin 的版本是 ^11.0.0,感興趣的朋友一起看看吧2022-06-06
解決iview多表頭動態(tài)更改列元素發(fā)生的錯誤的方法
這篇文章主要介紹了解決iview多表頭動態(tài)更改列元素發(fā)生的錯誤的方法,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-11-11
解決el-cascader在IE11瀏覽器中加載頁面自動展開下拉框問題
這篇文章主要為大家介紹了解決el-cascader在IE11瀏覽器中加載頁面自動展開下拉框問題,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-06-06

