兔女鵝:
「爸爸,兔兔昨天講的好難」
「有一大堆東西要記起來,要學不動了 QQ」
兔跋:
「一定是家裡的裝潢太壓抑,要換!」
兔女鵝:
「不是,爸爸...應該跟裝潢沒...」
兔跋:
「要換!」
兔女鵝:
「摁...要換。」 (苦笑
兔跋:
「要換! 既然你也同意了」
「那我就去跟你媽說一聲」
兔女鵝:
「可惡,被我爸算計了嗎...」
「裝潢哪有這麼輕易說換就換的啦...!」
有啦,還真的有!
而且還可以選擇性的換哦!
妳爸肯定是要用 Tailwind 來重新粉刷!
讓我們看看兔跋要怎麼做吧~
昨天有介紹到屬性綁定的部分,
就是透過 v-bind 可以簡單的實現。
我們再來看一次屬性綁定的用法:
<template>
<div :id="id"> # {{id}}</div>
</template>
<script>
export default {
data() {
return {
id: "test"
}
}
}
</script>
那之前也說過,幾乎所有的屬性都可以綁定,所以要綁定 style 與 class 來動態改變樣式
也是可行的!
就讓我們先從 style 綁定看起吧!
要綁定 style,必須要注意一下綁定的變數形式。
最基本,你可以直接給他字串,例如:
<template>
<div :style="'color:red'">兔兔教</div>
</template>
但這樣其實跟你直接寫並沒有兩樣。
你也可以把它整理到 data( ) 中:
<template>
<div :style="mystyle">兔兔教</div>
</template>
<script>
export default {
data() {
return {
mystyle: "color:red"
}
}
}
</script>
所以若要在加上個藍色背景的話:
<template>
<div :style="mystyle">兔兔教</div>
</template>
<script>
export default {
data() {
return {
mystyle: "color:red;background-color:blue"
}
}
}
</script>
如果覺得這串太長太礙眼了,也可以用陣列包起來。
<template>
<div :style="mystyle">兔兔教</div>
</template>
<script>
export default {
data() {
return {
mystyle: [
"color:red",
"background-color:blue",
].join(';')
}
}
}
</script>
需要
.join(';')
是因為 inline style 每個屬性皆是用分號 ( ; ) 隔開。
不過其實上述的方法都不好,
因為它還是字串,不夠靈活。
如果要在裡面使用變數非常的麻煩,
所以最好的方式應該是使用物件:
<template>
<div :style="mystyle">兔兔教</div>
</template>
<script>
export default {
data() {
return {
mystyle: {
"color": 'red',
"background-color": 'blue',
}
}
}
}
</script>
這樣我們就可以透過改變物件屬性的方式來改變樣式了!
比如按下按鈕之後,文字會變成黃色:
<template>
<div :style="mystyle">兔兔教</div>
<button @click="mystyle.['color']='yellow'">黃字</button>
</template>
<script>
export default {
data() {
return {
mystyle: {
"color": 'red',
"background-color": 'blue',
}
}
}
}
</script>
不知道你有沒有注意到按鈕上的寫法,
用陣列 key 值的方式太累了,
我們想要直接存取屬性的話,
我們必須把屬性以小駝峰命名方式呈現。
舉例,這樣就可以了:
<template>
<div :style="mystyle">兔兔教</div>
<button @click="mystyle.color='yellow'">黃字</button>
</template>
<script>
export default {
data() {
return {
mystyle: {
color: 'red',
backgroundColor: 'blue',
}
}
}
}
</script>
善用這個方法,我們就可以做到切換主題。
<template>
<div :style="getStyle">兔兔教</div>
<button @click="theme='red'">紅色主題</button>
<button @click="theme='blue'">藍色主題</button>
<button @click="theme='green'">綠色主題</button>
</template>
<script>
export default {
data() {
return {
theme: "red",
mystyle: {}
}
},
computed: {
getStyle(){
if(this.theme==='red'){
this.mystyle.color = 'red'
this.mystyle.backgroundColor = 'pink'
}
else if(this.theme==='blue') {
this.mystyle.color = 'blue'
this.mystyle.backgroundColor = 'lightblue'
}
else {
this.mystyle.color = 'green'
this.mystyle.backgroundColor = 'lightgreen'
}
return this.mystyle
}
}
}
</script>
這份切換主題的範例也有實作出來版本的,放在文章尾部。
那 style 綁定屬性的方法和要注意的點就差不多這樣,有了這靈活綁定屬性的功能,就能簡單做到像是讀取進度條那種用數值變化位置或寬度的效果。
還有個小補充。
一般來說 html 不接受重複屬性,
比如說不能一個元素出現兩個 style 之類的。
但是因為綁定是會把運算完的結果加上去,所以可以做到重覆屬性的部分。而至於為何要重複屬性?
因為可能有些不會變動的樣式你不希望一起寫到變數中時,就可以這麼做!
舉例:
<template>
<div style="line-height:2.5rem" :style="mystyle">兔兔教</div>
<button @click="mystyle.color='yellow'">黃字</button>
</template>
<script>
export default {
data() {
return {
mystyle: {
color: 'red',
backgroundColor: 'blue',
}
}
}
}
</script>
接著趕快我們進入 class 的部分吧!
終於進入到重頭戲了啦!
既然是要使用 Tailwind,
那 class 的綁定絕對是必須要知道的!
畢竟 Tailwind 的語法有機會變很長,
還有為了要可以動態切換,
才能做出更多樣化的效果!
跟 style 的綁定方式差不多,
不過通常為了保持設計與視覺一致,
我們不會把他拉出來到變數之中存放。
拿之前的 Box 舉例:
<template>
<div
:class="[
[
'w-20 h-20 bg-gray-500 rounded-md',
'focus:ring-4 group-hover:text-gray-600',
'font-bold text-3xl text-white',
'flex justify-center items-center',
'cursor-pointer outline-none'
],
(color==='red') && 'bg-red-500 hover:bg-red-400 ring-red-300',
(color==='blue') && 'bg-blue-500 hover:bg-blue-400 ring-blue-300',
(color==='purple') && 'bg-purple-500 hover:bg-purple-400 ring-purple-300'
]"
:tabindex="number"
>
{{ number }}
</div>
</template>
<script>
export default {
name: "Box",
props: ["number", "color"]
}
</script>
上面這樣是有經過整理的,不然會超~長一串。
而且這樣整理的好處就是,
還可以把要吃變數的樣式分離出來,
而 class 不需要 join(';')
,
因為 vue 預設會把他們用空白字元串接在一起。
上面得範例可能太複雜了,
我們換一個範例來解釋。
然後順便用 vue 官方上寫的用物件的方式。
以前面的 style 切換主題為例,用 class 寫而且是 Tailwind 的話,複雜度可以降低很多:
<template>
<div
:class="{
'leading-10':true,
'text-red-600 bg-red-300': theme==='red',
'text-blue-600 bg-blue-300': theme==='blue',
'text-green-600 bg-green-300': theme==='green',
}"
>
兔兔教
</div>
<button @click="theme='red'" class="p-1 m-1 bg-gray-200 rounded">
紅色主題
</button>
<button @click="theme='blue'" class="p-1 m-1 bg-gray-200 rounded">
藍色主題
</button>
<button @click="theme='green'" class="p-1 m-1 bg-gray-200 rounded">
綠色主題
</button>
</template>
<script>
export default {
data() {
return {
theme: "red",
}
},
}
</script>
有發現嗎,下面整個 computed 都不用寫了,簡單很多。
我們把最上面那塊抽出來講解一下:
<template>
<div
:class="{
'leading-10':true,
'text-red-600 bg-red-300': theme==='red',
'text-blue-600 bg-blue-300': theme==='blue',
'text-green-600 bg-green-300': theme==='green',
}"
>
兔兔教
</div>
有發現什麼玄機嗎?
仔細看應該會發現都是以 {'classNames': boolean}
的方式呈現,也就是說 Vue 在幫元素加上這些 class 時,只會加上 vaule 是 true 的 class
,如果是 false 則會直接被省略掉。
但這寫法並不優。 為什麼?
不優的原因就在於第一個的樣式 leading-10
,它是一個並不會變動的 class,但是為了讓它可以被加在元素上,你仍然要給一個 true
的 boolean 值。
所以我們要活用 js 中的 Truthy!
若是字串不為 ""
,
那它就會是 true!
運用這個道理,我們把它以物件和陣列的混寫的
方式來達成:
<template>
<div
:class="[
'leading-10',
{
'text-red-600 bg-red-300': theme==='red',
'text-blue-600 bg-blue-300': theme==='blue',
'text-green-600 bg-green-300': theme==='green',
}
]"
>
兔兔教
</div>
這樣是不是好多了呢?
固定的樣式我們就直接是字串
就好了,
底下需要變動的才寫成物件。
不過...其實這還是不好。(乾,兔兔又覺得不好了!)
應該要像我們前面一樣,
全部都用陣列解決就好!
那再改寫一下:
<template>
<div
:class="[
'leading-10',
theme==='red'? 'text-red-600 bg-red-300': '',
theme==='blue'? 'text-blue-600 bg-blue-300': '',
theme==='green'? 'text-green-600 bg-green-300': '',
]"
>
兔兔教
</div>
欸?
用三元運算子
變成字串,
然後空字串就是 false 嘛?
哦!
不錯哦!這想法 ...!
還可以再更好一些 XDDD
我們可以試著運用這個方法啦!
const result1 = false && "123" // false
const result2 = true && "123" // "123"
這樣看懂了嗎?
沒有錯! 用 AND!
如果今天前方的條件為 false
,
會直接回傳 false
,
但如果今天前方條件是 true
,
則會往後運算,
最後返回的是後面的字串
!
要是不這麼做啊,
我們還得再多寫一個空字串,
我不要!我不要!
所以,最後我們這樣寫:
<div
:class="[
'leading-10',
theme==='red' && 'text-red-600 bg-red-300',
theme==='blue' && 'text-blue-600 bg-blue-300',
theme==='green' && 'text-green-600 bg-green-300',
]"
>
兔兔教
</div>
這樣的寫法就跟之前的 box 一樣了!
那所謂的分類你可能沒感受到,我們就再來多加一個功能。
我們用 transition-all
來加上過渡效果,並再多加一個 duration-500
讓過度效果不要太快,不然就看不出來了。
加上去之後:
<div
:class="[
'leading-10',
'transition-all duration-500',
theme==='red' && 'text-red-600 bg-red-300',
theme==='blue' && 'text-blue-600 bg-blue-300',
theme==='green' && 'text-green-600 bg-green-300',
]"
>
兔兔教
</div>
這樣一行一行的,就可以把相同用途
的功能放在一起,不但撰寫起來輕鬆,邏輯也很清晰哦,要維護時就不會這麼困難了!
那這邊就放上完整的元件內容:
<template>
<div
:class="[
'leading-10',
'transition-all duration-500',
theme==='red' && 'text-red-600 bg-red-300',
theme==='blue' && 'text-blue-600 bg-blue-300',
theme==='green' && 'text-green-600 bg-green-300',
]"
>
兔兔教
</div>
<button @click="theme='red'" class="p-1 m-1 bg-gray-200 rounded">
紅色主題
</button>
<button @click="theme='blue'" class="p-1 m-1 bg-gray-200 rounded">
藍色主題
</button>
<button @click="theme='green'" class="p-1 m-1 bg-gray-200 rounded">
綠色主題
</button>
</template>
<script>
export default {
data() {
return {
theme: "red",
}
},
}
</script>
這個範例的連結也會放在文章尾部!
最後來補充一下,同樣的版搬到 React 也幾乎可以馬上使用! 要靠一個叫做 clsx
的 npm 套件,然後修改一下直接用:
<div
className="clsx([
'leading-10',
'transition-all duration-500',
theme==='red' && 'text-red-600 bg-red-300',
theme==='blue' && 'text-blue-600 bg-blue-300',
theme==='green' && 'text-green-600 bg-green-300',
])"
>
兔兔教
</div>
摁,只要你變數名稱一模一樣,上面這段就可以直接拉去 React 用
囉!
那 class 的部分就這樣詳解完啦~~
跟前幾天的相比,
今天有沒有比較簡單呢? (笑)
不過就是範例的量可能比較多啦,
慢慢看一定沒有問題的!
聽說只要說要考試,
學生們的學習能力就會大增
,
那我是不是下次來出個考... (被摀嘴)
兔女鵝:
「爸爸,我把老師的嘴摀住了,心裡不煩了,可以求你不要重新換我房間的裝潢嗎...!」
兔跋:
「 ... 」
「 要換!」
關於兔兔們:
( # 兔兔小聲說 )
你們知道廣告上的這句
「心中若少軟萌兔,編譯再也無一物」
其實,
是有下一句的嗎?