【React】信号灯面试题

前言

  • 无意中看见瓶子君推送的一篇阿里面试题文章,作者没做出来,然后喊别人做的。我们做做玩玩。

题目

/** 1. 信号灯控制器
用 React 实现一个信号灯(交通灯)控制器,要求:
1. 默认情况下,
  1.1. 红灯亮20秒,并且最后5秒闪烁
  1.2. 绿灯亮20秒,并且最后5秒闪烁
  1.3. 黄灯亮10秒
  1.4. 次序为 红-绿-黄-红-绿-黄
2. 灯的个数、颜色、持续时间、闪烁时间、灯光次序都可配置,如:
   lights=[{color: '#fff', duration: 10000, twinkleDuration: 5000}, ... ]
*/

import React from 'react'
import ReactDOM from 'react-dom'
class TrafficLightItem extends React.Component {
}

分析

  • 信号灯题目是一个经典的题目,因为以前前端界搞出了个信号灯大战,各种实现信号灯的方法都有,不过这题是变种。其实就是考你异步处理。
  • 假定候选人会干前端,那必定会调api,感觉能区分和大部分前端优秀的地方一般就在异步设计与工程化的配置上。。
  • 题目是给配置项的,题意也比较容易懂,就跟我们路上看到的信号灯差不多。
  • 先根据提意列出配置项:
const lights = [
	{ color: "red", duration: 20000, twinkleDuration: 5000 },
	{ color: "green", duration: 20000, twinkleDuration: 5000 },
	{ color: "yellow", duration: 10000, twinkleDuration: 0 },
];
  • 先搭好大致框架,我不太喜欢写ts写类组件,所以直接再套一层在函数组件里写:
/*
 * @Author: yehuozhili
 * @Date: 2021-03-07 00:46:28
 * @LastEditors: yehuozhili
 * @LastEditTime: 2021-03-07 00:55:58
 * @FilePath: \test\src\App.tsx
 */
import React from "react";

const lights = [
	{ color: "red", duration: 20000, twinkleDuration: 5000 },
	{ color: "green", duration: 20000, twinkleDuration: 5000 },
	{ color: "yellow", duration: 10000, twinkleDuration: 0 },
];

function Main(props: { lights: typeof lights }) {
	console.log(props);
	return <div>11</div>;
}

class TrafficLightItem extends React.Component<{ lights: typeof lights }> {
	render() {
		return <Main lights={this.props.lights}></Main>;
	}
}

function App() {
	return (
		<div className="App">
			<TrafficLightItem lights={lights}></TrafficLightItem>
		</div>
	);
}

export default App;
  • 这样我们就可以在main里处理逻辑了。
  • 信号灯要变颜色就用div的bg来表示。闪烁的话需要单独写个方法,然后调它。
  • 状态肯定是放颜色,这毫无疑问。
  • 这里的难点在无限循环,先不处理它, 然后每种亮灯方法封装成promise函数,因为调用时候需要等待,所以要await下。
  • 普通亮灯函数很简单:
	const normal = useMemo(() => {
		return (color: string, delay: number) => {
			return new Promise((res) => {
				setCurColor(color);
				setTimeout(() => {
					res("");
				}, delay);
			});
		};
	}, []);
  • 然后是闪烁函数,这里闪烁我就配置成1秒用black颜色闪烁一下:
	const twinkle = useMemo(() => {
		return (color: string, delay: number) => {
			return new Promise((res) => {
				let cur = color;
				let flag = true;
				let timer = setInterval(() => {
					if (flag) {
						if (cur === color) {
							cur = "black";
							setCurColor("black");
						} else {
							cur = color;
							setCurColor(color);
						}
					}
				}, 1000);
				setTimeout(() => {
					flag = false;
					window.clearTimeout(timer);
					res("");
				}, delay);
			});
		};
	}, []);
  • 最后,useEffect里执行for循环,执行完毕后,进行递归:
	useEffect(() => {
		const fn = async () => {
			for (let i in props.lights) {
				const cur = props.lights[i];
				const normaltime = cur.duration - cur.twinkleDuration;
				await normal(cur.color, normaltime);
				await twinkle(cur.color, cur.twinkleDuration);
			}
			fn();
		};
		fn();
	}, [normal, props.lights, twinkle]);
  • 这样就成功了。
  • 看了下时间,做完这题加顺带写了这篇博客一共花了40分钟。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

业火之理

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值