父子組件通信
prop
event
style和class
natvie修飾符
$listeners
v-model
sync修飾符
$parent和$children
$slots和$scopedSlots
ref
跨組件通信
Provide和Inject
router
vuex
store模式
eventbus
父子組件通信
prop
最常見的組件通信方式,由父組件向子組件傳遞。prop可接收一個數組或對象
//子組件
<script>
export default {
name: "Comp",
//數組方式 props:[....]
// ↓ 對象方式
props: {
datas: {
type: Object,
default: () => {
return {};
}
},
}
</script>
event
子組件向父組件發送通知,並傳遞參數
子組件
methods:{
// 通過 $emit向父組件發送一個通知
handleEvent(){
this.$emit('eventMsg', option)
}
}
父組件
methods:{
// 監聽子組件定義的方法
eventMsg(option){
console.log(option);
}
}
style 和 class
父組件可以向子組件傳遞style 和 class ,style 和 class將合併到子組件根元素上
父組件
<template>
<div id="app">
<HelloWorld
style="color:red"
class="hello"
msg="Welcome to Your Vue.js App"
/>
</div>
</template>
<script>
import HelloWorld from "./components/HelloWorld.vue";
export default {
components: {
HelloWorld,
},
};
</script>
子組件
<template>
<div class="world" style="text-align:center">
<h1>{{msg}}</h1>
</div>
</template>
<script>
export default {
name: "HelloWorld",
props: {
msg: String,
},
};
</script>
最終渲染結果
<div id="app">
<div class="hello world" style="color:red; text-aling:center">
<h1>Welcome to Your Vue.js App</h1>
</div>
</div>
attribute
父組件在使用子組件時,在子組件上定義一些屬性,這些屬性將作用於子組件的根元素上,但是不包括style和class
父組件
<HelloWorld data-a="1" data-b="2" msg="Welcome to Your Vue.js App" />
子組件
<template>
<div>
<h1>{{msg}}</h1>
</div>
</template>
<script>
export default {
name: "HelloWorld",
props: {
msg: String,
},
created() {
// 通過$attrs獲取父組件定義的 attribute
console.log(this.$attrs); // {"data-a":"1","data-b":"2"}
},
};
</script>
最終渲染結果
<div id="app">
<div data-a="1" data-b="2">
<h1>Welcome to Your Vue.js App</h1>
</div>
</div>
Tip:子組件可以通過定義 inheritAttrs:false 來緊張 attribute 附着在子組件根元素上 但不影響通過 $attrs 獲取數據
natvie修飾符
在註冊事件時,父組件可以通過 navite 修飾符,將事件註冊到子組件根元素上
父組件
<template>
<div id="app">
<HelloWorld @click.native="handleClick" />
</div>
</template>
<script>
import HelloWorld from "./components/HelloWorld.vue";
export default {
components: {
HelloWorld,
},
methods: {
handleClick() {
console.log(1);
},
},
};
</script>
子組件
<template>
<div>
<h1>Hello World</h1>
</div>
</template>
最終渲染結果
<template>
<div id="app">
<h1>Hello World</h1>
</div>
</template>
// 當點擊app時。會觸發父組件定義的 handleClick 方法
$listeners
子組件可以通過 $listeners 獲取父組件傳遞過來的所有處理函數
v-model
父組件在使用子組件時,可以在子組件上綁定v-model,子組件通過定義model的prop和event還獲取父組件定義的值
父組件
`
<Compn v-model="datas" />
`
子組件
<script>
export default {
//分類篩選組件
name: "sortFilter",
//定義實現v-modal的屬性與事件
model: {
prop: "value",
event: "change"
},
props: {
//綁定的值
value: {
type: [String, Number],
default: ""
}
},
created() {
console.log(this.value)
},
</script>
sync 修飾符
和 v-model類似,用於雙向數據綁定,不同點在於 v-model只能針對一個數據進行綁定,而 sync 修飾符沒有限制
子組件
<template>
<div>
<p>
<button @click="$emit(`update:num1`, num1 - 1)">-</button>
{{ num1 }}
<button @click="$emit(`update:num1`, num1 + 1)">+</button>
</p>
<p>
<button @click="$emit(`update:num2`, num2 - 1)">-</button>
{{ num2 }}
<button @click="$emit(`update:num2`, num2 + 1)">+</button>
</p>
</div>
</template>
<script>
export default {
props: ["num1", "num2"],
};
</script>
父組件
<template>
<div id="app">
<Numbers :num1.sync="n1" :num2.sync="n2" />
<!-- 等同於 -->
<Numbers
:num1="n1"
@update:num1="n1 = $event"
:num2="n2"
@update:num2="n2 = $event"
/>
</div>
</template>
<script>
import Numbers from "./components/Numbers.vue";
export default {
components: {
Numbers,
},
data() {
return {
n1: 0,
n2: 0,
};
},
};
</script>
$parent 和 $children
在組件內部,可以通過$parent 和$children屬性,分別獲取當前組件的父組件和子組件實例
<template>
<div class="hello">
<button @click="handelParent">獲取父組件實例</button>
<button @click="handelChild">獲取子組件實例</button>
<Child />
</div>
</template>
<script>
import Child from "./Children.vue";
export default {
name: "HelloWorld",
props: {
msg: String,
},
components: {
Child,
},
methods: {
handelParent() {
console.log("父組件實例:", this.$parent);
},
handelChild() {
console.log("子組件實例", this.$children);
},
},
};
</script>
ref
在使用組件時,可以通過在組件上定義ref來獲取組件實例
<template>
<div class="hello">
<button @click="handelChild">獲取子組件實例</button>
<Child ref="child" />
</div>
</template>
<script>
import Child from "./Children.vue";
export default {
name: "HelloWorld",
props: {
msg: String,
},
components: {
Child,
},
methods: {
handelChild() {
console.log("子組件實例", this.$refs.child);
},
},
};
</script>
跨組件通信
provide 和 Inject
provide和inject 可以實現深層組件通信,頂層組件只需定義provide,底層組件通過inject接受數據
頂層組件
// 父組件
provide(){
msg:'hello Children'
},
// 子組件
inject: ['msg']
created () {
console.log(this.msg) // hello Children
}
router
如果一個組將改變了地址欄,所有監聽地址欄的組將都會做出相應的改變,
//監聽路由變化
watch:{
$route(to,from) {
console.log(to,from);
}
}
vuex
vuex 過於笨重,通常不建議在小型項目中使用,小型項目可以使用store 或 eventbus代替vuex,vuex本質上就是一個數據倉庫。在此不做過多贅述,先挖一個坑,下回再敍。
store 模式
store模式其實就是一個普通的js模塊,各組件可以導入該模塊,將數據放到data裏面,此時store就具有響應式了。
// 導出一個 store.js模塊
export default {
userInfo:{...},
loginInfo:{...}
}
// A子組件導入 store模塊
import store from './store.js'
export default {
name:'Acompon',
data(){
userInfo: store.userInfo
}
}
// B子組件導入 store模塊
import store from './store.js'
export default {
name:'Bcompon',
data(){
loginInfo: store.loginInfo
}
}
tip: store模式的缺點是無法跟蹤數據的改變,因為所有組件都可以更改數據
eventbus
eventbus事件總線相當於一個橋樑,作為所有組將的一個事件中心,所有組件皆可往eventbus裏面註冊事件,也可以監聽事件。
// 定義一個eventbus模塊
import Vue from 'vue'
export const EventBus = new Vue()
// 在main.js裏導入該模塊並掛載到全局
// main.js
import eventbus from './eventbus.js'
Vue.prototype.$eventBus = eventbus
所有子組件向eventbus裏組 註冊 或者 監聽 事件
// 組件A 通過 $emit()註冊事件
sendMsg() {
this.$eventBus.$emit("aMsg", 'from A');
}
// 組件B 通過 $on 監聽事件
this.$eventBus.$on("aMsg", (msg) => {
// A發送來的消息
console.log(msg) // from A
})
// 通過 $off() 可以關閉事件