红绿灯面试题

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

.traffic-lights {
  border: 1px black solid;  
  display: inline-block;
}

.light {
  height: 32px;
  width: 32px;
  border-radius: 16px;
  border: 1px black solid;
  margin: 16px;
}
// traffic-lights.js

import React, { useState, useEffect } from 'react'
import './index.css'

const TrafficLightsControllor = props => {
    const { lights } = props  
    const [lightsView, setLightsView] = useState([])

    useEffect(() => {
        walkLights(lights)
    }, [])

    const wait = time => new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve()
        }, time)
    })

    const makeView = (idx, color) => 
        lights.map((light, cur) => {
            if(cur === idx) { return !color ? light.color: color }
            return 'black'
        })

    const walkLights = async () => {
        let index = 0
        while(true) {
            const idx = index%lights.length
            if(lights[idx]) {
                const { color, duration, twinkleDuration } = lights[idx]

                // 灯亮
                let activeTime = duration - twinkleDuration ? twinkleDuration : 0
                setLightsView(makeView(idx))
                await wait(activeTime)

                // 闪烁
                if(twinkleDuration) {
                    let gutter = 500
                    let twinkleTime = twinkleDuration / gutter
                    while(twinkleTime--) {
                        if(twinkleTime%2 === 0) {
                            setLightsView(makeView(idx, 'black'))
                        } else {
                            setLightsView(makeView(idx))
                        }
                        await wait(gutter)
                    }
                }
            }
            index++
        }
    }

    return (
        <div className="traffic-lights">
            {
                lightsView.map((color, idx) => <div key={idx} className="light" style={{ backgroundColor: color }}></div>)
            }
        </div>
    )
}

export default TrafficLightsControllor
// App.js

import React from 'react'
import TrafficLightsControllor from './traffic-lights'

const App = () => {
  return <TrafficLightsControllor lights={[
      { color: 'red', duration: 20000, twinkleDuration: 5000 },
      { color: 'green', duration: 20000, twinkleDuration: 5000 },
      { color: 'yellow', duration: 10000 },
  ]}/>
}

export default App