# 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=
```