---
# System prepended metadata

title: Vue JS初探(上)

---

# Vue JS初探(上)

## 目錄
[toc]

## What is framework
在網頁的發展歷史中，一開始大家都是直接透過原本的原生函式來撰寫網頁應用程式，因為當時的專案都不大，網路以及電腦也沒辦法負荷太多的程式碼，所以沒有太大影響。後來隨著專案越來越大，數量也越來越多，就出現了許多重複出現的需求，例如說針對一個有特定屬性的物件操作。秉持的「不要重複造輪子」的想法，大家會把這些常出現的東西寫再一起，變成所謂的「函式庫」，之後需要功能時就直接去呼叫這些已經寫好的函式，不用再重複撰寫。這樣一來降低了維護的成本，也提高的開發的效率。這樣的東西也衍伸出「黑盒子」的概念。

隨著專案更加龐大，現有的函式庫已經沒辦法有效地解決一些問題，例如說如果要開發一個網站動畫，函式庫能直接執行的功能有限，就變回當初用原生函式撰寫的狀況差不多，同時對於物件的概念日益盛行。於是比函式庫更加龐大，架構也更加完整的東西出現了：「框架」。
### 使用框架的好處
- 方便管理，由資料決定畫面，將資料從介面中抽取出來，每個畫面都是對資料處理過後的呈現，尤其是在動態JS中有關DOM的操作
- 將腳本和程式模組化，使得各組件只需要處理組件內的事，外部引用的組件來決定怎麼使用、提供什麼資料給組件，藉由簡單的切分權責，加上前述的由資料決定畫面，就能讓各個組件的任務單一，並且能被重複使用。
- 提高server和browser間資料存取的效率

## Then, what is Vue?
- Front-end, JavaScript/TypeScript framework
    - Vue是個發展中的前端框架，可以輕易的和其他library或現有專案整合
    - 像是把Vue和既有的HTML做整合，這讓你可以像使用插入性替換的函式庫一樣來使用Vue

- Used to **dynamic** & **data-driven** wedsites(SPA's)
    - Easy to let user use DOM and manage data
    - Vue是一套前端框架，目的是讓網頁可以動態Load資料，有別於傳統靜態的頁面將內容寫死在source code裡面
- Used to create stand-alone widgets
    - Vue提供漸進式的方法來撰寫網頁內容。就像大部分的框架，Vue讓創造可以重複使用的網頁內容區塊（稱為widget元件）

![](https://i.imgur.com/8KHATjy.png)

## The characterists of Vue websites
### Makw a comparison 
- between the progressive JavaScript framework and the imperative programming

|type|differnece|
|----|----------|
|the progressive JavaScript framework(渲染式框架)|透過簡單的語法，完成對目標的綁定，對於更動的內容更易修改|
|the imperative programming(指令式編成)|像是JavaScript的DOM，一個指令對應一個物件|

### MVVM模式
![](https://i.imgur.com/EmnflwQ.png)
- 將DOM監聽的事件狀態與狀態(Model)綁定，由JS的物件管理。使用者在畫面(View)上所做的更動，ViewModel層上的Vue.js就會回傳到有JS的物件表式的Model，Model修改後同步更新View上對影的內容
- 操作的最小單位從DOM中的節點變為一個個component的組合，而每個components都有其模板與樣式JS code
    - DOM Tree --> Components Tree

### The routing between browser and server
- 前端模擬路由，用於實現SPA；that is，換頁時不需向後端發出請求
- All routing is done in the browser instead on the sever
- When we interact with the components, the website doesn't go to the server and instead Vue handles in the browser(much faster and smoother)--Single Page Application
#### Don't use Vue or something similar like react
![](https://i.imgur.com/wcyfFtv.png)
- the browser is constantly making a request to the server for every new pages(a bit slow)

#### Use Vue
![](https://i.imgur.com/ppZWhnJ.png)
- Vue can be injected to different websites
- Vue bundles take control of the website in the browser, and it renders the different Vue components needed for the page and take over the link of it

### Single Page Application(SPA)
- Only a single HTML page sent to the browser
- Vue intercept(攔截) subsequent(後來的) requests and handles "page" changes in the browser by swapping what components are shown on the page
- Result is in much faster and smoother 

### Instal the extension "Vetur"
![](https://i.imgur.com/a2fRIw7.png)

- bring some features for Vue appication


## Basic template
- `<script src="https://unpkg.com/vue@3.0.2">`是一種對於Vue形式的引用，在此我所使用的版本為3.0.2    
    - 也能以`<script src="https://unpkg.com/vue@next">`表示使用最新版的Vue
### Example
![](https://i.imgur.com/kjoiso6.jpg)
#### HTML的操作
1. 設立讓HTML掛載的節點，像是id,class,tag
2. 需綁定的內容以{{}}表示
    - name of the property we want to output use double curly braces
    - We can't use those variables outside the scope of Vue "root"
#### 建立Vue的框架
3. 利用Vue.createApp()這個method，建立實體物件(以root為例)
    - pass in the object and represent something called "root component" in view
    - controlling the section in the web page
4. data()函式能將JavaScript建立的對應object資料，用於HTML中綁定
5. return a data object
    - it can be dynamic changing value
6. 將Vue的實體物件掛載至節點之上
    - this method tells the app at what point or where in the DOM to mount this application
    - any dynamic data we want to output inside this app element or any events(like click,mousemove....). All of that will be controlled by our view
    - "root"物件內能夠回傳給html一物件，也能在JS檔中使用，作為動態操作value的依據 
#### 補充 -- template
```htmlembedded=
const app = Vue.createApp({
  template:`<h2>I am the template</h2>`
});
app.mount('#app'); 
```
<hr>

### methods - how to make our website be active
#### Methods and computed
- 監聽事件觸發後，透過函式的手法，對資料進行操作
- 若要使用data()內的屬性，要用this去做存取，也能用帶有參數的形式
    - reference to the component itself 
(後續再詳細說明，下面以methods為例)

#### Events--試問DOM中的AddEventListener和getElementById等method的靈壓?
`v-on:click="age++"`作為JavaScript中的物件綁定，語法為`v-on:使用者行為=執行程式`
- v-on is a directive which allow us to react to different type of events
- update the data() in the script

`@click` 其中的@為v-on的簡寫
`v-if`像是JavaScript中的條件判斷作用於DOM之上(這說法有點怪?舉例!!)
- In this case, v-if evalute what is in the quote,if it's true,then show this

`v-for`用於連續生成目標相近的element
- we use v-for to cycle through an array of the data and output a bit of template for each items or output to users some kind of list

`v-bind`用來動態新增或綁定一個或多個HTML屬性（src、class、style）
#### Example 1

```htmlembedded=
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="https://unpkg.com/vue@next"></script>
</head>
<body>
  <div id="root">
    <p>{{commodities}}-{{price}}</p>
    <button v-on:click="price++">rise</button>
    <button @click="commodities = 'nothing'">nothing</button>
    <br>
    <button @click="changegoods">Change goods </button>
    <br>
    <button @click="changegoods_re('Ten days wonder')">Change goods 2</button>
    <div v-if="true">
      <p>{{commodities}} || {{price}} </p>
    </div>
  </div>

  <script>
const app = Vue.createApp({
  data(){
    return {
      commodities:'The final Banpire',
      price:54
    }
  },
  methods: {
    changegoods(){
      console.log('you click me');
      this.commodities = 'Boyce ODE';
    },
    changegoods_re(commodities){
      this.commodities = commodities;
    }
  }
});
app.mount('#root');

  </script>
</body>
</html>
```

#### Example 2
```htmlembedded=
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Learning Vue</title>
  <script src="https://unpkg.com/vue@next"></script>
</head>
<body>
  <div id="app">
    <div v-if="showBooks">
      <p>{{ books[0].title }} - by {{ books[0].author }}</p>
      <p>{{ books[1].title }} - by {{ books[1].author }}</p> 
    </div>
    <div v-else>
      <p>Click the button below to show books</p>
    </div>
    <button @click="toggleShowBooks">
      <span v-if="showBooks">Hide books</span>
      <span v-else>Show books</span>
    </button>

      <ul>
        <li v-for="book in books">
          <h3>{{book.title}}</h3>
          <h3>{{book.author}}</h3>
        </li>
      </ul>
    
  </div>

  <script>
    const root = Vue.createApp({
      data(){
    return{
      showBooks:true,
      books: [
        {title:'The final Banpire',author:'Duncan',display:true},{title:'JavaScript Eloquent',author:'Johnny',display:true},{title:'Boyce ODE',author:'Fanny',display:true},{title:'Duncan is handsome',author:'Duncan',display:false}
      ]
    }
  },
  methods:{
    toggleShowBooks(){
      this.showBooks=!this.showBooks;
    }
  }
})
root.mount('#app');
  </script>
</body>
</html>
```

### v-bind
- 目的:用於和HTML與CSS之間的資料綁定
- 寫法為`v-bind:html屬性="對應的object"`，其中，`v-bind:`可簡化為`:`
    - 複習一下html的屬性列表
        - `<a href="">` `<img src="">` `<div class="">`等等 

#### Example 3
```htmlembedded=
<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8" />
		<meta http-equiv="X-UA-Compatible" content="IE=edge" />
		<meta name="viewport" content="width=device-width, initial-scale=1.0" />
		<link rel="stylesheet" href="style.css" />
		<script src="https://unpkg.com/vue@next"></script>
		<title>Vue Learn</title>
	</head>
	<body>
		<div id="app">
			<a href="https://www.youtube.com/c/%E5%A4%9C%E6%A9%98%E5%AF%A6%E6%B3%81">夜橘YT</a>
			<hr>
			<a v-bind:href="link">豆漿YT</a>
		</div>
		<script>
      const app = {
        data() {
          return {
            link: "https://www.youtube.com/user/Qiyoudaoyi",
          };
        },
      };
      Vue.createApp(app).mount("#app");
    </script>
	</body>
</html>

```

#### Example 4
```htmlembedded=
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="https://unpkg.com/vue@next"></script>
  <style>
    body{
      background-color: white;
      max-width: 960px;
      margin: 20px auto;
    }
    p, h3, ul{
        margin: 0;
        padding: 0;
      }
    li{
      list-style-type: none;
      background: #fff;
      margin: 20px auto;
      padding: 10px 20px;
      border-radius: 10px;
      display: flex;
      align-items: center;
      justify-content: space-between;
    }
    li.fav{
      background: #ff9ed2;
      color: white;
    }
    img{
      width:400px;
      height:200px;
    }
  </style>
</head>
<body>
  <div id="app">
    <p>{{filterBooks}}</p>
    <div>
      <!-- v-bind用於在Vue框架開發時，綁定HTML屬性 -->
      <a v-bind:title="hint">把滑鼠移過來</a>
    </div>
    
    <div v-if="showBooks"> 
      <ul>
        <li v-for="book in filterBooks" v-bind:class="{fav: book.isFav}" @click="toggleFav(book)">
                                        <!-- If the value is true, then we can apply this style -->
          <img :src="book.img" v-bind:alter="book.owner">
          <h3 style="font-size:100px">{{book.title}}</h3>
        </li>
      </ul>
    </div>

    <div v-else>
      <p>Click the button below to show books</p>
    </div>
    
    <button @click="toggleShowBooks">
      <span v-if="showBooks">Hide books</span>
      <span v-else>Show books</span>
    </button>
    
  </div>

  <script>
    const app = Vue.createApp({
      data(){
    return{
      hint:'哈哈笑死',
      showBooks:true,
      books: [
        // Note that the property like "img" is a kind of HTML property
        // The purpose to use the property "isFav" due to what we want to display 
        {title:'The final Banpire',owner:'Setsuna',img:'picture/Setsuna.png',isFav:true},
        {title:'JavaScript Eloquent',owner:'Shioriko',img:'picture/Shioriko.png',isFav:false},
        {title:'Boyce ODE',owner:'Ayumu',img:'picture/Ayumu.png',isFav:true}
      ]
    }
  },
  methods:{
    toggleShowBooks(){
      this.showBooks=!this.showBooks
    },
    toggleFav(book){
      book.isFav = !book.isFav
    }
  },
  computed:{
    filterBooks(){
      return this.books.filter((book)=> book.isFav)
    }
  }
})
app.mount('#app');
  </script>
</body>
</html>
```
### v-modal
- 一種雙向綁定
- v-model常用於表單及元素來做雙向數據綁定，結合v-bind跟v-on一樣，用v-bind初始綁定與呈現資料，用v-on監聽事件來做資料更新。
#### Example 5
```htmlembedded=
<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8" />
		<meta http-equiv="X-UA-Compatible" content="IE=edge" />
		<meta name="viewport" content="width=device-width, initial-scale=1.0" />
		<script src="https://unpkg.com/vue@next"></script>
		<title>Vue Learn</title>
	</head>
	<body>
		<div id="app">
			<input type="text" v-model="text" />
			<div>{{ text }}</div>
		</div>
		<script>
      const app = {
        data() {
          return {
            text: "",
          };
        },
      };
  Vue.createApp(app).mount("#app");
    </script>
	</body>
</html>
```

### Computed 和 Methods 比較
- 兩者的差異在於， computed 會把計算後的結果暫存起來，如果裡面使用的資料沒有變動，就不會重複執行，以避免過度調用methods；反之，methods 只要在 HTML 裡面被使用幾次就會執行幾次。
- 在實際使用上，computed較為簡潔，尤其在重複使用相同的計算重複使用，但須注意computed需要return出一個值
- computed 的缺點是無法帶入參數，所以在設計時需考量，如果有有帶入參數的需求，就應使用 methods。

#### Example 6
```htmlembedded=
<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8" />
		<meta http-equiv="X-UA-Compatible" content="IE=edge" />
		<meta name="viewport" content="width=device-width, initial-scale=1.0" />
		<script src="https://unpkg.com/vue@next"></script>
		<title>Vue Learn</title>
	</head>
	<body>
		<div id="app">
			<input type="number" v-model="Num" />
			<div>{{ Num }}</div>
			<div>{{ time }}</div>
			<div>{{ output }}</div>
			<button v-on:click="calculate()">Calculate</button>
			<button @click="calculate()">Calculate</button>
			<div>{{ times }}</div>
		</div>
		<script>
      const app = {
        data() {
            return {
                time: 10,
                Num: 0,
                output: 0,
            };
        },
        methods: {
            calculate() { this.output = this.time * this.Num; },
        }, 
        computed: {
            times() { return this.Num * this.time; },
        },
    };
    Vue.createApp(app).mount("#app");
    </script>
	</body>
</html>
```

## Vue CLI
![](https://i.imgur.com/sozIV0x.png)

- 全稱為Vue.js Command-Line Interface
- 由Vue.js核心團隊開發，提供開發者快速建置 Vue.js 專案並整合相關工具鍊的一套指令列 (command-line) 工具
- 它的特色是提供開發者在短短的幾分鐘時間內，即可快速建置一個立即可用的 Vue.js (含 2.x/3.x) 示範專案，這個專案同時也內建了 Router、Hot-Reload、ES Lint 與 dev-Server 等功能。
- a tool to boilerplate full vue applications which come along to the configuration and structure that we need to create full vue website

### setup Vue CLI

1. 到[官網](https://nodejs.org/zh-tw/)安裝Node.js，建議安裝長期維護版
![Node.js官網圖片](https://i.imgur.com/SJ1BkVI.png)

2. 打開command prompt，並輸入`node -v`，透過顯示版本的手段，以確認是否安裝Node.js
3. 打開terminal，輸入`npm install -g @vue/cli`(下圖為示意圖)
![](https://i.imgur.com/7UpwWYR.png)
4. 先創一個資料夾，用以放入專案，並在terminal輸入`vue create [專案名稱]`
![](https://i.imgur.com/5bUd2tJ.png)
5. 選擇Vue 3 或 Manually select features(下面以後者作為操作)
6. features目前只需要Babel，透過空白鍵來選擇(之後提到Router會在建立一次cli，到時操作會在說明)
![](https://i.imgur.com/Dc8SJzZ.png)
7. 其他選項
![](https://i.imgur.com/qRp3oHC.png)
8. 安裝完後，進入那專案並由vscode打開即可
![](https://i.imgur.com/XkJwGyl.png =50%x)

#### 簡單相關的file介紹
- `node_modules`: library --> if we install another library/package, they will be put in there
- `public`:contain the index.html file, which is sent to the browser initially
- `src`:the place where we write the source code
    - contain main.js, which kickstarts our applications
    - we use the method `createApp()`, which directly import "createApp" function from 'vue' library
    - import a component from .vue file 
    - 載入整個專案中所使用到的所有JavaScript檔案
```htmlembedded=
import { createApp } from 'vue'
import App from './App.vue'

createApp(App).mount('#app')
```
#### To preview our vue application in a browser
- 打開terminal，並輸入`npm run serve`，然後會得到一個連結`http://localhost:8080/`，打開即可(之後能從控制台觀察一下)
    - 打開console後，all inside in the empty div with '#app'

## Vue元件檔-SFC(Single File Component) 單一元件檔
### What is this?
一開始我們的專案都是透過Javascript去做相對應的渲染，但是當專案逐漸龐大的時候，很多可以重複用的元件都必須重複撰寫，這不僅會提升專案維護的難度，更會讓專案的架構變得複雜。

為了解決這樣的問題，Vue提供一個新的選項：SFC(Single File Component)，作為單一元件的檔案。這樣的好處是當我們在組織程式碼的結構的時候， 可以很清楚地看出整個專案的架構與元件的分割關係，進而達到更高的可讀性及可重用性

### How to do?
以剛剛生成的app.vue為例
```htmlembedded=
<template>
  <img alt="Vue logo" src="./assets/logo.png">
  <HelloWorld msg="Welcome to Your Vue.js App" />
</template>

<script>
import HelloWorld from './components/HelloWorld.vue'

export default {
  name: 'App',
  components: {
    HelloWorld
  }
}
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>
```

- 一個vue檔內會有三個部分，分別是<template\>、<script\>與<style\>。下面將逐一介紹
備註:components 中的.vue檔，檔名必須用大寫名稱，為了在<template\>不會和其他html tag 搞混
    
### template
- 這個部分類似html，就是撰寫這個元件長什麼樣子，寫法類似html，可以使用像是{{}}、v-if等vue的指令與語法
- With a view to not being in mess, we spilt those parts into different components. Then, when we render(打底) the components into the DOM, its template will be injected into the DOM.
- use the way of "ref" to store a refernece to a DOM element inside a variable, then, we can use regular JS way to manipulate it
  - Just like the way of queryselector of DOM
### script
- 這個部分的寫法比較特殊，原則上是寫Javascript，也就是這個元件會怎麼動，但是由於這個是元件檔，所以會需要有匯出元件的部分。
- 在匯出的部分，會需要多提供這個元件的名稱(name: string)，還有這個元件所使用到的元件(object list)，剩下的部分就是與前面所提及的相似，例如data，computed等等。
- represent the root components as an object
- components屬性中，用於registering any extra components we use inside this component
### style
- 就是CSS，不過要注意CSS汙染，例如底下這樣的寫法，會導致整個元件的h1都被設定大小為100px，包括引用的元件。

```javascript=
<style>
h1 {
    font-size:100px;
}
</style>
```
而這樣的問題可以透過增加scoped標籤解決
- `<style scoped>` 
    - we can add "scoped" attribute to limit CSS to this component only 
    - if we use "scoped" attribite on, it means that these styles will now only applay to whatever in the component
    - it's not working and it won't apply this style to anything outside the components
```javascript=
<style scoped>
h1 {
    font-size:100px;
}
</style>
```

### multiple components--to nest other components as html tags
![](https://i.imgur.com/WnMlv0t.png)
- 將內含的HelloWorld.vue改為下面的Modal.vue
```htmlembedded=
<template>
  <div class="backdrop">
    <div class="modal">
      <h1>Modal title</h1>
      <p>modal content</p>
    </div>
  </div>
</template>

<style>
.modal{
  width:400px;
  padding:20px;
  margin: 100px auto;
  background:white;
}
.backdrop{
  top:0;
  position:fixed;
  background:rgb(0, 0, 0, 0.5);
  width:100%;
  height: 100%;
}
</style>

<style scoped>
h1{
  color:aqua;
  font-size: 100px;
}
</style>
```
然後在App.vue中引入Modal這個component
```htmlembedded=
<template>
<div>
  <h1>{{title}}</h1>
  <Modal/>
  <h1>we can write any html components here!!</h1>
  <input type="text" ref="name">
  <button @click="handleclick">click me</button>
</div>
</template>

<script>
import Modal from './components/Modal.vue'

export default {
  name: 'App',
  components: {Modal},
  data(){
    return{
      title:'My first Vue app :)'
    }
  },
    methods:{
      handleclick(){
        console.log(this.$refs.name);
        this.$refs.name.classList.add('active');
        this.$refs.name.focus();
      }
    }
}
</script>

<style>
/* global --> inside the component file they apply to any element on the page*/
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
h1{
  border: 1px solid red;
  display: inline-block;
  padding-bottom: 10px;
}
.active{
  color:blueviolet;
}
</style>
```
- 在`<template>`中為該component插入的位置，在此以`<Modal/>`表示
- 在`<script>`中引入該.vue的位置，在此以
`import Modal from './components/Modal.vue'`表示
- 也要在default物件中裡的components物件註冊child component
- for `$refs`, we can access on the refs object "any ref" that we name in the template

#### 附註:`<template>`出現error，顯示出The template root requires exactly one element.的狀況
- 原因:vue的模板只容許一個element，因此出現多個element便會報錯(這問題多出現於設定為Vue2的情況)
- 解決方法:
    - 將`<template>`中的內容**以一個`<div>`包裝**
    - 到`settings`中，輸入`eslint`，並取消勾選`Validate vue-html in using eslint-plugin-vue
        - eslint-plugin-vue: 提供 Vue Style Guide

## The interaction between Parent Components and Child Components
- 從`<style scoped>`這最簡單的例子便能看出，Vue.js每個components都必須以互為獨立的形式，that is，我們不能從child components中修改parent components或其他components的資料
- 因此，我們需要透過某種屬性或是方法，完成child componens和 parent components 之間的資料傳遞

在撰寫Vue元件檔的時候，各位可能有注意到一行程式碼
```javascript=
<HelloWorld msg="Welcome to Your Vue.js App" />
```
這裡的msg就是Props。==Props就是父元件將資料傳遞給子元件的方式==，或稱元件間溝通的方式，他是一個陣列型態
父元件寫法：
```javascript=
<component :props="data" />
```
其中:props為名稱，data為值

子元件中的寫法
```javascript=
props:[
  "props1",
  "props2"
]
```
在app.vue與helloeorld.vue可以看到範例，使用方法就是直接將它當作資料使用
```htmlembedded
<div>{{ props1 }}</div>
<p>{{ props2 }}</p>
```
- 之前曾提及過Vue能將網頁所需的內容切割成多個components，並將之重複利用；然而，在不能直接取用的前提下，若有從外部引進資料的需求，就需要透過 props 屬性來引用外部的狀態。
- for those html elements, such as`<p>` `<h1>`, we can pass those html datas into the components from App.vue (the parent elements) to child components 
- advantage:
      1. make the components reusable && dynamic 
      2. there are multiple components using the same data that may be a text or an array of items, exc. We have to define that data in one single place
    - which is called "single source of truth/data"

<hr>

### emit語法
- props屬性由parent component傳遞資料給child component，從上到下傳遞。反之，自然也會有下到上的溝通方式
- `emit` is what we use to **customize** events which can be fired from a component and **can be listened from the parent component**
- 語法:
```htmlembedded=
this.$emit('the_customized_event',{title:'this is a title'})
```
其中，emit能接收第二個參數作為想傳遞的資料(也可將之省略)
接著，我們看看下面兩個例子

- 父元件
```htmlmixed=
<template>
  <div id="app">
    <child v-on:childMethod="parentMethod"></child>
  </div>
</template>

<script>
import Child from './components/Child';
export default {
  name: 'App',
  components: {
    Child,
  },
  methods: {
    parentMethod() {
      console.log('Hello World');
    },
  },
};
</script>
```

- 子元件
```htmlmixed=
<template>
  <button @click="handleClick">Emit</button>
</template>

<script>
export default {
  methods: {
    handleClick() {
      this.$emit('childMethod');
    },
  },
};
</script>
```

也可以帶入參數
- 父元件
```htmlmixed=
<template>
  <div id="app">
    <child v-on:childMethod="parentMethod"></child>
  </div>
</template>

<script>
import Child from './components/Child';
export default {
  name: 'App',
  components: {
    Child,
  },
  methods: {
    parentMethod(val) {
      console.log(val);
    },
  },
};
</script>
```

- 子元件
```htmlmixed=
<template>
  <button @click="handleClick">Emit</button>
</template>

<script>
export default {
  methods: {
    handleClick() {
      this.$emit('childMethod', "Hello world!");
    },
  },
};
</script>
```
透過在後方加入參數的方式，可以將值往上傳到父元件

### Example 7
- App.vue
```htmlembedded=
<template>
<div>
  <h1>{{title}}</h1>
  <div v-if="showModal">
    <ThisModal header="This is header" :text="text" theme="sale" @close="ToggleModal"/>
  </div>
  <button @click="ToggleModal">open</button>
</div>
</template>

<script>
import ThisModal from './components/ThisModal.vue'

export default {
  name: 'App',
  components: {ThisModal},
  data(){
    return{
      title:'My first Vue app :)',
      text:"This is a text",
      showModal:false
    }
  },
  methods:{
    ToggleModal() {
      this.showModal = !this.showModal;
    }
  }
}
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
h1{
  border: 1px solid red;
  display: inline-block;
  padding-bottom: 10px;
}
.active{
  color:blueviolet;
}
</style>
```
- ThisModel.vue
```htmlembedded=
<template>
  <div class="backdrop" @click.self="closeModal">
    <!-- 'self' means that only when we click on this and this is the target of the event, it will fire this function-->
    <div class="modal" :class="{sale: theme === 'sale'}">
      <h1>{{header}}</h1>
      <p>{{text}}</p>
    </div>
  </div>
</template>

<script>
export default{
  props:['header','text','theme'],
  methods:{
    closeModal(){
      this.$emit('close');
    }
  }
}
</script>



<style>
.modal{
  width:400px;
  padding:20px;
  margin: 100px auto;
  background:white;
}
.backdrop{
  top:0;
  position:fixed;
  background:rgb(0, 0, 0, 0.5);
  width:100%;
  height: 100%;
}
.modal h1{
  /* make the style more specific */
  color:red;
}
.modal p{
  font-style: normal;
  /* override the global */
}
.modal.sale {
  background-color: brown;
  color:wheat;
}
.modal.sale h1{
  color:white;
}
</style>
```
#### We will illustrate the code step by step
- recall: **data-binded**
1. class屬性作為data-binded，這裡的例子也是很直覺，在`:class="{sale: theme === 'sale'}"`之中，如果sale的value為true(也就是===成立)，則會有css渲染(也就是下方的.madal .sale)
2. 承上，我們能觀察到一個很有趣的比較，就是從`class="modal"`和 `:class="{sale: theme === 'sale'}"`之中，能發現前著的綁定呈  static，而後者呈dynamic的key vlaue pass

<hr>

- first, we pay attention on the property of "**props**"

1. "props"屬性的value透過array表示，將想操作的attribute以**string**的形式放入
2. 將我們所要從parent component的資料，註冊於child component之中，放入child component所插入的位置，像是`<Modal/>` 之中
3. 以"header"為例:在App.vue中，我們不需要在裡面定義和"header"本身有關的資料，因為我們已經在ThisModal.vue中註冊進props屬性綁定的array中；因此，我們能在ThisModal.vue中，直接以{{}}攫取
4. 如果不是用data-binded的形式(也就是:或v-bind:)，操作的內容只能以string的形式；反之，像是數字、陣列、物件等便能進一步操作

<hr>

- second, how to control whether we want to inject the `<ThisModal/>` (that is, the child components)
    - 以此為例，我們希望按下open的按鈕來讓`<ThisModal/>`component 顯示，而**只**按下背景使該component關閉
1. we use property "showModal" to control, and use the way of `v-if` 
2. ThisModal.vue中做為App.vue的child component，利用`
    closeModal(){
      this.$emit('close');
    }`的函式，返回parent component中`<ThisModal header="This is header" :text="text" theme="sale" @close="ToggleModal"/>`v-on所監聽的自訂'close' event，並執行其中的ToggleModal()函式
