阿里面试被问到用Vue手写一个功能,我懵了!
之前去阿里的二面,信心满满的我准备了一堆面试题,想着可以暴打面试官了,很是开心!结果去了以后,他喵的居然让我给他现场机试实现一个功能,当场蒙蔽了我!
具体功能如下 gif:

需求设计
差点凌乱,结果一想,这难吗? 难就难在没有思路。于是这时的我两腿一蹬,大脑开始高速运转,生成如下流程图:

这么看来好像就清晰很多了,果然设计是编程中不可或缺的一步!
正式 coding
首先我问面试官,后台响应回来的详情数据是什么结构,于是他给了我这么一坨
{
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: 400,
},
{
color: "黄色",
type: "S",
mianliao: "棉的",
price: 500,
},
{
color: "黄色",
type: "M",
mianliao: "棉的",
price: 600,
},
{
color: "黄色",
type: "S",
mianliao: "涤纶",
price: 700,
},
{
color: "黄色",
type: "M",
mianliao: "涤纶",
price: 800,
},
{
color: "蓝色",
type: "S",
mianliao: "棉的",
price: 900,
},
{
color: "蓝色",
type: "M",
mianliao: "棉的",
price: 1000,
},
{
color: "蓝色",
type: "S",
mianliao: "涤纶",
price: 1100,
},
{
color: "蓝色",
type: "M",
mianliao: "涤纶",
price: 1200,
},
]
}
我们从这个结构不难看出,json2 就是具体的数据,而 json1 里面存放是三个维度的分类,实现效果差不多是这样:

所以问题不大,我们先把 json1 的数据渲染出来再说。
<div v-for="(rowArr, index) in mockData.json1" :key="index">
<a v-for="(item, i) in rowArr" :key="i" @click="changeData(index,item)">{{item}}</a>
</div>
上述数据我们保存在 mockData 中,只遍历 json1,效果出来了,适当加点样式:
#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;
}
出来了,beautiful:

逻辑处理及代码优化
面试官在告知我需求的时候,强调又强调数据不能写死,聪明的我当然明白,意思就是要尽可能让我们的前端代码有更高的复用性,说白了就是可能会匹配颜色、尺码、面料,也可能会用金额、风格来匹配。
设计一个万能属性匹配器
可以想象,不管他是什么属性,但只要是【条件对象】的 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]);
}
},
注意注意:
- 第 2 行是讲具体商品数据中的所有属性名存储到数组中;
- 第 7 行则是动态添加响应式属性,这是 Vue2 中动态添加属性必须要做的,否则更改数据页面那个属性不变化,Vue3 这个问题已经解决。
点中后的激活效果
<a :class="{ active: condition[types[index]] === item }" href="#"
v-for="(item, i) in rowArr"
:key="i"
>{{ item }}</a>
这个比较简单!
核心代码(过滤数据)
1、首先我们给 a 标签添加点击事件,点了那项,就更改其中颜色或者尺码或者面料的值,因此相同函数我们必须要知道点了哪个类别,这里我们可以用【外层的 index】做区分,给 a 标签加上事件:
<a @click="changeData(types[index], item)" a>{{item}}</a>
2、保存这个数据变化
changeData(prop, data) {
let self = this;
self.condition[prop] = data;
}
3、有了数据,就可以做过滤显示了,computed 是最佳人选
computed: {
showGoodsInfo() {
return his.mockData.json2.filter((e) => {
return diffObjectByKeys(this.condition, e);
});
},
}
4、核心的工具函数,对比两个对象的函数还没实现,我们去实现它,这个函数接收俩对象,对比其属性值,全都相同,返回 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;
}
5、别忘了使用这个计算属性:
价格是: {{ showGoodsInfo }}
最终效果

至此,完美实现,非常 Nice!
以上关于阿里面试被问到用Vue手写一个功能,我懵了!的文章就介绍到这了,更多相关内容请搜索码云笔记以前的文章或继续浏览下面的相关文章,希望大家以后多多支持码云笔记。
如若内容造成侵权/违法违规/事实不符,请将相关资料发送至 admin@mybj123.com 进行投诉反馈,一经查实,立即处理!
重要:如软件存在付费、会员、充值等,均属软件开发者或所属公司行为,与本站无关,网友需自行判断
码云笔记 » 阿里面试被问到用Vue手写一个功能,我懵了!
微信
支付宝