阿里面试被问到用Vue手写一个功能,我懵了!

目录
文章目录隐藏
  1. 需求设计
  2. 正式 coding
  3. 逻辑处理及代码优化
  4. 核心代码(过滤数据)
  5. 最终效果

之前去阿里的二面,信心满满的我准备了一堆面试题,想着可以暴打面试官了,很是开心!结果去了以后,他喵的居然让我给他现场机试实现一个功能,当场蒙蔽了我!

具体功能如下 gif:

阿里面试被问到用 Vue 手写一个功能

需求设计

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

流程图

这么看来好像就清晰很多了,果然设计是编程中不可或缺的一步!

正式 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]);
    }
},

注意注意:

  1. 第 2 行是讲具体商品数据中的所有属性名存储到数组中;
  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!

「点点赞赏,手留余香」

2

给作者打赏,鼓励TA抓紧创作!

微信微信 支付宝支付宝

还没有人赞赏,快来当第一个赞赏的人吧!

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。
码云笔记 » 阿里面试被问到用Vue手写一个功能,我懵了!

发表回复