學習元件,我們首先要了解什麼是元件。元件是Vue可以複用的Vue例項,且帶有一個名字,在Vue中我們可以定義多個元件,在多個不同的頁面的中引用多個多不同的元件,減少開發的工作量。因為元件是可複用的Vue例項,所以它們與new Vue接收相同的選項,例如:data,computed,watch,methods以及生命週期鉤子等等,僅有的例外是像el這樣根例項特有的選項。
建立元件的幾種方式
- 第一種使用Vue.extend來建立全域性的Vue元件
// 建立元件模版物件
let mycomponent = Vue.extend({
// 通過template屬性指定了元件要展示的HTML結構
template:"<div>我是使用Vue.extend建立的元件</div>" //
})
// 使用Vue.component("元件名稱", 建立出來的元件模版物件)
Vue.component("custom", mycomponent)
// 直接把元件的名稱以HTML標籤的形式引入到頁面中就可以使用了
<custom></custom>
複製程式碼
注意 :不論是那種方式建立出來的元件,元件的template屬性指向的模版內容,必須有且只能有一個唯一的根元素。
注意 :在使用Vue.component定義全域性元件的時候,元件名稱使用駝峰命名,則在引用元件的時候,需要把大寫的駝峰改為小寫的字母,同時兩個單詞之間使用 - 連線,例如:
Vue.component("customLabel", mycomponent) // 元件名稱駝峰命名
<custom-label></custom-label> // 駝峰改為小寫的字母,同時兩個單詞之間使用 - 連線
複製程式碼
註冊全域性元件引用的簡寫方式:
Vue.component("custom", Vue.extend({
// 通過template屬性指定了元件要展示的HTML結構
template:"<div>我是使用Vue.extend建立的元件</div>" //
}))
複製程式碼
- 第二種使用Vue.component建立全域性的Vue元件
Vue.component("custom", {
// 通過template屬性指定了元件要展示的HTML結構
template:"<div>我是使用Vue.component建立的元件</div>" //
})
// 通過Vue.component的另一種書寫方式建立全域性元件
Vue.component("custom", {template:"#tmp"}) // template屬性指向一個id
// 在被控制的Vue例項el繫結的元素外,使用template元素定義元件的HTML模版結構
<template id="tmp">
<div>
<h1>我是Vue.component建立全域性元件的第二種方式</h1>
</div>
</template>
複製程式碼
- 第三種通過Vue例項的components屬性建立Vue區域性元件(例項內部私有元件)
<div id="app">
<custom>/custom>
<customTwo></customTwo>
<customThree></customThree>
</div>
<template id="tmp">
<div>
<h1>我是components建立的區域性元件利用template元素</h1>
</div>
</template>
<script>
let customThree = {
template: "<div><h1>我是Vue例項外建立的元件模版物件</h1></div>"
}
new Vue({
el: "#app",
components: {
// 第一種方式
"custom": {template:"<div><h1>我是components建立的區域性元件</h1></div>"},
// 第二種方式
"customTwo"{template:"#tmp"},
// 第三種方式
"customThree": customThree // 自定義元件名稱和元件模版物件名稱一致可以簡寫為一個
}
})
</script>
複製程式碼
注意 : 元件中也可以定義資料和屬性
// 但是元件中的data和例項中的data不一樣,例項中的data可以為一個物件,但元件中的data必須是一個方法。
// 這個方法內部還必須return一個物件出來才行。
// 元件中data的資料和例項中data資料的使用方式完全一樣
// 例如:
new Vue({
el: "#app",
data: {
msg: "我是例項中data的資料"
}
})
Vue.components("custom",{
template:"<div> <h1>{{ msg }}</h1></div>",
data () {
return {
msg: "我是元件中data的資料"
}
}
})
複製程式碼
Vue提供了components元素來展示對應名稱的元件
// components是一個佔位符, :is 屬性可以用來指定要展示的元件名稱
// 注意 :is 屬性的值為要展示的元件名稱,但是也可以寫成一個變數,方便某些時候動態切換要展示的元件。
<div id="app">
<component :is="msg"></component>
<button @click="change">切換元件</button>
</div>
<script>
new Vue({
el: "#app",
data: {
msg: "custom"
},
components: {
"custom": {template:"<div><h1>我是components建立的區域性元件custom</h1></div>"},
"customTwo": {template:"<div><h1>我是components建立的區域性元件customTwo</h1></div>"}
},
methods: {
change () {
// 通過chage方法動態改變msg的值來切換要展示的元件
}
}
})
</script>
複製程式碼
元件通訊 => 父子元件,兄弟元件之間通訊
- 元件通訊中,子元件是無法訪問到父元件中的資料和方法的。
- 父元件可以在引用子元件的時候,通過屬性繫結(v-bind)的形式,把資料傳遞給子元件使用。
- 父元件通過自定義屬性傳過來的資料,需要子元件在props屬性上接收才能使用。
父傳子值
<div id="app">
<custom :parentmsg="msg"></custom>
</div>
<script>
new Vue({
el: "#app",
data: {
msg: "我是父元件中的資料"
},
components: {
"custom": {
props: ["parentmsg"],// 子元件通過props屬性接收父元件傳來的資料
template:"<div><h1>我要引用父元件中的資料----{{ parentmsg }}</h1></div>"
}
}
})
</script>
複製程式碼
父傳子方法, 子傳父資料
父元件向子元件傳遞方法,使用的是事件繫結機制v-on,當我們自定義事件屬性後,那麼子元件就可以通過某些方式來呼叫父元件傳遞的這個方法。
<div id="app">
// 通過自定義事件名稱func以事件繫結機制@func="show"將父元件的show方法傳遞給子元件
<custom @func="show"></custom>
</div>
<script>
new Vue({
el: "#app",
data: {
msg: "我是父元件中的資料"
},
components: {
"custom": {
props: ["parentmsg"],// 子元件通過props屬性接收父元件傳來的資料
data () {
return {
childmsg: "我是子元件的資料"
}
},
template:`
<div>
<h1>我要呼叫父元件傳遞過來的方法</h1>
<button @click="emit">點我呼叫父元件傳遞的方法</button>
</div>`,
methods: {
emit () {
// 觸發父元件傳過來的func方法,配合引數可以將子元件的資料傳遞給父元件
// vm.$emit(evebtNane, [...args]) 觸發當前例項上的事件,附加引數會傳給監聽器回撥。
this.$emit("func",this.childmsg)
}
}
},
},
methods: {
// 子元件觸發了我,並且給我傳遞了子元件的資料data
show (data) {
console.log("我是父元件中的show方法")
console.log("接收到了子元件傳遞的資料---" + data)
}
}
})
</script>
複製程式碼
- 注意元件中所有props屬性中的資料,都是通過父元件傳遞給子元件的。
- props中的資料都是隻讀不可寫的,data上的資料都是可讀可寫的,
- 子元件中data中的資料,並不是通過父元件傳遞過來的,而是子元件自己私有的。
兄弟元件之間資料傳遞
- 第一種藉助中央事件匯流排
<div id="app">
</div>
<script>
// 重新例項一個Vue
let Bus = new Vue()
new Vue({
el: "#app",
components: {
"custom": {
template:`<div @click = sendMsg>
<button>點我給customTwo元件傳遞我的資料</button>
</div>`,
data () {
return {
msg: "我是custom元件的資料"
}
},
methods: {
sendMsg () {
Bus.$emit("myFunc", this.msg) // $emit這個方法會觸發一個事件
}
}
},
"customTwo": {
template:`<div>
<h1>下面是我接收custom元件傳來的資料</h1>
<p>{{ customTwoMsg }}</p>
</div>`,
data () {
return {
customTwoMsg: ""
}
},
created () {
this.brotherFunc()
},
methods: {
brotherFunc () {
Bus.$on("myFunc", (data) => { // 這裡要用箭頭函式,否則this指向有問題。
this.customTwoMsg = data
})
}
}
}
}
})
</script>
複製程式碼
這樣藉助匯流排機制,實現兄弟元件之間的資料共享。
- 第二種藉助第三方vuex庫(這是我推薦使用的)
Vuex 是一個專為 Vue.js 應用程式開發的狀態管理模式。它採用集中式儲存管理應用的所有元件的狀態,並以相應的規則保證狀態以一種可預測的方式發生變化。Vuex 也整合到 Vue 的官方除錯工具 devtools extension,提供了諸如零配置的 time-travel 除錯、狀態快照匯入匯出等高階除錯功能。
具體用法請檢視vuex官方文件超級詳細。