---
# System prepended metadata

title: Vue樣板語法
tags: [Vue框架]

---

# Vue 樣板語法

### 嵌入純文字
標籤內使用 {{ 嵌入的變數 }} 語法

```
組建名稱.vue

<script setup>
    let data="Hello";
</script>
<template>
    <div>{{ data }}</div>
</template>
<style scoped>
    /*CSS設定*/
</style>
```

### 嵌入Html語法
標籤屬性設定 v-html="嵌入的變數"

```
組建名稱.vue

<script setup>
    let htmlData="<u>Hello</u>";
</script>
<template>
    <div v-html="htmlData"></div>
</template>
<style scoped>
    /*CSS設定*/
</style>
```

### 屬性
- 嵌入屬性值(將變數中的資料帶入到標籤中的屬性中)
v-bind:屬性名稱="嵌入的變數"
簡寫->
:屬性名稱="嵌入的變數"

```
組建名稱.vue

<script setup>
    let name="content";
</script>
<template>
    <div v-bind:class="name">Hello</div>
    //簡寫-> <div:class="name">Hello</div>//
</template>
<style scoped>
    /*CSS設定*/
</style>
```

### 程式語句
- 透過程式語句產生標籤內文
標籤內使用 {{ 程式語句 }}語法

```
組建名稱.vue

<script setup>
    let data="Hello";
</script>
<template>
    <div>{{ data.toUpperCase()}}</div>
</template>
<style>
    /*CSS設定*/
</style>
```

- 透過程式語句產生標籤屬性值
- 標籤屬性設定
:屬性名稱="程式語句"

```
組建名稱.vue

<script setup>
    let data="true";
</script>
<template>
    <div :class="data?'dark':'light'">Hello</div>
</template>
<style scoped>
    /*CSS設定*/
</style>
```

### 判斷式
- if 判斷式
v-if="布林值"

```
組建名稱.vue

<script setup>
    let data = true;
    let number = 3000;
</script>
<tamplate>
    <div v-if="data">顯示</div>
    <div v-if="!data">不顯示</div>
    <div v-if="number>2000">大於2000</div>
</tamplate>
<style scoped>
    /*CSS設定*/
</style>
```

- if...else判斷式
使用v-else語法，必須搭配v-if使用

```
組建名稱.vue

<script setup>
    let number = 1000;
</script>
<template>
    <div v-if="number>2000">大於2000</div>
    <div v-else>小於等於2000</div>
</template>
<style scoped>>
    /*CSS設定*/
</style>
```

- if...else if...else判斷式
使用v-else-if="布林值"語法，必須搭配v-if使用，可搭配v-else

```
組建名稱.vue

<script setup>
    let number = 15;
</script>
<template>
    <div v-if="number<20">小於20</div>
    <div v-else-if="number<20">小於10</div>
    <div v-else>小於5</div>
</template>
<style scoped>
    /*CSS設定*/
</style>
```

### 迴圈
- for迴圈-陣列
使用v-for="變數in陣列"語法

```
<script setup>
    let data=[1,2,3];
</script>
<template>
    <div v-for="n in data">Item{{ n }}</div>
</template>
<style scoped>
    /*CSS設定*/
</style>
```

- for迴圈-陣列索引
使用v-for="(變數,變數)in陣列"語法

```
<script setup>
    let data=["A","B","C"];
</script>
<template>
    <div v-for="(text,index)in data">
    {{ index }}-{{ text }}
    </div>
</template>
<style scoped>
    /*CSS設定*/
</style>
```

- for迴圈-物件
使用v-for="(變數,變數)in物件"語法

```
<script setup>
    let data=["x"=3,"y"=4];
</script>
<template>
    <div v-for="(value,key)in data">
    物件屬性{{ key }}為{{ value }}
    </div>
</template>
<style scoped>
    /*CSS設定*/
</style>
```

### 基本事件處理
- 基本事件處理
使用v-on:事件名稱="函式名稱"語法

```
<script setup>
    let handler = function(){
        console.log("Click");
    };
</script>
<template>
    <span v-on:click="handler"> </span>
</template>
<style scoped>
    /*CSS設定*/
</style>
```

- 基本事件處理(簡寫)
使用@事件名稱="函式名稱"語法

```
<script setup>
    let clickHandler = function(){
            console.log("Click");
    }
    let mouseoverHandler = function(){
        console.log("MouseOver");
    }
</script>
<template>
    <span
        @click = "clickHandler"
        @mouseover = "mouseoverHandler">文字
    </span>
</template>
<style scoped>
    /*CSS設定*/
</style>
```

### 使用修飾字
- 使用once表達事件只觸發一次
v-on:事件名稱.once="函式名稱"
@事件名稱.once="函式名稱"

```
<script setup>
    let handler = function(){
        console.log("Click");
    };
</script>
<template>
    <span v-on:click.once="handler"> </span>
</template>
<style scoped>
    /*CSS設定*/
</style>
```

- 使用prevent表達停止預設行為
v-on:事件名稱.prevent="函式名稱"
@事件名稱.prevent="函式名稱"

```
<script setup>
    let handler = function(){
        console.log("Click");
    };
</script>
<templte>
    <a href="http://training.pada-x.com/"
    v-on:click.prevent="handler"
        >我的網站</a>
</templte>
<style scoped>
    /*CSS設定*/
</style>
```

### 響應式狀態
#### 非響應式的狀態
資料和畫面沒有連動

```
<script setup>
    let content = "網站的內容";
    let handler = function(){
    content = "新的網站內容";
}
</script>
<template>
    <div>{{ content }}</div>
    <button @click = "handler">點擊</button>
</template>
<style scoped>
    /*CSS設定*/
</style>
```

#### 響應式狀態
資料和畫面有連動

- 載入Vue的ref函式
`import{ref}form "vue";`
- 呼叫ref函式建立響應式狀態
`let content = ref(資料);`
- 在樣板中使用、顯示資料
`<div>{{content}}</div>`
- 更新響應式狀態的資料
`content.value="新的資料";`

```
<script setup>
    import{ref}from "vue";
    let content = ref("網站的內容");
    let handler = function(){
    content.value = "新的網站內容";
}
</script>
<template>
    <div>{{ content }}</div>
    <button @click = "handler">點擊</button>
</template>
<style scoped>
    /*CSS設定*/
</style>
```

```
<script setup>
    let name = ref("title");
    let handler = function(){
        name.value = "title highlight"
    }
</script>
<template>
    <div :class="name">段落標題</div>
    <button @click = "handler">點擊</button>
</template>
<style scoped>
    .title{font-weight:bold}
    .highlight{color:red}
</style>
```
```

:class="name" 语法将 CSS 类绑定到 name 变量，实际上是将 name 的值用作元素的 CSS 类名称。因此，当 name 的值与你的 CSS 类名匹配时，相关的样式将应用于元素。

在你的代码中，name 的初始值是 "title"，这正好与你定义的 .title CSS 类的名称匹配。因此，在页面加载时，<div> 元素将应用名为 "title" 的 CSS 类，从而应用了与 .title 类相关的样式。
```

```
練習：
<script setup>
    import {ref} from "vue";
    let state = ref({
        title : "網站標題",
        className : "title"
    });
    let handler = function(){
        state.value.title = "新的網站標題";
        state.value.className = "highlight";
    };
</script>
<template>
   <div :class= "state.className"> {{ state.title }}</div>
   <button @click ="handler" >按鈕</button>
</template>
<style>
    .title{color:grey}
    .highlight{color:red}
</style>
```

### 表單輸入元件
接受使用者輸入的HTML元件

- 單行、多行文字輸入
<input type="text"/>
<textarea></textarea>>

- 多選方框、單選圓框
<input type="checkbox"/>
<input type="radio"/>

- 下拉式選單
<select>
    <option></option>
    <option></option>
</select>

### 輸入元件、和響應式的綁定
- 使用v-model="響應式狀態名稱"
輸入的資料和響應式狀態連動

```
<script setup>
    import {ref} form "vue";
    let text = ref("預設的文字");
</script>
<template>
    <input type="text" v-model="text"/>
    <div>輸入文字：{{ text }}</div>
</template>
<style scoped>
    /*CSS設定*/
</style>
```

#### 單選框範例
多個選擇框綁定同一個響應式狀態
資料和標籤的value屬性對應

```
<script setup>
import { ref } from "vue";
let gender = ref(null);
</script>
<template>
  <input type="radio" value="male" v-model="gender" id="male"/><label for="male" class="male">男</label>
  <input type="radio" value="female" v-model="gender" id="female"/><label for="female" class="female">女</label>
  <div>選擇的性別：<span :class="gender">{{ gender }}</span></div>
</template>
<style scoped>
.male{color: lightblue;}
.female{color: pink;}
</style>

```

#### 多選框範例
綁定的響應式狀態使用陣列資料
資料和標籤的value屬性對應

```
<script setup>
    import {ref} from "vue";
    let fruits = ref([]); 
</script>
<template>
    <input type="checkbox" v-model="fruits" value="apple"/>蘋果
    <input type="checkbox" v-model="fruits" value="gruava"/>芭樂
    <input type="checkbox" v-model="fruits" value="grape"/>葡萄
    <div>選擇的水果：{{ fruits }}</div>
</template>
<style scoped>
    /*CSS設定*/
</style>
```

#### 下拉式選單範例
v-model綁定select標籤
資料和option標籤的value屬性對應

```
<script setup>
    import {ref} from "vue";
    let gender = ref("");
</script>
<template>
<select v-model="gender">
    <option value="">請選擇</option>
    <option value="male">男</option>
    <option value="female">女</option>
</select>
    <div>選擇的性別是：{{ gender }}</div>
</template>
<style scoped>
    /*CSS設定*/
</style>
```

```
練習：
<script setup>
    import {ref} from "vue";
    let name = ref("");
    let reset = function(){
        name.value = "";
    }
    let gender = ref("");
    let interest = ref([]);
    let mood = ref("");
</script>
<template>
    <h3>單行輸入匡</h3>
    請輸入名字：<input type="text" v-model="name">
    <button @click="reset">清空輸入匡</button>
    <br>
    我的名字是：{{ name }}
    <h3>單選匡</h3>
    性別：<input type="radio" value="male" v-model="gender">男生<input type="radio" value="female" v-model="gender">女生
    <br>
    我的性別是：{{ gender }}
    <h3>多選匡</h3>
    <input type="checkbox" value="打棒球" v-model="interest">打棒球
    <input type="checkbox" value="看電影" v-model="interest">看電影
    <input type="checkbox" value="吃美食" v-model="interest">吃美食
    <input type="checkbox" value="運動" v-model="interest">運動
    <input type="checkbox" value="看書" v-model="interest">看書
    <br>
    我的興趣是：<ul>
    <li v-for="myInterest in interest">{{ myInterest }}</li>
    </ul>
    <h3>下拉式選單</h3>
    今天心情怎麼樣：<select name="" id="" v-model="mood">
        <option value="">請選擇</option>
        <option value="普通">普通</option>
        <option value="平靜">平靜</option>
        <option value="焦慮">焦慮</option>
        <option value="累">累</option>
        <option value="無奈">無奈</option>
    </select>
    <br>
    <div>我今天的心情：{{ mood }}</div>
</template>
<style>

</style>
```

### 單一組件
整個網頁由單一組件組成
```
<script setup>
    //Javascript程式碼
    console.log("我的首頁");
</script>
<template>
    <!--HTML樣板結構-->
    <nav>
        網頁導覽列
    </nav>
    <main>
        <div>網頁主區塊一</div>
        <div>網頁主區塊二</div>
    </main>
</template>
<style scoped>
    /*CSS設定*/
    nav{font-weight:bold};
    main{padding:30px 0xp}
</style>
```
### 組件的切割
- 將網頁根據實際的畫面區塊切割成多個組件
將上述單一組建網頁架構分為：App.vue + Nav.vue + Main.vue

```
App.vue：
<script setup>
    import Nav from "./Nav.vue";
    import Main from "./Main.vue";
</script>
<template>
    <Nav></Nav>
    <Main></Main>
</template>
<style scoped>
</style>
```
```
Nav.vue：
<script setup>
    console.log("導覽頁相關的程式碼");
</script>
<template>
    <nav>
        網頁導覽列
    </nav>
</template>
<style scoped>
    nav{font-weight:bold};
</style>
```
```
Main.vue：
<script setup>
    console.log("主區塊相關的程式碼");
</script>
<template>
    <main>
        <div>網頁主區塊一</div>
        <div>網頁主區塊二</div>
    </main>
</template>
<style scoped>
    main{padding:30px 0xp};
</style>
```

### 載入組件
- 在程式中載入其他的組件
import  組建名稱 from "組建檔案路徑";
```
範例：
<script setup>
        import NavComp from "./Nav.vue";
</script>
```
### 使用載入的組件 
- 在樣板中使用載入的組件
`<組建名稱></組建名稱>`
```
範例：
<script setup>
        import NavComp from "./Nav.vue";
</script>
<template>
    <NavComp></NavComp>
</template>
```
練習：
```
單一組件：
<script setup>
    import {ref} from "vue";
    let text = ref("主要的網站內容");
    let change = function(){
        text.value = "新的網站內容";
    };
</script>
<template>
    <nav>基本的導覽列</nav>
    <main>
        <div @click = "change">{{ text }}</div>
    </main>
</template>
<style>
    nav{padding:10px}
    main{padding:10px;background-color:pink;};
</style>
```

```
App.vue：
<script setup>
    import NavComp from "./Nav.vue";
    import MainComp from "./Main.vue";
</script>
<template>
    <NavComp></NavComp>
    <MainComp></MainComp>
</template>
<style>

</style>
```
```
Nav.vue：
<script setup>
</script>
<template>
    <nav>基本的導覽列</nav>
</template>
<style scoped>
    nav{padding:10px}
</style>
```
```
Main.vue：
<script setup>
    import {ref} from "vue";
    let text = ref("主要的網站內容");
    let change = function(){
        text.value = "新的網站內容";
    };
</script>
<template>
    <main>
        <div @click = "change">{{ text }}</div>
    </main>
</template>
<style scoped>
    main{padding:10px;background-color:pink;};
</style>
```

### 自訂屬性
組件的使用，自訂屬性；就像是HTML標籤的屬性一樣
- 載入組件
import 組件名稱 from "組件檔案路徑";
- 在樣板中使用載入的組件，並設定屬性
```
<組件名稱
    屬性名稱="資料" 屬性名稱="資料"...
></組件名稱>
```
```
App.vue：
<script setup>
    import Nav from "./Nav.vue";
    import Main from "./Main.vue";
</script>
<template>
    <Nav title="任意的標題"></Nav>
    <Main></Main>
</template>
<style scoped>
</style>
```
```
Nav.vue
<script setup>
    defineProps(["title"]);
</script>
<template>
    <nav>
        {{ title }}
    </nav>
</template>
<style scoped>
</style>
```
- 定義、接受並使用屬性
定義要接收的屬性名稱語法
`defineProps(["屬性名稱","屬性名稱"],...)`

```
App.vue：
<script setup>
    import NavComp from "./Nav.vue";
    import MainComp from "./Main.vue";
</script>
<template>
    <NavComp title ="標題哈囉！！！"></NavComp>
    <MainComp fontcolor="white" bgcolor="black"></MainComp>
</template>
<style>
</style>
```
```
Nav.vue：
<script setup>
    defineProps(["title"]);
</script>
<template>
    <nav>{{ title }}</nav>
</template>
<style scoped>
    nav{padding:10px}
</style>
```
```
Main.vue：
<script setup>
    import {ref} from "vue";
    let text = ref("主要的網站內容");
    let change = function(){
        text.value = "新的網站內容";
    };
    defineProps(["fontcolor","bgcolor"]);
</script>
<template>
    <main :style="{color:fontcolor,backgroundColor:bgcolor}">
        <div @click = "change">{{ text }}</div>
    </main>
</template>
<style scoped>
    main{padding:10px;background-color:pink;};
</style>
```
注意此寫法：
:style="{**backgroundColor**:bgcolor}">

### 自訂事件處理
#### 建立組件的自訂事件
使用@符號+自訂事件名稱

- 載入組件
import 組件名稱 from "組件檔案路徑";
- 在樣板中使用載入的組件，並建立自訂事件
<組件名稱
    @自訂事件名稱="處理函式"
    @自訂事件名稱="處理函式"
    ...></組件名稱>

```
範例：
<script setup>
    import Nav from "./Nav.vue";
    let 函式名稱=function(){...};
</script>
<template>
    <Nav @handler="函式名稱"></Nav>
</template>
```

#### 組件內部呼叫自訂事件方法(一)
樣板語法的標準事件中使用
`$emit('自訂事件名稱')`

範例
```
App.vue：
<script setup>
    import NavComp from "./Nav.vue";
    import MainComp from "./Main.vue";
    import {ref} from "vue";
    let text = ref("測試文字");
    let change = function(){
        text.value="修改的文字";
    };
</script>
<template>
    <NavComp></NavComp>
    <MainComp @changeText="change"></MainComp>
    <div>{{ text }}</div>
</template>
<style>
</style>
```

```
Nav.vue：
<script setup>
</script>
<template>
    <main>
        <button @click="$emit('changeText')">按鈕</button>
    </main>
</template>
<style scoped>
    main{padding:10px;background-color:pink;};
</style>
```

#### 組件內部呼叫自訂事件方法(二)
JavaScript程式中使用
`defineEmits(["自訂事件名稱",...])`

範例
```
App.vue：
<script setup>
    import Nav from "./Nav.vue";
</script>
<template>
    <Nav @handler="函式名稱"></Nav>
</template>

Nav.vue：
<script setup>
    let emit = defineEmits(["handler"]);
    //呼叫defineEmits(["handler"]會回傳一個可以讓我呼叫自定義組件的函式emit
    let 函式名稱 = funtion(){ emit("handler");};
</script>
<template>
    <nav>
        <button @click="函式名稱">按鈕</button>
    </nav>
</template>
```
<hr>
延伸

![image](https://hackmd.io/_uploads/BJ-FtW5HT.png)

解決方式

![image](https://hackmd.io/_uploads/B1Ulcb9r6.png)


