终於到了我们的元件篇啦!!!
今天是第一个元件,所以稍微简单一点。
我们要来做下载的进度条~
我们这次要使用的专案环境是 Vue 的,所以之前建立过的那个专案就不沿用罗!
而 Tailwind + Vue 的专案要快速建立就得用到 Creator
啦!
Creator 连结在这边: 点我
进到 Creator 後,我这边专案名称是叫做 beautiful-components-libs
,然後 template 选择 Vite 分类下的 Vue。
都 OK 之後,大力按下复制然後贴到你的 Terminal (cmd) 中,让他开始建立专案并开启 dev server。
开启後,我们浏览网站就会看到这个画面:
那这样前置作业就完成啦~
接着开启 vs code 准备开发!
(如果对这些步骤或是对 Creator 还不熟悉的人,建议你回去复习兔兔的 Day 18:「极速开发」- Vitawind
)
首先,我们要先建立空白元件,
这样画面上就可以同步看到我们的修改内容。
先在专案里的 ./src/components
资料夹中新增一个 ProgressBar.vue
的元件:
完成後,增添以下内容:
<template>
</template>
<script>
export default {
name: "ProgressBar",
}
</script>
<style>
</style>
接着我们就可以把这个元件新增到画面中,打开 App.vue
然後改成以下内容:
<template>
<div :class="[
'w-screen h-screen',
'flex flex-col',
'justify-center items-center',
'gap-5',
]">
<ProgressBar />
</div>
</template>
<script>
import ProgressBar from './components/ProgressBar.vue'
export default {
components: {
ProgressBar
}
}
</script>
这时候画面上 ... 是空白的!
对,因为我们把 HelloWorld.vue 从画面上去掉了,加入了我们建立的 ProgressBar
元件,然後因为元件内容都还没有做,所以画面是空白的。
再来,就要来开始做我们的进度条罗!
我们先来看一下,进度条可能会有的样子!
所以很明显,这就是要分成三层,
既然知道了,就 div 大法直接建 3 层!
像这样:
<template>
<div>
<div>
<div />
</div>
</div>
</template>
<script>
export default {
name: "ProgressBar",
}
</script>
建好之後,都先填上背景颜色:
<div :class="[
'bg-gray-200'
]">
<div :class="[
'bg-green-800'
]">
<div :class="[
'bg-green-500'
]" />
</div>
</div>
因为现在都还没有宽度高度,所以画面上还是没有东西。 我们帮最外层设定高度 w-80
并增加一点内距 p-5
:
<div :class="[
'w-80 p-5',
'bg-gray-200'
]">
<div :class="[
'bg-green-800'
]">
<div :class="[
'bg-green-500'
]" />
</div>
</div>
看起来有点 ... 样子?
还没,我们再来帮进度条背景和进度条本体设定宽度高度,进度条背景的宽高设为 w-full h-2
,然後进度条本体的宽高设定为 w-1/3 h-full
:
<div :class="[
'w-80 p-5',
'bg-gray-200'
]">
<div :class="[
'w-full h-2',
'bg-green-800'
]">
<div :class="[
'w-1/3 h-full',
'bg-green-500'
]" />
</div>
</div>
这次是不是真的有点 fu 了?
对啦~一定有啦~我知道啦~
可是根据小米定律,要好看的话肯定要加上什麽?
大声点,我听不到! 梁静茹也听不到!
嘿啦~就是圆角
啦!
我们帮最外层加上大量级的圆角 rounded-lg
,然後帮进度条背景和进度条本体都加上 rounded-full
:
<div :class="[
'w-80 p-5',
'bg-gray-200',
'rounded-lg'
]">
<div :class="[
'w-full h-2',
'bg-green-800',
'rounded-full'
]">
<div :class="[
'w-1/3 h-full',
'bg-green-500',
'rounded-full'
]" />
</div>
</div>
嗯~~~很可以。
是不是! 我就说小米定律超有效的啦!
质感整个大提升了。
但现在只是固定的画面,所以我们要让它可以实际使用!
要让它动起来了!
接下来就是要写 Vue 的部分了。
这时候可以仔细的思考一下,
进度条会需要什麽东西?
答案就是:最小值
、最大值
、现在值
。
所以我们就帮元件加上 props,分别是 minVal
、maxVal
、currentVal
:
<script>
export default {
name: "ProgressBar",
props: ["minVal","maxVal","currentVal"],
}
</script>
加好之後,我们需要算进度是多少 % 。
在 data 中建立一个变数 percent 来储存算完的结果
,预设值是 0。
但是光是建立好变数,还没建立算式呢! 这时候我们要使用之前没说过的东西:watch
来完成。
之前在 Day 20 有谈过类似的概念,而 Vue 中的 watch 呢就是可以用来监看某个变数或物件是否有变动
,然後触发你所指定的方法。
因为我们这里需要在 currentVal 变动时重新计算进度是多少 % ,所以我们写在 watch 之中:
<script>
export default {
name: "ProgressBar",
props: ["minVal","maxVal","currentVal"],
data() {
return {
percent: 0,
}
},
watch: {
currentVal(newVal, oldVal) {
this.percent = newVal <= this.minVal ? 0 : (newVal-this.minVal)*100/(this.maxVal-this.minVal)
}
}
}
</script>
最後,因为元件建立时载入初始值的当下不算是变数内容的变动,所以我们要在元件挂载时重新计算一次:
<script>
export default {
name: "ProgressBar",
props: ["minVal","maxVal","currentVal"],
data() {
return {
percent: 0,
}
},
mounted() {
this.percent = this.currentVal <= this.minVal ? 0 : (this.currentVal-this.minVal)*100/(this.maxVal-this.minVal)
},
watch: {
currentVal(newVal, oldVal) {
this.percent = newVal <= this.minVal ? 0 : (newVal-this.minVal)*100/(this.maxVal-this.minVal)
}
}
}
</script>
那麽我们就 ... 啊!
修但几咧,差点就忘了最重要最重要的点!
我们的 % 算完还没让它应用到高度上啊 XD
所以,我们贴心的帮进度条本体绑定 style
,用 percent 来动态改变宽度:
<div :class="[
'w-80 p-5',
'bg-gray-200',
'rounded-lg'
]">
<div :class="[
'w-full h-2',
'bg-green-800',
'rounded-full'
]">
<div
:class="[
'w-1/3 h-full',
'bg-green-500',
'rounded-full'
]"
:style="{
width: percent + '%'
}"
/>
</div>
</div>
这样就真的完成了!
最後元件的完整内容会是这样:
<template>
<div :class="[
'w-80 p-5',
'bg-gray-200',
'rounded-lg'
]">
<div :class="[
'w-full h-2',
'bg-green-800',
'rounded-full'
]">
<div
:class="[
'w-1/3 h-full',
'bg-green-500',
'rounded-full'
]"
:style="{
width: percent + '%'
}"
/>
</div>
</div>
</template>
<script>
export default {
name: "ProgressBar",
props: ["minVal","maxVal","currentVal"],
data() {
return {
percent: 0,
}
},
mounted() {
this.percent = this.currentVal <= this.minVal ? 0 : (this.currentVal-this.minVal)*100/(this.maxVal-this.minVal)
},
watch: {
currentVal(newVal, oldVal) {
this.percent = newVal <= this.minVal ? 0 : (newVal-this.minVal)*100/(this.maxVal-this.minVal)
}
}
}
</script>
元件完成之後,我们就可以来测试啦!
再测试之前,我们要先来完善一下我们的测试环境。
回到 App.vue
,我们来增加一个拉杆的 input 元素,不然一直改来改去很累,不如用拉的来改变数值!
<div :class="[
'w-screen h-screen',
'flex flex-col',
'justify-center items-center',
'gap-5',
]">
<input type="range" />
<ProgressBar />
</div>
加好之後,我们也需要从外部帮他们两个元件设定最小值、最大值,然後让进度条元件的 currentVal 与拉杆的当前值同步,最後就会是这个样子:
<template>
<div :class="[
'w-screen h-screen',
'flex flex-col',
'justify-center items-center',
'gap-5',
]">
<input type="range" v-model="val" :min="min" :max="max" />
<ProgressBar :currentVal="val" :minVal="min" :maxVal="max" />
</div>
</template>
<script>
import ProgressBar from './components/ProgressBar.vue'
export default {
data() {
return {
min: 0,
max: 200,
val: 100,
}
},
components: {
ProgressBar,
}
}
</script>
那麽可以测试了!
我们回到画面上玩玩~
耶~大成功!
虽然像是做完了,不过还有一些可以再加强的地方!
毕竟这样还是不够灵活、不够华丽呀~
所以最简单的,我们先加上个过渡效果
,且 duration 设为 0.5 s:
<div :class="[
'w-80 p-5',
'bg-gray-200',
'rounded-lg'
]">
<div :class="[
'w-full h-2',
'bg-green-800',
'rounded-full'
]">
<div
:class="[
'w-1/3 h-full',
'bg-green-500',
'rounded-full',
'transition-all duration-500'
]"
:style="{
width: percent + '%'
}"
/>
</div>
</div>
加完之後,应该觉得顺畅多了吧?
「是没错啦,华丽的部份解决了 ... 但兔兔你说的灵活度呢?」
灵活度吗,好!
这就要靠 slot 啦~
我们可以运用 slot 的 props,把资料从内部拉出来外部使用
,像是:
<div :class="[
'w-80 p-5',
'bg-gray-200',
'rounded-lg',
'flex flex-col',
'justify-center items-center',
'gap-3'
]">
<slot
:minVal="minVal"
:maxVal="maxVal"
:currentVal="currentVal"
:percent="percent"
/>
<div :class="[
'w-full h-2',
'bg-green-800',
'rounded-full'
]">
<div
:class="[
'w-1/3 h-full',
'bg-green-500',
'rounded-full',
'transition-all duration-500'
]"
:style="{
width: percent + '%'
}"
/>
</div>
</div>
然後为了让文字和进度条可以直向排列,我还另外在外框多下了
flex flex-col
的样式,然後记得给一点空隙,才不会看起来太挤。
这样做之後,我们就可以弄出像这样子的效果:
<ProgressBar
:currentVal="val" :minVal="min" :maxVal="max"
v-slot="{ percent }"
>
已下载 {{ percent }} %
</ProgressBar>
不仅如此,
也可以轻松修改出像是游戏载入资源的进度条:
<ProgressBar
:currentVal="val" :minVal="min" :maxVal="max"
v-slot="{ maxVal, currentVal }"
>
正在准备资源 ({{currentVal}} / {{maxVal}})
</ProgressBar>
那就会看起来像是这样~
这麽一来就完全做完啦!
好的,那麽今天的进度条就是这麽轻松简单~
明天的也很简单喔,
我们要来完成各种按钮的变化!
是不是跃跃欲试啦?
那我就不说这麽多了,赶快留时间给你去做做看!
关於兔兔们:
( # 兔兔小声说 )
今天兔兔喉咙烧声,说不出话。
但是可以唱歌!(欸你这明明就是选择性的!)
Day 18: LeetCode 322. Coin Change Tag: follow John...
写文至今已介绍过 XRGB-mini 跟 OSSC 这两种神器、互有上下也都能得到相当好的效果。但身...
鬼故事 - 我们有通过国际资安 OOO 标准 credit: AilinStock, DNDmeme...
叙述统计表 今天一家电脑公司为了了解该电脑在一地区销售的远景,所以利用近60天的销售报表,试求该电脑...
「老板,为因应多国语系,以及多平台的支援,我要增加 QA 团队的编制到对应的国家数与平台数。」这是我...