您好,登錄后才能下訂單哦!
這篇文章主要介紹了Vue怎么實現(xiàn)新國標(biāo)紅綠燈效果的相關(guān)知識,內(nèi)容詳細(xì)易懂,操作簡單快捷,具有一定借鑒價值,相信大家閱讀完這篇Vue怎么實現(xiàn)新國標(biāo)紅綠燈效果文章都會有所收獲,下面我們一起來看看吧。
組件化開發(fā)是我們一貫的風(fēng)格。如何進(jìn)行這個紅綠燈組件的設(shè)計呢?
從上圖可以看出我對新國標(biāo)紅綠燈的組件拆分。
lamp 代表每個燈,在上圖中一共有9個燈,分別是左轉(zhuǎn)三個顏色的燈、直行三個顏色的燈、右轉(zhuǎn)三個顏色的燈。這 9 個燈的區(qū)別是顏色和內(nèi)部的箭頭,而內(nèi)部的箭頭與車輛行駛方向(左轉(zhuǎn)、右轉(zhuǎn)、直行)有關(guān),故顏色和方向可定義為屬性,由外部傳遞。
圖中一共有三個 lamp-group,每個行駛方向的三個顏色的燈組成一個 lamp-group。同樣的,lamp-group 有一個屬性為方向,該屬性表示左轉(zhuǎn)、直行或右轉(zhuǎn)。此外,每個 lamp-group 中最多只有一個燈亮,故可以定義一個屬性為狀態(tài),表示這個 lamp-group 中哪個燈亮、或者都不亮。
traffic-lamp 表示整個新國標(biāo)紅綠燈。有三個 lamp-group 組成。整個紅綠燈也需要一個狀態(tài)屬性,描述三個方向的 lamp-group 的狀態(tài)。
在 src/assets/ 中創(chuàng)建目錄 scss
,并在該目錄下創(chuàng)建樣式變量文件 traffic-lamp-common.scss
,在該文件中定義紅黃綠顏色、間距等常見樣式,便于全局保持一致。由于咱 demo 較小,將 scss 變量與通用樣式定義在一起就可以了,如果在正式開發(fā)中,要遵守 CSS 架構(gòu)規(guī)范,無論是 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; }
創(chuàng)建 src/common/traffic-lamp-common.ts
,在該文件中定義兩個枚舉類,分別是行駛方向(左、直、右)和燈的狀態(tài),O - off 表示燈不亮。
export enum Direction { L = 'left', C = 'center', R = 'right' } export enum Status { R = 'red', Y = 'yellow', G = 'green', O = 'off' }
由于燈里面有左箭頭、右箭頭兩個圖標(biāo),故從 iconfont 上搜索并下載這兩個圖標(biāo),優(yōu)雅哥采用 iconfont 的方式使用圖標(biāo),資源文件位于 src/assets/iconfont
下。在 main.ts 中引入iconfont:
import '@/assets/iconfont/iconfont.css'
在 src/components 目錄下創(chuàng)建目錄 traffic-lamp
,上面分析的三個組件就在該目錄下開發(fā)。
lamp.vue
:
<template> <div class="lamp" :class="colorClass"> <span v-if="direction === Direction.L" class="iconfont icon-left"></span> <span v-if="direction === Direction.R" class="iconfont icon-right"></span> </div> </template> <script lang="ts" setup> import { computed, defineProps, PropType } from 'vue' import { Direction, Status } from '@/common/traffic-lamp-common' const props = defineProps({ direction: { type: String as PropType<Direction>, required: true }, color: { type: String as PropType<Status>, required: false, default: Status.O } }) const colorClass = computed(() => { if (!props.color) { return '' } return `${props.direction}` === Direction.C ? `bg-${props.color}` : props.color }) </script> <style scoped lang="scss"> @import "~@/assets/scss/traffic-lamp-common.scss"; .lamp { width: $lampSize; height: $lampSize; line-height: $lampSize; background-color: #0e0e0e; margin: 5px; border-radius: 50%; text-align: center; color: gray; .iconfont { font-size: $lampSize - 10px; font-weight: bolder; } } </style>
可以在測試頁面測試:
<lamp direction="left" color="green"></lamp>
lamp-group 組件中容納了三個 lamp,分別是紅燈、黃燈、綠燈。
lamp-group.vue
:
<template> <div class="lamp-group" :class="{ 'radius-left': direction === Direction.L, 'radius-right': direction === Direction.R}"> <div class="wrapper"> <lamp :direction="direction" :color="status === Status.R ? status : Status.O" /> <lamp :direction="direction" :color="status === Status.Y ? status : Status.O" /> <lamp :direction="direction" :color="status === Status.G ? status : Status.O" /> </div> </div> </template> <script lang="ts" setup> import { defineProps, PropType } from 'vue' import Lamp from './lamp.vue' import { Direction, Status } from '@/common/traffic-lamp-common' defineProps({ direction: { type: String as PropType<Direction>, required: true }, status: { type: String as PropType<Status>, required: false, default: Status.O } }) </script> <style scoped lang="scss"> @import "~@/assets/scss/traffic-lamp-common.scss"; .lamp-group { background-color: #777; margin: 0 10px; padding: 10px; .wrapper { background-color: #5d5d5d; padding:5px; } } .radius-left { border-radius: $radius 0 0 $radius; } .radius-right { border-radius: 0 $radius $radius 0; } </style>
可以在測試頁面測試該組件:
<lamp-group direction="right" status="green" />
traffic-lamp 組件容納三個 lamp-group,分別代表左轉(zhuǎn)、直行、右轉(zhuǎn)。其中屬性 status 要代表三個 group 的狀態(tài),父組件在使用時可以用逗號分隔。在設(shè)計的時候,也可以將狀態(tài)拆分為三個屬性,每個方向?qū)?yīng)一個狀態(tài)。
traffic-lamp.vue
:
<template> <div class="traffic-lamp"> <lamp-group :direction="Direction.L" :status="statusList[0] || Status.O" /> <lamp-group :direction="Direction.C" :status="statusList[1] || Status.O" /> <lamp-group :direction="Direction.R" :status="statusList[2] || Status.O" /> </div> </template> <script lang="ts" setup> import { computed, defineProps } from 'vue' import LampGroup from './lamp-group.vue' import { Status, Direction } from '@/common/traffic-lamp-common' const props = defineProps({ status: { type: String, required: false, default: '' } }) const statusList = computed(() => { const list = props.status.split(',') const remain = 3 - list.length for (let i = 0; i < remain; i++) { list.push(Status.O) } return list }) </script> <style scoped lang="scss"> .traffic-lamp { display: flex; } </style>
可以在測試頁面測試該組件:
<traffic-lamp status="red,red"></traffic-lamp>
到這里為止,交通燈功能就模擬實現(xiàn)完成了,切換交通燈紅綠燈狀態(tài)時,只需要改變 status 即可。
現(xiàn)在咱額外新增一個功能,新國標(biāo)有 8 種狀態(tài),咱就讓這 8 種狀態(tài)自動切換。
下列所有代碼都編寫在測試頁面中。在測試頁面中使用 traffic-lamp
組件。
在測試頁面中定義 8 種狀態(tài)列表:
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}` ]
在測試頁面中定義遍歷狀態(tài)列表的索引:
const currentIndexRef = ref(0) const currentStatus = computed(() => statusList[currentIndexRef.value])
在模板中動態(tài)設(shè)置 traffic-lamp 的 status 屬性:
<traffic-lamp :status="currentStatus"></traffic-lamp>
在測試頁面 onMounted 生命周期函數(shù)中,定時修改索引 currentIndexRef
的值,從而實現(xiàn)紅綠燈的自動切換:
onMounted(() => { setInterval(() => { currentIndexRef.value += 1 currentIndexRef.value = currentIndexRef.value % statusList.length }, 1000) })
可以在紅綠燈下面添加是否可以通行的文字描述。
模板:
<traffic-lamp :status="currentStatus"></traffic-lamp> <div class="display"> <div :class="left">{{getText(left)}}</div> <div :class="center">{{getText(center)}}</div> <div :class="right">{{getText(right)}}</div> </div>
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 '' }
樣式:
<style scoped lang="scss"> @import "~@/assets/scss/traffic-lamp-common.scss"; .display { width: 420px; display: flex; margin-top: 10px; div { flex: 1; text-align: center; } } </style>
運(yùn)行如下:
關(guān)于“Vue怎么實現(xiàn)新國標(biāo)紅綠燈效果”這篇文章的內(nèi)容就介紹到這里,感謝各位的閱讀!相信大家對“Vue怎么實現(xiàn)新國標(biāo)紅綠燈效果”知識都有一定的了解,大家如果還想學(xué)習(xí)更多知識,歡迎關(guān)注億速云行業(yè)資訊頻道。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。