效果
思路
数据格式
{ json1: [ ["红⾊", "黄⾊", "蓝⾊"], ["S", "M"], ["棉的", "涤纶"], ],json2: [ { color: "红⾊", type: "S", mianliao: "棉的", price: 100, },{ color: "红⾊", type: "M", mianliao: "棉的", price: 200, },{ color: "红⾊", type: "S", mianliao: "涤纶", price: 300, },{ color: "红⾊", type: "M", mianliao: "涤纶", price: 300}]}
我们从这个结构不难看出,json2就是具体的数据,⽽json1⾥⾯存放是三个维度的分类,实现效果
coding
基本结构
和样式
<div v-for="(rowArr, index) in mockData.json1" :key="index">
<a v-for="(item, i) in rowArr" :key="i" @click="changeData(index,item)">
</div>
<style>
#app a {
text-decoration: none;
border: 1px solid grey;
margin: 8px;
padding: 6px;
display: inline-block;
color: grey;
}
#app a.active {
border: 1px solid red;
color: red;
}
</style>
逻辑处理及代码优化
⾯试官在告知我需求的时候,强调⼜强调数据不能写死,聪明的我当然明⽩,意思就是要尽可能 让我们的前端代码有更⾼的复⽤性,说⽩了就是可能会匹配颜⾊、尺码、⾯料,也可能会⽤⾦额、风 格来匹配。
设计⼀个万能属性匹配器
可以想象,不管他是什么属性,但只要是【条件对象】的abc属性,与【数据对象】的abc属性 ⼀致,我就可以认为筛选出来的就是这个对象,因此不要在乎abc这个名,岂不就通⽤性很⾼啦。接 着我们在data下声明⼀个condition对象来存储当前选中的各项属性,再给他默认值。
data() {
return {
types:[], // 保存从json2中获取的动态属性名称
condition: {}, // 有json1.length个属性,分别是前三项color、type、mianliao
mockData: {
json1: [
["红⾊", "黄⾊", "蓝⾊"],
["S", "M"],
["棉的", "涤纶"],
],
json2: [
{
color: "红⾊",
type: "S",
mianliao: "棉的",
price: 100,
}
/*....省略数据*/
]
}
}
}
模拟created中动态获取,并动态⽣成types和condition
created(){
this.types = Object.keys(this.mockData.json2[0]);
for (let i = 0; i < this.types.length; i ++) {
// 由于分类有可能没有数据的属性多,所以判断⼀下
if (!this.mockData.json1[i])return;
let propName = this.types[i];
this.$set(this.condition,propName,this.mockData.json1[i][0]);
}
},
注意注意
a. 第2⾏是讲具体商品数据中的所有属性名存储到数组中
b. 第7⾏则是动态添加响应式属性
,这是Vue2中动态添加属性必须要做的,vue2使用的是Object.definePrroperty来拦截各个属性的getter和setter,来发布消息给订阅者,进行监听,并且它监听不到对象属性的添加与删除
否则更改数据页⾯那个属性不变化,Vue3这个问题使用Proxy已经解决
点中后的激活效果
<a :class="{ active: condition[types[index]] === item }"
href="#"
v-for="(item, i) in rowArr"
:key="i"
>
{{ item }}
</a>
核⼼代码(过滤数据)
- ⾸先我们给a标签添加点击事件,点了那项,就更改其中颜⾊或者尺码或者⾯料的值,因此相同 函数我们必须要知道点了哪个类别,这⾥我们可以⽤【外层的index】做区分,给a标签加上事件
<a @click="changeData(types[index], item)" a>{{item}}</a>
- 保存这个数据变化
changeData(prop, data) {
let self = this;
self.condition[prop] = data;
}
- 有了数据,就可以做过滤显⽰了,computed是最佳⼈选
computed: {
showGoodsInfo() {
return his.mockData.json2.filter((e) => {
return diffObjectByKeys(this.condition, e);
});
},
}
- 核⼼的⼯具函数,对⽐两个对象的函数还没实现,我们去实现它,这个函数接收俩对象,对⽐其 属性值,全都相同,返回true,否则false。
function diffObjectByKeys(obj1, obj2) {
let isEqual = true;
for (let key in obj1) {
let v = obj1[key];
if (obj2[key] && obj2[key] === v) {
continue;
} else return false;
}
return isEqual;
}
- 使⽤这个计算属性:
价格是: {{ showGoodsInfo }}