• Vue 3-150行代码实现新国标红绿灯效果案例


    昨天刷视频,都是关于新国标红绿灯的,看大家议论纷纷,下班就用150行代码通过Vue组件实践红绿模拟演示,视频也跟大家展示过了。今天接着更新图文版本,大家跟着优雅哥通过该案例实操模拟一下。

    不过新国标红绿灯的设计,这个专业性、逻辑性、艺术性就是厉害,三个方向 * 三种颜色,玩转九宫格。大部分场景都可以不加思考就知道应该通行或者等待,只有某些情况下对应行驶方向的灯不亮时,才需要 if ... else ... 判断。优雅哥比较脑残,无论哪个方向:左转、直行、右转,如果灯都亮着,不就可以一眼看出能否通行了吗,对应方向红灯就停、绿灯就通行,这样是不是就可以不需要思考了?或许专家是为了省电吧,三个方向都亮灯太费电了。
    后面得知,关于新国标红绿灯信息是误传,以上说辞纯属个人当时根据信息的一些看法,请大家不要误以为真。

    现在来说说作为程序员,咱就用 Vue3 来模拟新国标红绿灯玩一玩。

    1 组件分析

    组件化开发是我们一贯的风格。如何进行这个红绿灯组件的设计呢?

    image

    从上图可以看出我对新国标红绿灯的组件拆分。

    1.1 lamp

    lamp 代表每个灯,在上图中一共有9个灯,分别是左转三个颜色的灯、直行三个颜色的灯、右转三个颜色的灯。这 9 个灯的区别是颜色和内部的箭头,而内部的箭头与车辆行驶方向(左转、右转、直行)有关,故颜色和方向可定义为属性,由外部传递。

    1.2 lamp-group

    图中一共有三个 lamp-group,每个行驶方向的三个颜色的灯组成一个 lamp-group。同样的,lamp-group 有一个属性为方向,该属性表示左转、直行或右转。此外,每个 lamp-group 中最多只有一个灯亮,故可以定义一个属性为状态,表示这个 lamp-group 中哪个灯亮、或者都不亮。

    1.3 traffic-lamp

    traffic-lamp 表示整个新国标红绿灯。有三个 lamp-group 组成。整个红绿灯也需要一个状态属性,描述三个方向的 lamp-group 的状态。

    2 全局文件定义

    2.1 样式变量

    在 src/assets/ 中创建目录 scss,并在该目录下创建样式变量文件 traffic-lamp-common.scss,在该文件中定义红黄绿颜色、间距等常见样式,便于全局保持一致。由于咱 demo 较小,将 scss 变量与通用样式定义在一起就可以了,如果在正式开发中,要遵守 CSS 架构规范,无论是 ITCSS 还是 SMACSS。

    src/assets/scss/traffic-lamp-common.scss

    $red: #e42621;
    $yellow: #eecd48;
    $green: #59e02e;
    
    $commonPadding: 10px;
    $commonMargin: 10px;
    $lampSize: 80px;
    $radius: 8px;
    
    .red {
      color: $red !important;
    }
    .yellow {
      color: $yellow !important;
    }
    .green {
      color: $green !important;
    }
    .bg-red {
      background-color: $red !important;
    }
    .bg-yellow {
      background-color: $yellow !important;
    }
    .bg-green {
      background-color: $green !important;
    }
    

    2.2 常量定义

    创建 src/common/traffic-lamp-common.ts,在该文件中定义两个枚举类,分别是行驶方向(左、直、右)和灯的状态,O - off 表示灯不亮。

    export enum Direction {
      L = 'left',
      C = 'center',
      R = 'right'
    }
    export enum Status {
      R = 'red',
      Y = 'yellow',
      G = 'green',
      O = 'off'
    }
    

    2.3 导入资源

    由于灯里面有左箭头、右箭头两个图标,故从 iconfont 上搜索并下载这两个图标,优雅哥采用 iconfont 的方式使用图标,资源文件位于 src/assets/iconfont 下。在 main.ts 中引入iconfont:

    import '@/assets/iconfont/iconfont.css'
    

    3 组件开发

    在 src/components 目录下创建目录 traffic-lamp,上面分析的三个组件就在该目录下开发。

    3.1 实现 lamp 组件

    lamp.vue

    
    
    
    
    
    

    可以在测试页面测试:

    
    

    3.2 实现 lamp-group 组件

    lamp-group 组件中容纳了三个 lamp,分别是红灯、黄灯、绿灯。

    lamp-group.vue

    
    
    
    
    
    

    可以在测试页面测试该组件:

    
    

    3.3 实现 traffic-lamp 组件

    traffic-lamp 组件容纳三个 lamp-group,分别代表左转、直行、右转。其中属性 status 要代表三个 group 的状态,父组件在使用时可以用逗号分隔。在设计的时候,也可以将状态拆分为三个属性,每个方向对应一个状态。

    traffic-lamp.vue

    
    
    
    
    
    

    可以在测试页面测试该组件:

    
    

    4 附加功能

    到这里为止,交通灯功能就模拟实现完成了,切换交通灯红绿灯状态时,只需要改变 status 即可。

    现在咱额外新增一个功能,新国标有 8 种状态,咱就让这 8 种状态自动切换。

    下列所有代码都编写在测试页面中。在测试页面中使用 traffic-lamp 组件。

    4.1 状态数组

    在测试页面中定义 8 种状态列表:

    const { R, G, O } = Status
    const statusList = [
      `${R},${R},${R}`,
      `${R},${R},${O}`,
      `${G},${R},${R}`,
      `${O},${R},${O}`,
      `${R},${G},${R}`,
      `${O},${G},${R}`,
      `${R},${G},${O}`,
      `${O},${G},${O}`
    ]
    

    4.2 定义索引

    在测试页面中定义遍历状态列表的索引:

    const currentIndexRef = ref(0)
    const currentStatus = computed(() => statusList[currentIndexRef.value])
    

    在模板中动态设置 traffic-lamp 的 status 属性:

    
    

    4.3 自动切换

    在测试页面 onMounted 生命周期函数中,定时修改索引 currentIndexRef 的值,从而实现红绿灯的自动切换:

    onMounted(() => {
      setInterval(() => {
        currentIndexRef.value += 1
        currentIndexRef.value = currentIndexRef.value % statusList.length
      }, 1000)
    })
    

    4.4 文字描述

    可以在红绿灯下面添加是否可以通行的文字描述。

    模板:

    
    
    {{getText(left)}}
    {{getText(center)}}
    {{getText(right)}}

    TS 代码:

    const left = computed(() => {
      const list = currentStatus.value.split(',')
      return list[0] === Status.O ? list[1] : list[0]
    })
    const center = computed(() => {
      return currentStatus.value.split(',')[1] || Status.O
    })
    const right = computed(() => {
      const list = currentStatus.value.split(',')
      return list[2] === Status.R ? Status.R : Status.G
    })
    
    const getText = (status: string) => {
      if (status === Status.G) {
        return '可以通行'
      }
      if (status === Status.R) {
        return '停车等待'
      }
      return ''
    }
    

    样式:

    
    

    运行如下:

    image
    \/ “程序员优雅哥”,今日学习到此结束,期待一箭三连(赞、藏、转)~~~

  • 相关阅读:
    2023.10(u盘刻录iso)主机,vmware,virtualbox安装linux/ubuntu/kali/centos stream9/arch
    微服务框架 SpringCloud微服务架构 5 Nacos 5.6 环境隔离
    zabbix的自动发现和自动注册
    网络安全: Kali Linux 使用 MSF 漏洞利用
    放弃webstrom转战vscode
    Flutter入门-Dart端和Native端的页面跳转
    SpringMVC的准备工作
    【STM32学习】通用定时器的应用实验
    Python统治编程界?Java第一个不服
    Day07 Stream流&递归&Map集合&Collections&可变参数
  • 原文地址:https://www.cnblogs.com/youyacoder/p/16620988.html