Vue.js #練習2-事件處理與判斷:心情指數 v.s 表情管理-瞬間變臉大作戰!

Penny
16 min readMay 24, 2023

--

《 練習成果 》

網頁實作成果

《 學習重點 》

  1. v-bind屬性綁定 / 1–4 Vue.js的黑魔法:指令
  2. v-on事件綁定 / 1–5 事件處理
  3. v-if、v-else-if、v-else / 1–6 條件判斷與列表渲染

《 學習過程:筆記整理》

在這次的範例中,橫跨了教學指南裡面比較多的篇章,以下會將有運用到的部分做整理與紀錄,有興趣的捧油或是未來的我自己,可以再看看教學指南這幾個篇章裡其他的內容,像是以下:

v-model表單綁定 / 1–4 Vue.js的黑魔法:指令

v-model與修飾子 / 1–4 Vue.js的黑魔法:指令

v-textv-htmlv-oncev-pre 模板綁定/ 1–4 Vue.js的黑魔法:指令

v-on與修飾子 / 1–5 事件處理

v-for/ 1–6 條件判斷與列表渲染

在回到本次範例中,學習的重點統整 >>

◆ v-bind 屬性綁定:

  1. 用於標籤的「屬性」上,像是常見的 idclass、圖片的src 、連結的 href …等。
  2. 原完整寫法為 v-bind:屬性名稱="",可簡寫成 :屬性名稱=""
[ html ]

<div id="app">

<p :id="aaa">show the idName = "{{ aaa }}"</p> <!-- 利用v-bind將data中的變數帶入 -->
<button :disabled="cantclick">Click</button> <!-- 利用v-bind將data中的變數帶入 -->

</div>
[ vue.js ]

Vue.createApp({
data(){
return{
aaa: 'Hello_idName', // 將要取的id名稱存入 data 變數中
cantclick: true, // 將disabled 設定為 true 存入 data 變數中
}
}
}).mount('#app')
【v-bind】console.log執行出來的結果

◆ v-on 事件綁定:

  1. 使用方式 : v-on:事件名稱="運算式or呼叫方法" ,可直接寫在html中進行運算,也可將運算式寫在methods的方法內,再於html中呼叫methods的方法。
  2. 除了完整寫法 v-on:事件名稱="運算式or呼叫方法",也可簡寫成 @事件名稱="運算式or呼叫方法"
[ html ]

<div id="app">
<div class="container">
<div>
<input v-model="fullCount">
<button @click="fullCount++">運算式寫在html中</button> <!-- 寫在html中的運算式不需要加this-->
<span>@click="fullCount++"</span>
</div>
<div>
<input v-model="shortCount">
<button @click="shortWriting">methods呼叫方法</button>
<span>@click="shortWriting"</span>
</div>
</div>
</div>
[ vue.js ]

Vue.createApp({
data(){
return{
fullCount: 0,
shortCount: 1,
}
},
methods:{
shortWriting(){
this.shortCount++;
}
}
}).mount('#app')
【v-on】直接寫運算式 / 呼叫方法進行運算

◆ v-if、v-else-if、v-else:

  1. 如同Javascript中的if、else if、else一樣,針對不同的條件設定進行判斷。
[ html ]

<div id="app">
<input v-model="count">
<button @click="count++">plus</button>
<button @click="count = 0">reset</button>
<h4 v-if="count===0" style="color:red;">TestA</h4> <!-- 判斷數字0時,字體顏色為紅色 -->
<h4 v-else-if="count <= 3" style="color:blue;">TestB</h4> <!-- 判斷數字<=3時,字體顏色為藍色 -->
<h4 v-else style="color:green;">TestB</h4> <!-- 判斷數字不是0,也不是<=3時,字體顏色為綠色 -->
</div>
[ vue.js ]

Vue.createApp({
data(){
return{
count: 0,
}
},
}).mount('#app')
【v-if、v-else-if、v-else】執行成果

§ 補充紀錄:

  1. 若要顯示或隱藏某個元素,可使用上述說的 v-if 或是 v-show 來完成,兩個顯示出來的成效差不多,但在元素為隱藏時v-if 會直接移除元素,而v-show 會保留原素,僅透過css的display:none將元素隱藏。
  2. v-if 資源耗損較高; v-show 資源耗損較低。
【v-if、v-show】值為true時,元素都在
【v-if、v-show】值為false時,v-if元素移除、v-show元素display:none

《 學習過程:範例實作》

透過以上的學習,在這次的範例練習中,我們先將不同表情的圖片放進data,並且在methods中設定「增加」以及「減少」的按鈕,另外我希望數字的range只在0~10之間,所以分別在「增加」的按鈕中判斷數字最多加到10,在「減少」的按鈕中判斷數字最少減到0。(↓)

[ vue.js ] 

Vue.createApp({
data(){
return{
count: 0,
body:'./vueTest5/link/body.png', // 身體和臉
face1:'./vueTest5/link/face-1.png', // 哭哭表情
face2:'./vueTest5/link/face-2.png', // 委屈表情
face3:'./vueTest5/link/face-4.png', // 開心表情
}
},
methods:{
// 設定增加的按鈕
plus(){
// 數字小於10時,每按一次增加1
if(this.count < 10){
this.count++;
}
// 當數字到達10時,就無法再往上加
else{
this.count = 10;
}
},
// 設定減少的按鈕
minus(){
// 數字大於10時,每按一次增加1
if(this.count > 0){
this.count--;
}
// 當數字到達0時,就無法再往下減
else{
this.count = 0;
}
}
}
}).mount('#app')

接下來就是將以上的設定,在html中的元素上進行綁定的動作(↓)

[ html ]

<div class="scoreArea text-center">
<div class="point-title">心情指數</div>
<div class="d-flex justify-content-center align-items-center">
<div @click="minus" class="countBtn px-1 d-flex justify-content-center align-items-center"> <!--將「增加」的方法,利用v-on:click進行事件綁定-->
<i class="fa-solid fa-minus"></i>
</div>
<p class="score p-1">{{count}}</p>
<div @click="plus" class="countBtn p-1 d-flex justify-content-center align-items-center"> <!--將「減少」的方法,利用v-on:click進行事件綁定-->
<i class="fa-solid fa-plus"></i>
</div>
</div>
</div>

為了將數字的range只在0~10之間顯示出來能夠更明顯,所以我在「增加」以及「減少」的按鈕上,將已設置好的css className,利用 v-bind屬性綁定 的方式給予判斷是否要增加className。(↓)

[ css ]

/* ------------- 背景呈現灰色 ------------- */
.bg-gray{
background-color: #d9d9d9;
}
[ html ]

<div class="scoreArea text-center">
<div class="point-title">心情指數</div>
<div class="d-flex justify-content-center align-items-center">
<div @click="minus" class="countBtn px-1 d-flex justify-content-center align-items-center" :class="{'bg-gray': count === 0}"> <!-- 利用v-bind屬性綁定,並判斷數字為0加上className -->
<i class="fa-solid fa-minus"></i>
</div>
<p class="score p-1">{{count}}</p>
<div @click="plus" class="countBtn p-1 d-flex justify-content-center align-items-center" :class="{'bg-gray': count === 10}"> <!-- 利用v-bind屬性綁定,並判斷數字為10加上className -->
<i class="fa-solid fa-plus"></i>
</div>
</div>
</div>

最後就是圖片表情的部分,利用 v-ifv-else-ifv-else 來判斷什麼表情要在數字到達多少的時候進行變換。(↓)

[ html ]

<div class="face-box">
<img :src="face1" v-if="count <=3" > <!-- 哭哭表情,在數字<=3時顯示 -->
<img :src="face2" v-else-if="count <= 6" > <!-- 委屈表情,在數字<=6時顯示 -->
<img :src="face3" v-else> <!-- 開心表情,在數字不是以上數字的範圍時顯示 -->
</div>

基本上就大功告成拉!d(`・∀・)b

《 完整程式碼紀錄 》

※需先引入Vue.js 3.0、Bootstrap 5、fontAwesome 6.4.0

◆ Html :

<div id="app">
<div class="container">
<div class="content d-flex flex-column justify-content-center align-items-center vh-100">

<div class="title text-center">
<h3 class="CN-title m-0">情緒表情管理</h3>
<p class="EG-title">Emotions Character</p>
</div>

<div class="imgBox mb-2">
<div class="body-box">
<img :src="body"></img>
</div>
<div class="face-box">
<img :src="face1" v-if="count <=3" > <!-- 哭哭表情,在數字<=3時顯示 -->
<img :src="face2" v-else-if="count <= 6" > <!-- 委屈表情,在數字<=6時顯示 -->
<img :src="face3" v-else> <!-- 開心表情,在數字不是以上數字的範圍時顯示 -->
</div>
</div>

<div class="scoreArea text-center">
<div class="point-title">心情指數</div>
<div class="d-flex justify-content-center align-items-center">
<div @click="minus" class="countBtn px-1 d-flex justify-content-center align-items-center" :class="{'bg-gray': count === 0}"> <!-- 利用v-bind屬性綁定,並判斷是否加上className -->
<i class="fa-solid fa-minus"></i>
</div>
<p class="score p-1">{{count}}</p>
<div @click="plus" class="countBtn p-1 d-flex justify-content-center align-items-center" :class="{'bg-gray': count === 10}"> <!-- 利用v-bind屬性綁定,並判斷是否加上className -->
<i class="fa-solid fa-plus"></i>
</div>
</div>
</div>

</div>
</div>
</div>

◆ Javascript :

Vue.createApp({
data(){
return{
count: 0,
body:'./vueTest5/link/body.png', // 身體和臉
face1:'./vueTest5/link/face-1.png', // 哭哭表情
face2:'./vueTest5/link/face-2.png', // 委屈表情
face3:'./vueTest5/link/face-4.png', // 開心表情
}
},
methods:{
// 設定增加的按鈕
plus(){
// 數字小於10時,每按一次增加1
if(this.count < 10){
this.count++;
}
// 當數字到達10時,就無法再往上加
else{
this.count = 10;
}
},
// 設定減少的按鈕
minus(){
// 數字大於10時,每按一次增加1
if(this.count > 0){
this.count--;
}
// 當數字到達0時,就無法再往下減
else{
this.count = 0;
}
}
}
}).mount('#app')

◆ Css:

.content{
margin: auto;
}

/* ------------- 標題區 ------------- */
.CN-title{
font-size: 3rem;
color: #98c05b;
font-weight: 600;
}
.EG-title{
font-size: 2.2rem;
color: #e39952;
font-weight: 600;
}

/* ------------- 圖片區 ------------- */
.imgBox{
width: 60%;
position: relative;
}
@media screen and (min-width:768px){
.imgBox{
width: 45%;
position: relative;
}
}
@media screen and (min-width:992px){
.imgBox{
width: 25%;
position: relative;
}
}
.imgBox img{
width: 100%;
}
.face-box{
width: 55%;
position: absolute;
top: 15%;
left: 50%;
transform: translate(-50%, 50%);
}

/* ------------- 計分區 ------------- */
.scoreArea{
width: 100%;
}
.point-title{
color: #98c05b;
font-weight: 600;
font-size: 1.6rem;
}
.score{
width: 30%;
outline: 2px solid #98c05b;
color: #e39952;
font-weight: 600;
border-radius: 30px;
margin: 0 15px;
font-size: 1.2rem;
}
.countBtn{
width: 35px;
height: 35px;
border-radius: 35px;
cursor: pointer;
background-color: #98c05b;
}
i{
color: #fff;
}
.bg-gray{
background-color: #d9d9d9;
}

--

--