---
# System prepended metadata

title: Vue.js - Component
tags: [FrameWork-vue.js]

---

# Vue.js - Component
###### tags: `FrameWork-vue.js`

##  ㄧ . 宣告Component
### (一) . instance和component的關係
- Vue的FrameWork設計 : 元件樹。
  1. App是由一個元件所構成的樹狀結構所組成的。
  2. 其中的根元件就稱為instance，由```craeteApp```方法建構出來。
  3. 而非根元件的其他元件，就稱為Component，由```craeteApp```方法的App建構。
- Instance和Component的建構順序 ： 
  1. 建構app。
  2. 建構Component。
  3. mount app : 注意，mount app方法必須在最後使用。

### (二) . Component宣告
- 方法一 ： global註冊，可以使整個App instance都可以使用。
  1. 語法 ： ```app.component('元件名稱', option)```。
  2. 特性 ： 即使不使用此Component，他還是會被編譯下去。
```javascript=
const app= Vue.createApp({
    data(){
        return{
            title_array :['Test-01', 'Test-02']
        }
    },
    template:`
    <test-title  v-for='title in title_array'
    :title='title'></test-title>        `
});

app.component('test-title',{
    props: ['title'],
    template:`<h2>{{title}}</h2>`
});
app.mount('#app');
```

- 方法二 ： local註冊，只有註冊的單一個instance或Component可以用。
  1. 語法 ： 在要使用的元件加入『component』的option，輸入key-value對。
  2. 特性 ： 不使用此Component，他就不會被編譯下去。
  3. 注意 ： Component option中的屬性name會被當為component的name。
```javascript=
const ComponentA={ /* option */ };
const ComponentB={ /* option */ };
const app=Vue.createApp({
    component:{
         'component-a': ComponentA,
         'component-b': ComponentB,
         /* 
          *   ES6 寫法 ： ComponentA, 
          *   等於ES5寫法 ： 'ComponentA' : ComponentA
          * */
    }
})
```
## 二 . Props 
### (一) . Props的功用
- Props的功用 ： **由父元件，傳遞data到子元件。**
- Props的基本語法 ： 
  1. 父元件 ： 在使用子元件的tag上，加入```name='data'```。
  2. 子元件 ： 在option中加入『props』的array，並輸入name的字串。
```javascript=
const app= Vue.createApp({
    template:`
    <test-title  title= 'Test-01'></test-title>
    <test-title  title= 'Test-02'></test-title>  `
});

app.component('test-title',{
    props: ['title',],
    template:`<h2>{{title}}</h2>`
});
app.mount('#app');
```
- 使用 ： Props可以傳遞動態的資料 
  1. 靜態資料 ： 固定的字串等等。
  2. 動態資料 ： father元件內的data。 
- 使用 ： Binding props，動態傳輸的方法。
  1. 用v-bind 綁定props的name attribute。
  2. 綁定的字串內讀取的會是父元素的變數名稱。 
```javascript=
const app= Vue.createApp({
    data(){
        return{
            title_array :['Test-01', 'Test-02']
        }
    },
    template:`
    <test-title  v-for='heading in title_array' :title='title'
    :content='heading'></test-title>        `
});

app.component('test-title',{
    props: ['title','content'],
    template:`<h2>{{title +' : '+ content}}</h2>`
});
app.mount('#app');
```

### (二) . Prop Validation
- Props type check : 可以檢查props傳入的型別。
  1. 語法 ： props改用object包住。
  2. 語法 ： 改為key-value pair : key為名稱，value為type。
  3. 語法 ： 也可以多重型態，value用array包住。
  5. 若型別錯誤，會有warning 。
- Validator function : 自訂的檢查行為。
  1. 語法 ： key-value pair改用object包住，並加上validator 關鍵字。
  2. 注意 ： 此function要有回傳值。
- default 、 require屬性 : 可以預設props的內容。
  1. default語法 ： key-value pair改用object包住，並加上default關鍵字。
  2. require語法 ： key-value pair改用object包住，並加上require關鍵字。  
```javascript=
pp.component('my-component', {
  props: {
    // Basic type check (`null` and `undefined` values will pass any type validation)
    propA: Number,
    // Multiple possible types
    propB: [String, Number],
    // Required string
    propC: {
      type: String,
      required: true
    },
    // Number with a default value
    propD: {
      type: Number,
      default: 100
    },
    // Object with a default value
    propE: {
      type: Object,
      // Object or array defaults must be returned from
      // a factory function
      default: function() {
        return { message: 'hello' }
      }
    },
    // Custom validator function
    propF: {
      validator: function(value) {
        // The value must match one of these strings
        return ['success', 'warning', 'danger'].indexOf(value) !== -1
      }
    },
    // Function with a default value
    propG: {
      type: Function,
      // Unlike object or array default, this is not a factory function - this is a function to serve as a default value
      default: function() {
        return 'Default function'
      }
    }
  }
})
```
### (三) . 使用概念 ： 
- Style : 命名方式的注意，如果你是用template渲染的話。
  1. 用camelCase在元件的option。
  2. 用kebab-case在父元件的props傳入。
```javascript=
const app = Vue.createApp({})

app.component('blog-post', {
  // camelCase in JavaScript
  props: ['postTitle'],
  template: '<h3>{{ postTitle }}</h3>'
})
```
```htmlembedded=
<!-- kebab-case in HTML -->
<blog-post post-title="hello!"></blog-post>
```
- 單一資料流 ： 

## 三 . Emit
### (一) . Emit Event的功用
- Emit Event的功用 : **由子元件，向父元件溝通的管道**。
- Emit Event的基本語法 ： 
  1. 子元件 ： ```this.$emit('event name', pare)```。
  2. 父元件 ： 在子元件的tag加入『$v-on:event name ='methods'$』。
```javascript=
const app=Vue.createApp({
    data(){
        return {
            age:15
        }
    },
    methods:{
        addAge(){
            this.age++;
        }
    },
    template:`
        <div>
            <p>{{age}}</p>
            <my-button @add='addAge' ></my-button>
        <div>
    `
});

app.component('myButton',{
    methods:{
        onClick(){
            this.$emit('add');
        }
    },
    template:`
        <button @click='onClick'>Push</button>
    `
});

app.mount('#app');
```
### (二) . Event Validation
- $custom\ event$ : 
  1. 語法 ： 可以用array和在option中加入emit去定義event。
  2. 功用 ： 可以使得程式碼比較容易閱讀。
```javascript=
app.component('myComponent',{
    emit:['onclick', 'submit']
})
```
- $event\ Validation$ : 概念和props validation相同。
  1. 語法 ： 用object包住emit的option，並用key-value對表示event-validator。
  2. 功用 ： 可以使事件觸發的比較安全。
```javascript=
app.component('custom-form', {
  emits: {
    // No validation
    click: null,

    // Validate submit event
    submit: ({ email, password }) => {
      if (email && password) {
        return true
      } else {
        console.warn('Invalid submit event payload!')
        return false
      }
    }
  },
  methods: {
    submitForm() {
      this.$emit('submit', { email, password })
    }
  }
})
```
### (三) . ```v-modal```綁定
- 功用 ： 綁定子元件的資料直接同步於父元件。
- 

## 四 . Slot
### (一) . Slot的功用 
- Slot的功用 ： 讓父元件傳入需要陳列的元素在子元件上。
- Slot的語法 ： 
  1. 子元件 ： 加入```<slot></slot>```代表動態接受的陳列元素。
  2. 父元件 ： 在使用子元件的tag中間加入資料。
  3. 注意 ： 子元件沒有加入slot下，任何父元件在子元件tag中加入的都被discard。
```htmlembedded=
<todo>
   <slot></slot>
</todo>

<div>
     <todo>
         to do nothing <!-- to do nothing 到<slot>的區段 -->
     </todo>
</div>
```
- Slot動態輸入 ：
  1. 連接父元件資料 ： 可以在父元件使用子元件的地方加入```{{}}```填入父元件資料。 
  2. default行為 ： 可以在子元件的```<slot></slot>```中加入預設內容。
```htmlembedded=

```
