Vue—基础概念—组建化
6.組件化
在大型應(yīng)用開發(fā)的時(shí)候,頁面可以劃分成很多部分。往往不同的頁面,也會有相同的部分。例如可能會有相同的頭部導(dǎo)航。
但是如果每個頁面都獨(dú)自開發(fā),這無疑增加了我們開發(fā)的成本。所以我們會把頁面的不同部分拆分成獨(dú)立的組件,然后在不同頁面就可以共享這些組件,避免重復(fù)開發(fā)。
6.1.全局組件
我們通過Vue的component方法來定義一個全局組件。
<div id="app"><!--使用定義好的全局組件--><counter></counter> </div> <script src="./node_modules/vue/dist/vue.js"></script> <script type="text/javascript">// 定義全局組件,兩個參數(shù):1,組件名稱。2,組件參數(shù)Vue.component("counter",{template:'<button v-on:click="count++">你點(diǎn)了我 {{ count }} 次,我記住了.</button>',data(){return {count:0}}})var app = new Vue({el:"#app"}) </script>- 組件其實(shí)也是一個Vue實(shí)例,因此它在定義時(shí)也會接收:data、methods、生命周期函數(shù)等
- 不同的是組件不會與頁面的元素綁定,否則就無法復(fù)用了,因此沒有el屬性。
- 但是組件渲染需要html模板,所以增加了template屬性,值就是HTML模板
- 全局組件定義完畢,任何vue實(shí)例都可以直接在HTML中通過組件名稱來使用組件了。
- data必須是一個函數(shù),不再是一個對象。
效果:
6.2.組件的復(fù)用
定義好的組件,可以任意復(fù)用多次:
<div id="app"><!--使用定義好的全局組件--><counter></counter><counter></counter><counter></counter> </div>效果:
你會發(fā)現(xiàn)每個組件互不干擾,都有自己的count值。怎么實(shí)現(xiàn)的?
組件的data屬性必須是函數(shù)!
當(dāng)我們定義這個?<counter>?組件時(shí),它的data 并不是像這樣直接提供一個對象:
data: {count: 0 }取而代之的是,一個組件的 data 選項(xiàng)必須是一個函數(shù),因此每個實(shí)例可以維護(hù)一份被返回對象的獨(dú)立的拷貝:
data: function () {return {count: 0} }如果 Vue 沒有這條規(guī)則,點(diǎn)擊一個按鈕就會影響到其它所有實(shí)例!
6.3.局部注冊
一旦全局注冊,就意味著即便以后你不再使用這個組件,它依然會隨著Vue的加載而加載。
因此,對于一些并不頻繁使用的組件,我們會采用局部注冊。
我們先在外部定義一個對象,結(jié)構(gòu)與創(chuàng)建組件時(shí)傳遞的第二個參數(shù)一致:
const counter = {template:'<button v-on:click="count++">你點(diǎn)了我 {{ count }} 次,我記住了.</button>',data(){return {count:0}} };然后在Vue中使用它:
var app = new Vue({el:"#app",components:{counter:counter // 將定義的對象注冊為組件} })- components就是當(dāng)前vue對象子組件集合。
- 其key就是子組件名稱
- 其值就是組件對象的屬性
- 效果與剛才的全局注冊是類似的,不同的是,這個counter組件只能在當(dāng)前的Vue實(shí)例中使用
6.4.組件通信
通常一個單頁應(yīng)用會以一棵嵌套的組件樹的形式來組織:
- 頁面首先分成了頂部導(dǎo)航、左側(cè)內(nèi)容區(qū)、右側(cè)邊欄三部分
- 左側(cè)內(nèi)容區(qū)又分為上下兩個組件
- 右側(cè)邊欄中又包含了3個子組件
各個組件之間以嵌套的關(guān)系組合在一起,那么這個時(shí)候不可避免的會有組件間通信的需求。
6.4.1.props(父向子傳遞)
父組件使用子組件,并自定義了title屬性:
<div id="app"><h1>打個招呼:</h1><!--使用子組件,同時(shí)傳遞title屬性--><introduce title="大家好,我是鋒哥"/> </div> <script src="./node_modules/vue/dist/vue.js"></script> <script type="text/javascript">Vue.component("introduce",{// 直接使用props接收到的屬性來渲染頁面template:'<h1>{{title}}</h1>',props:['title'] // 通過props來接收一個父組件傳遞的屬性})var app = new Vue({el:"#app"}) </script>效果:
6.4.2.props驗(yàn)證
我們定義一個子組件,并接受復(fù)雜數(shù)據(jù):
const myList = {template: '\<ul>\<li v-for="item in items" :key="item.id">{{item.id}} : {{item.name}}</li>\</ul>\',props: {items: {type: Array,default: [],required: true}}};- 這個子組件可以對 items 進(jìn)行迭代,并輸出到頁面。
- props:定義需要從父組件中接收的屬性
- items:是要接收的屬性名稱
- type:限定父組件傳遞來的必須是數(shù)組
- default:默認(rèn)值
- required:是否必須
- items:是要接收的屬性名稱
當(dāng) prop 驗(yàn)證失敗的時(shí)候,(開發(fā)環(huán)境構(gòu)建版本的) Vue 將會產(chǎn)生一個控制臺的警告。
我們在父組件中使用它:
<div id="app"><h2>已開設(shè)如下課程:</h2><!-- 使用子組件的同時(shí),傳遞屬性,這里使用了v-bind,指向了父組件自己的屬性lessons --><my-list :items="lessons"/> </div> var app = new Vue({el:"#app",components:{myList // 當(dāng)key和value一樣時(shí),可以只寫一個},data:{lessons:[{id:1, name: 'java'},{id:2, name: 'php'},{id:3, name: 'ios'},]} })效果:
type類型,可以有:
6.4.3.動態(tài)靜態(tài)傳遞
給 prop 傳入一個靜態(tài)的值:
<introduce title="大家好,我是鋒哥"/>給 prop 傳入一個動態(tài)的值: (通過v-bind從數(shù)據(jù)模型中,獲取title的值)
<introduce :title="title"/>靜態(tài)傳遞時(shí),我們傳入的值都是字符串類型的,但實(shí)際上任何類型的值都可以傳給一個 props。
<!-- 即便 `42` 是靜態(tài)的,我們?nèi)匀恍枰?`v-bind` 來告訴 Vue --> <!-- 這是一個JavaScript表達(dá)式而不是一個字符串。--> <blog-post v-bind:likes="42"></blog-post><!-- 用一個變量進(jìn)行動態(tài)賦值。--> <blog-post v-bind:likes="post.likes"></blog-post>6.4.4.子向父的通信
來看這樣的一個案例:
<div id="app"><h2>num: {{num}}</h2><!--使用子組件的時(shí)候,傳遞num到子組件中--><counter :num="num"></counter> </div> <script src="./node_modules/vue/dist/vue.js"></script> <script type="text/javascript">Vue.component("counter", {// 子組件,定義了兩個按鈕,點(diǎn)擊數(shù)字num會加或減template:'\<div>\<button @click="num++">加</button> \<button @click="num--">減</button> \</div>',props:['num']// num是從父組件獲取的。})var app = new Vue({el:"#app",data:{num:0}}) </script>- 子組件接收父組件的num屬性
- 子組件定義點(diǎn)擊按鈕,點(diǎn)擊后對num進(jìn)行加或減操作
我們嘗試運(yùn)行,好像沒問題,點(diǎn)擊按鈕試試:
子組件接收到父組件屬性后,默認(rèn)是不允許修改的。怎么辦?
既然只有父組件能修改,那么加和減的操作一定是放在父組件:
var app = new Vue({el:"#app",data:{num:0},methods:{ // 父組件中定義操作num的方法increment(){this.num++;},decrement(){this.num--;}} })但是,點(diǎn)擊按鈕是在子組件中,那就是說需要子組件來調(diào)用父組件的函數(shù),怎么做?
我們可以通過v-on指令將父組件的函數(shù)綁定到子組件上:
<div id="app"><h2>num: {{num}}</h2><counter :num="num" @inc="increment" @dec="decrement"></counter> </div>在子組件中定義函數(shù),函數(shù)的具體實(shí)現(xiàn)調(diào)用父組件的實(shí)現(xiàn),并在子組件中調(diào)用這些函數(shù)。當(dāng)子組件中按鈕被點(diǎn)擊時(shí),調(diào)用綁定的函數(shù):
Vue.component("counter", {template:'\<div>\<span>num2:{{num}}</span>\<button @click="plus">加</button> \<button @click="reduce">減</button> \</div>',props:['num'],methods:{plus(){this.$emit("inc");},reduce(){this.$emit("dec");}}})- vue提供了一個內(nèi)置的this.$emit()函數(shù),用來調(diào)用父組件綁定的函數(shù)
效果:
?
總結(jié)
以上是生活随笔為你收集整理的Vue—基础概念—组建化的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Vue—基础概念—指令
- 下一篇: Vue—基础概念—路由(vue-rout