定義全局元件
我們通過Vue的component方法來定義一個全局元件。
<div id="app">
<!--使用定義好的全局元件-->
<counter></counter>
</div>
<script src="./node_modules/vue/dist/vue.js"></script>
<script type="text/javascript">
// 定義全局元件,兩個參數:1,元件名稱。2,元件參數
Vue.component("counter",{
template:'<button v-on:click="count++">你點了我 {{ count }} 次,我記住了.</button>',
data(){
return {
count:0
}
}
})
var app = new Vue({
el:"#app"
})
</script>
- 元件其實也是一個Vue執行個體,是以它在定義時也會接收:data、methods、生命周期函數等
- 不同的是元件不會與頁面的元素綁定,否則就無法複用了,是以沒有el屬性。
- 但是元件渲染需要html模闆,是以增加了template屬性,值就是HTML模闆
- 全局元件定義完畢,任何vue執行個體都可以直接在HTML中通過元件名稱來使用元件了。
- data的定義方式比較特殊,必須是一個函數。
元件的複用
定義好的元件,可以任意複用多次:
<div id="app">
<!--使用定義好的全局元件-->
<counter></counter>
<counter></counter>
<counter></counter>
</div>
你會發現每個元件互不幹擾,都有自己的count值。怎麼實作的?
當我們定義這個
<counter>
元件時,它的data 并不是像這樣直接提供一個對象:
data: {
count: 0
}
取而代之的是,一個元件的 data 選項必須是一個函數,是以每個執行個體可以維護一份被傳回對象的獨立的拷貝:
data: function () {
return {
count: 0
}
}
如果 Vue 沒有這條規則,點選一個按鈕就會影響到其它所有執行個體!
局部注冊
一旦全局注冊,就意味着即便以後你不再使用這個元件,它依然會随着Vue的加載而加載。
是以,對于一些并不頻繁使用的元件,我們會采用局部注冊。
我們先在外部定義一個對象,結構與建立元件時傳遞的第二個參數一緻:
const counter = {
template:'<button v-on:click="count++">你點了我 {{ count }} 次,我記住了.</button>',
data(){
return {
count:0
}
}
};
然後在Vue中使用它:
var app = new Vue({
el:"#app",
components:{
counter:counter // 将定義的對象注冊為元件
}
})
- components就是目前vue對象子元件集合。
- 其key就是子元件名稱
- 其值就是元件對象的屬性
- 效果與剛才的全局注冊是類似的,不同的是,這個counter元件隻能在目前的Vue執行個體中使用
元件通信
父向子傳遞props
比如我們有一個子元件:
Vue.component("introduce",{
// 直接使用props接收到的屬性來渲染頁面
template:'<h3>{{title}}</h3>',
props:[title] // 通過props來接收一個父元件傳遞的屬性
})
- 這個子元件中要使用title屬性渲染頁面,但是自己并沒有title屬性
- 通過props來接收父元件屬性,名為title
父元件使用子元件,同時傳遞title屬性:
<div id="app">
<h1>打個招呼:</h1>
<!--使用子元件,同時傳遞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>
傳遞複雜資料
我們定義一個子元件:
const myList = {
template:'\
<ul>\
<li v-for="item in items" :key="item.id">{{item.id}} : {{item.name}}</li>\
</ul>\
',
props:{ // 通過props來接收父元件傳遞來的屬性
items:{// 這裡定義items屬性
type:Array,// 要求必須是Array類型
default:[] // 如果父元件沒有傳,那麼給定預設值是[]
}
}
}
- 這個子元件可以對 items 進行疊代,并輸出到頁面。
- 但是元件中并未定義items屬性。
- 通過props來定義需要從父元件中接收的屬性
- items:是要接收的屬性名稱
- type:限定父元件傳遞來的必須是數組,否則報錯
- default:預設值
我們在父元件中使用它:
<div id="app">
<h2>傳智播客已開設如下課程:</h2>
<!-- 使用子元件的同時,傳遞屬性,這裡使用了v-bind,指向了父元件自己的屬性lessons -->
<my-list :items="lessons"/>
</div>
var app = new Vue({
el:"#app",
components:{
myList // 當key和value一樣時,可以隻寫一個
},
data:{
lessons:[
{id:1, name: 'java'},
{id:2, name: 'php'},
{id:3, name: 'ios'},
]
}
})
子向父的通信
來看這樣的一個案例:
<div id="app">
<h2>num: {{num}}</h2>
<counter :count="num" @inc="increment" @dec="decrement"></counter>
</div>
<script src="./node_modules/vue/dist/vue.js"></script>
<script type="text/javascript">
Vue.component("counter", {
template:'\
<div>\
<button @click="plus">加</button> \
<button @click="reduce">減</button> \
</div>',
props:['count'],
methods:{
plus(){
this.$emit("inc");
},
reduce(){
this.$emit("dec");
}
}
})
var app = new Vue({
el:"#app",
data:{
num:0
},
methods:{ // 父元件中定義操作num的方法
increment(){
this.num++;
},
decrement(){
this.num--;
}
}
})
</script>
- vue提供了一個内置的this.$emit函數,用來調用父元件綁定的函數