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