目标
实现 webContainer 四种状态的进度展示
commit: github.com/Arabeseque/…
思路:
在 pinia 全局状态中定义变量 status表示当前的进度。
定义循序变量 PlaygroundStatusOrder 表示装填转移的顺序。
使用函数获取当前的是否已经完成,展示对应的样式。
代码实现
pinia导出
export const usePlaygroundStore = defineStore('playground', (): PlaygroundStateRaw => {
return {
...
status: undefined,
}
}) as unknown as () => PlaygroundState
定义固定的状态顺序
export const PlaygroundStatusOrder = [
'init',
'mount',
'install',
'start',
'ready',
] as const
实现内容
<script setup lang="ts">
const play = usePlaygroundStore()
// 判断是否到达阶段,返回 `current` `done` `todo`等内容
function getStep(status: PlaygroundStatus) {
if (status === 'error' || play.status === 'error')
return 'error'
const indexCurrent = PlaygroundStatusOrder.indexOf(play.status!)
const index = PlaygroundStatusOrder.indexOf(status)
if (indexCurrent === index)
return 'current'
if (indexCurrent > index)
return 'done'
return 'todo'
}
// 根据阶段修改样式
function getStatusIcon(status: PlaygroundStatus) {
const step = getStep(status)
switch (step) {
case 'error':
return 'i-ph-x-circle-duotone text-error text-xl'
case 'current':
return 'i-svg-spinners-90-ring-with-bg scale-95 text-xl'
case 'done':
return 'i-ph-check-circle-duotone text-primary text-xl'
case 'todo':
return 'i-ph-dot-duotone text-xl'
}
}
function getTextClass(status: PlaygroundStatus) {
const step = getStep(status)
switch (step) {
case 'error':
return 'text-red'
case 'current':
return ''
case 'done':
return 'text-primary'
case 'todo':
return 'op50'
}
}
</script>
<template>
<div
v-if="play.status !== 'ready'"
flex="~ col items-center justify-center"
h-full capitalize
>
<div grid="~ cols-[max-content_1fr] gap-2 items-center justify-center">
<div :class="getStatusIcon('init')" />
<span :class="getTextClass('init')">Initialize WebContainer</span>
<div :class="getStatusIcon('mount')" />
<span :class="getTextClass('mount')">Mount files</span>
<div :class="getStatusIcon('install')" />
<span :class="getTextClass('install')">Install Dependencies</span>
<div :class="getStatusIcon('start')" />
<span :class="getTextClass('start')">Boot Nuxt Server</span>
</div>
</div>
</template>