組件(Component)是前端在單頁面應用(SPA)上最好的一種實現方式,把全部功能模塊拆解成單獨的組件,每一個組件都有獨立的做用域,且還能夠相互通訊javascript
在傳統的頁面之間跳轉,是經過刷新,從新渲染一個頁面而實現,在渲染的過程當中勢必要加載外部資源文件,頁面在服務器中渲染出來是經過一系列的生命週期,在這個過程當中會由於網速等硬件問題直接影響頁面的加載速度,爲解決這一問題,前端在新的設計模式上引入了組件的概念,頁面之間的跳轉變成了組件之間的切換,不須要從新加載整個頁面,也不用考慮頁面的生命週期,換成組件的生命週期,在性能上大大的提高了。html
<div id="app"> <!--組件的使用--> <global-component></global-component> </div>
//組件的定義 Vue.component(組件名稱, {template}) Vue.component('global-component', { template: '<h1>全局組件</h1>' }) var vm = new Vue({ el: '#app' })
最終渲染的效果前端
<div id="app"> <h1>全局組件</h1> </div>
<div id="app"> <!--組件的使用--> <private-component></private-component> </div>
//組件的定義 Vue.component(組件名稱, {template}) var vm = new Vue({ el: '#app', components:{ 'private-component': { template: '<h1>局部組件</h1>' } } })
最終渲染的效果vue
<div id="app"> <h1>局部組件</h1> </div>
每一個組件都有單獨的做用域java
<div id="app"> <p>{{count}}</p> <component1/> </div>
var vm = new Vue({ el: '#app', data: { count: 10 }, methods: { increment: function(){ this.count += 1; } }, components:{ 'component1': { template: '<button v-on:click="increment">{{ count }}</button>', data: function(){ //在組件裏面 data 必定是 function 並返回一個對象 return { count: 0 } }, methods: { increment: function(){ this.count += 1; } } } } })
渲染結果爲git
<div id="app"> <p>10</p> <!-- 此按鈕每次點擊都會自增 1,而 p 標籤永遠都是爲 10 緣由爲組件的做用域是單獨的 --> <button>0</button> </div>
效果預覽github
好比在下拉列表(select)元素裏面,子元素必須爲 option,則在使用組件的時候用 is設計模式
<div id="app"> <select> <option is="privateOption"></option> </select> </div>
var vm = new Vue({ el: '#app', components: { 'privateOption': { template: '<option value=1>1</otpion>' } } })
渲染結果服務器
<div id="app"> <select> <option value="1">1</option> </select> </div>
<div id="app" style="display: none;"> <input type="button" value="changeLight" @click="changeLight" /> <br/> <p :is="show"></p> </div> <script type="text/javascript"> var vm = new Vue({ el: '#app', data: { show: 'red', }, methods:{ changeLight: function(){ this.show = this.show == 'red' ? 'green' : 'red'; } }, components: { red: { template: '<h1>Red</h1>' }, green: { template: '<h1>Green</h1>' } } }) </script>
組件的屬性要先聲明後使用,props: ['屬性名'...]app
<div id="app"> <!--組件的使用--> <private-component title="組件屬性" :text="mess"></private-component> </div>
//組件的定義 Vue.component(組件名稱, {template}) var vm = new Vue({ el: '#app', data: { mess: '-動態屬性' } components:{ 'private-component': { template: '<h1>{{title + text}}</h1>', props: ['title', 'text'] } } })
最終渲染的效果
<div id="app"> <h1>組件屬性-動態屬性</h1> </div>
和組件屬性不同的在於 <組件名 v-bind:屬性名="">,屬性名要在組件中先聲明再使用:props: ['屬性名']
自定義事件:<組件名 v-on:自定義事件名="">,自定義事件名不須要聲明,直接用 $emit() 觸發
<div id="app"> <p>{{total}}</p> <increment-total v-on:count="incrementTotal"></increment-total> </div>
var vm = new Vue({ el: '#app', data: { total: 0 }, methods: { incrementTotal: function(){ this.total += 1; } }, components: { 'incrementTotal': { template: '<input type="button" @click="incrementTotal" value="Total" />', data: function(){ return { total: 0 } }, methods: { incrementTotal: function(){ this.total += 1; this.$emit('count') } } } } })
Vue 組件默認是覆蓋渲染,爲了解決這一問題,Vue 提出了 slot 分發內容
<div id="app"> <component1> <h1>Sam</h1> <h1>Lucy</h1> </component1> </div>
Vue.component('component1', { template: ` <div> <h1>Tom</h1> <slot></slot> </div> ` })
最終渲染的效果
<div id="app"> <component1> <h1>Tom</h1> <!-- 若是在組件定義的 template 當中沒有 <slot></slot>,那麼下面兩個 h1 標籤將不會存在 換句話說就是 <slot></slot> = <h1>Sam</h1><h1>Lucy</h1> <slot></slot>能夠放到 <h1>Tom</h1> 上面進行位置調換 --> <h1>Sam</h1> <h1>Lucy</h1> </component1> </div>
若是要將組件裏面不一樣的子元素放到不一樣的地方,那就爲子元素加上一個屬性 slot="名稱",而後在組件定義的時候用名稱對應位置 <slot name="名稱"></slot>,其它沒有 slot 屬性的子元素將統一分發到 <slot></slot> 裏面
<div id="app"> <component1> <h1>Sam</h1> <h1 slot="lucy">Lucy</h1> </component1> </div>
Vue.component('component1', { template: ` <div> <slot name="lucy"></slot> <h1>Tom</h1> <slot></slot> </div> ` })
最終渲染的效果
<div id="app"> <component1> <!--<slot name="lucy"></slot> = <h1 slot="lucy">Lucy</h1>--> <h1>Lucy</h1> <h1>Tom</h1> <!--其它沒有 slot 屬性的子元素將所有分發到 <slot></slot> 標籤--> <h1>Sam</h1> </component1> </div>
<template id="component1"> <div> <input type="text" v-model="name"/> <p>{{name}}</p> </div> </template> <div id="app"> <component1/> </div>
var vm = new Vue({ el: '#app', components: { 'component1': { template: '#component1', data: function(){ return {name: 'Tom'}; } } } })