【笔经】数字马力前端笔试-22应届 [ 笔经面经 ]
晚安月亮 文章 正文

椰奶冻
{{nature("2022-07-26 22:03:12")}}更新第一题
目标
使用 React, 参考下述需求优先级和设计稿 ,实现倒计时抢券组件。
关键需求点
- 功能1: 按钮自动倒计时(此功能重要占比60%)
- 进入页面时,卡片中的按钮开始自动 10s 倒计时
- 倒计时过程中, 按钮显示剩余时间 (文案为: 10s、9s、8s、...、1s)
- 倒计时结束后,按钮文案变为「 抢购 」
- 功能2: 抢购功能模拟(此功能重要占比20%)
- 点击抢购按钮时,调用异步模拟请求方法,请求完成后按钮文字变为「 已抢购 」
- 异步请求模拟方法需自行实现,延迟 1s 后返回成功即可
- 功能3: 还原券css样式(此功能重要占比20%)
- 副标题最多支持2行, 多余2行省略号表示
设计稿
/**
* 第一题
*/
import React, { FC, useEffect, useState } from 'react';
import './style.less';
/**
* 渲染测试数据
*/
export const cardDataList: IDirectVoucher[] = [
{
title: '杭州市通用5元券',
subTitle:
'杭味面馆非常好吃,太好吃了,相当不错,味道鲜美,特别划算,快快抢购,聚划算',
},
{
title: '杭州市10元券',
subTitle: '兰州拉面非常好吃',
},
];
/**
* 券卡片渲染数据类型
*/
export interface IDirectVoucher {
/** 标题 */
title?: string;
/** 副标题 */
subTitle?: string;
}
export interface ICardProps {
data: IDirectVoucher;
}
/**
* 卡片组件
*/
export const Card: FC<ICardProps> = (props) => {
// 在这里完成代码
const { data } = props;
const max = 10;
const [str, setStr] = useState('抢购');
const [count, setCount] = useState(max);
// 倒计时逻辑
// useEffect(() => {
// if (count >= 0) {
// setTimeout(() => {
// setCount(count - 1);
// if (count == 0) {
// setStr('抢购');
// } else {
// setStr(count + 's');
// }
// }, 1000);
// }
// },[count]);
useEffect(() => {
if (count >= 0) {
const interval = setInterval(() => {
setCount(count - 1);
if (count === 0) {
setStr('抢购');
} else {
setStr(count + 's');
}
}, 1000);
return () => clearInterval(interval);
}
});
const timeClick = async () => {
await setTimeout(function () {
setStr('已抢购');
}, 1000);
};
return (
<div className="card">
<div className="left">
<div className="title">{data.title}</div>
<div className="subTitle">{data.subTitle}</div>
</div>
<div className="right">
<button onClick={() => timeClick()}>{str}</button>
</div>
</div>
);
};
第二题
目标
实现一个 query
方法,实现对数据的链式查询和处理。
要求
query
传入参数为原始数据(数组格式,每个元素都是对象)- 通过进行链式调用对数据执行操作,支持的方法有
where(predicate)
: 根据参数的条件进行筛选,参数与[].filter
的参数类似orderBy(key, desc)
: 根据key
的值进行排列,默认升序排列,当第二个参数为true
时降序排列groupBy(key)
: 根据key
的值对数据元素进行分组,合并为二维数组execute()
: 执行所有处理并返回最终结果
- 请结合下面示例理解需求
/**
* 第二题
*/
import { isEqual } from 'lodash-es';
function query(data: Object[]) {
let list = data;
function myArray() {}
// 判断数据类型
if (Object.prototype.toString.call(data).slice(8, -1) !== 'Array') {
return console.error('must be an array');
}
myArray.prototype.where = function (key) {
list = list.filter(key);
return { ...myArray.prototype };
};
myArray.prototype.orderBy = function (key) {
list = list.sort((a, b) => a[key] - b[key]);
return { ...myArray.prototype };
};
myArray.prototype.groupBy = function (key) {
let group = list.reduce((pre, item) => {
pre[item[key]] = [...(pre[item[key]] || []), item];
return pre;
}, {});
let ordList = [];
for (let key in group) {
ordList.push(group[key]);
}
list = ordList;
return { ...myArray.prototype };
};
myArray.prototype.execute = function (key) {
return list;
};
return { ...myArray.prototype };
}
/**
* 以下为测试用例,无需修改
*/
export default () => {
try {
const data = [
{ name: 'foo', age: 16, city: 'shanghai' },
{ name: 'bar', age: 24, city: 'hangzhou' },
{ name: 'fiz', age: 22, city: 'shanghai' },
{ name: 'baz', age: 19, city: 'hangzhou' },
];
const result = query(data)
// @ts-ignore
.where((item) => item.age > 18)
.orderBy('age')
.groupBy('city')
.execute();
console.log('result:', result);
if (
!isEqual(result, [
[
{ name: 'baz', age: 19, city: 'hangzhou' },
{ name: 'bar', age: 24, city: 'hangzhou' },
],
[{ name: 'fiz', age: 22, city: 'shanghai' }],
])
) {
throw new Error('Wrong answer');
}
return true;
} catch (err) {
console.warn('测试运行失败');
console.error(err);
return false;
}
};
{{nature('2022-06-23 23:10:58')}} {{format('1473')}}人已阅读
{{nature('2023-02-03 16:12:08')}} {{format('1394')}}人已阅读
{{nature('2024-05-29 15:14:38')}} {{format('1012')}}人已阅读
{{nature('2024-05-24 15:20:21')}} {{format('900')}}人已阅读
目录
一言
评论 0
{{userInfo.data?.nickname}}
{{userInfo.data?.email}}