組件 (Component) 是 Vue.js 最強大的功能之一。組件能夠擴展 HTML 元素,封裝可重用的代碼。在較高層面上,組件是自定義元素,Vue.js 的編譯器爲它添加特殊功能。在有些狀況下,組件也能夠表現爲用 is 特性進行了擴展的原生 HTML 元素。
也可分爲:html
有結構HTML數組
有樣式CSSapp
有交互(效果)ide
行爲函數
信號量存數據ui
<input type="number" style="outline: 10px solid red" step="3" min="0" max="30" oninput="console.log(1)" onclick="change()">
組件的行爲能夠定製?經過屬性設置this
在Vue中有什麼樣的組件(組件進行分類):
實現基本功能的基礎的組件(最小的元素)
可複用的邏輯組件(業務組件)
頁面組件spa頁面上全部的東西全都是組件:造成了組件樹code
你沒必要把每一個組件都註冊到全局。你能夠經過某個 Vue 實例/組件的實例選項 components 註冊僅在其做用域中可用的組件:component
<child></child>//在html中是使用 var Child = { template: '<div>A custom component!</div>' } var vm = new Vue({ el: "#app", components: { // Child 將只在父組件模板中可用 Child } })
這種封裝也適用於其它可註冊的 Vue 功能,好比指令。
頁面上全部的東西全都是組件:造成了組件樹
// 頭部組件 var AppHead = { template: `<div>app head</div>` }; // 主窗口單元組件 var AppMainUnit = { template: `<div>app main unit</div>` } // 主窗口組件 var AppMain = { template: `<div>app main <app-main-unit></app-main-unit> <app-main-unit></app-main-unit> </div>`, components: { AppMainUnit } } // 側邊欄單元組件 var AppSideUnit = { template: `<div>app side unit</div>` } // 側邊欄組件 var AppSide = { template: `<div>app side <app-side-unit></app-side-unit> <app-side-unit></app-side-unit> <app-side-unit></app-side-unit> </div>`, comp onents: { AppSideUnit } } // 根組件 var vm = new Vue({ el: "#app", components: { AppHead, AppMain, AppSide } })
子組件與根組件的data用法不一樣
根組件data:
var vm = new Vue({ el: "#app", data: { msg: '' }, components: { MyLi } }) <div>{{msg}}</div>調用其中的msg
子組件data:
var MyLi = { //那麼 Vue 會中止運行,並在控制檯發出警告,告訴你在組件實例中 data 必須是一個函數。 data() { console.log(1); return { counter: 0 } }, template: `<button @click='counter++'>{{counter}}</button>` } //根組件 var vm = new Vue({ el: "#app", data: { msg: '123' }, components: { MyLi } }) <my-li></my-li> <my-li></my-li> <my-li></my-li> 輸出結果:0 0 0
組件實例的做用域是孤立的。這意味着不能 (也不該該) 在子組件的模板內直接引用父組件的數據。父組件的數據須要經過 prop 才能下發到子組件中。
var Child = { template: `<span >{{message}}{{myMessage}}</span>`, //聲明當前組件內部可以接受一個message的屬性,若是是駝峯式命名,在傳遞參數時使用小寫, props: ['message','myMessage'] } var vm = new Vue({ el: '#app', data: { parentMessage:'h' }, components: { Child } })
在html中使用:
<child message="hello" :my-message="parentMessage"></child>//父組件賦值到子組件 <child message="hi"></child> <input type="text" v-model="parentMessage"/>//實時同步的pareMessage值
Prop 是單向綁定的:當父組件的屬性變化時,將傳導給子組件,可是反過來不會。這是爲了防止子組件無心間修改了父組件的狀態,來避免應用的數據流變得難以理解。
另外,每次父組件更新時,子組件的全部 prop 都會更新爲最新值。這意味着你不該該在子組件內部改變 prop。若是你這麼作了,Vue 會在控制檯給出警告。
在兩種狀況下,咱們很容易忍不住想去修改 prop 中數據:
Prop 做爲初始值傳入後,子組件想把它看成局部數據來用;
Prop 做爲原始數據傳入,由子組件處理成其它數據輸出。
var Child = { template: `<div @click="childCounter++">{{initCounter}} {{childCounter}}</div>`, props:['initCounter'], data(){ //保存初始值到childCounter並返回,發生變化的是當前的childCounter的值 return {childCounter: this.initCounter} } } var vm = new Vue({ el: "#app", data: { counter: 0 }, components:{ Child } }) 在html中調用: <child :init-counter="counter"></child>
注意在 JavaScript 中對象和數組是引用類型,指向同一個內存空間,若是 prop 是一個對象或數組,在子組件內部改變它會影響父組件的狀態。
var Child = { template: `<div>{{size}} {{normalSize}}</div>`, props: ['size'], computed: { normalSize(){ return this.size.trim().toLowerCase(); } } } var vm = new Vue({ el: "#app", data:{ parentSize: ' THREE' }, components:{ Child } }) 在html中調用: <child :size="parentSize"></child>
咱們能夠爲組件的 prop 指定驗證規則。若是傳入的數據不符合要求,Vue 會發出警告。這對於開發給他人使用的組件很是有用。
要指定驗證規則,須要用對象的形式來定義 prop,而不能用字符串數組:
var Child = { template: `<div>{{pa}} {{pb}} {{pc}} {{pd}} {{pe}} {{pf}}</div>`, props: { pa: Number, pb: [String, Number], pc: { type: Number, required: true//必填 }, pd: { type: Number, default: 100//默認值 }, pe: { type: Object, default: function(){ return { hello : "world" } } }, pf: { type: Number, validator: function(v){ return v > 100 }//自定義屬性判斷 } } } var vm = new Vue({ el: "#app", data:{ pa: 2, pb: "abc", pc: 2, pd: 50, pe: {}, pf: 120 }, components:{ Child } }) 在html中使用: <child :pa="pa" :pb="pb" :pc="pc" :pd="pd" :pe="pe" :pf="pf"></child>
String
Number
Boolean
Function
Object
Array
Symbol
type 也能夠是一個自定義構造器函數,使用 instanceof 檢測。當 prop 驗證失敗,Vue 會拋出警告 (若是使用的是開發版本)。注意 prop 會在組件實例建立以前進行校驗,因此在 default 或 validator 函數裏,諸如 data、computed 或 methods 等實例屬性還沒法使用。