vue中提到【父子組件】,則一定會想到我們常用的父子組件通信:props+$on()
、$emit()
,如圖:
也就是說,雖然在一般情況下,子組件是不能引用父組件或者Vue實例的數據,但是對於在開發中出現的“數據需要在組件中來回傳遞”,我們最簡單的解決辦法就是通過props(和v-on)將數據從父組件傳到子組件,再用$emit
將數據從子組件傳到父組件,以此循環引用。
但是在另一些場景下,我們可能想要比如(在父組件中)拿到子組件對象,然後直接操作其中數據,去實現一些功能,比如方法的調用。
有時候我們需要父組件直接訪問子組件、子組件直接訪問父組件,或者子組件訪問根組件:
- 父組件訪問子組件:使用
$children
或$refs
reference - 子組件訪問父組件:使用
$parent
父子組件的訪問方式之:$children
children很特別,查閱資料可以發現:this.$children
是一個數組類型,它包含了所有子組件對象:
<body>
<div id="app">
<mxc></mxc>
<mxc></mxc>
<mxc></mxc>
<button @click="btnClick">顫抖吧</button>
</div>
<template id="mxc">
<div>我是子組件啊</div>
</template>
<script>
const app=new Vue({
el:'#app',
data:{
message:'你好'
},
methods:{
btnClick(){
console.log(this.$children)
}
},
components:{
mxc:{
template:'#mxc',
methods:{
showMessage(){
console.log('mxcnb')
}
}
}
}
})
</script>
</body>
點擊(父組件)按鈕之後:
我們還可以通過循環拿到所有子組件數據:
<body>
<div id="app">
<mxc></mxc>
<mxc></mxc>
<mxc></mxc>
<button @click="btnClick">顫抖吧</button>
</div>
<template id="mxc">
<div>我是子組件啊</div>
</template>
<script>
const app=new Vue({
el:'#app',
data:{
message:'你好'
},
methods:{
btnClick(){
console.log(this.$children)
for(let c of this.$children){
console.log(c.name)
}
}
},
components:{
mxc:{
template:'#mxc',
data(){
return{
name:'我是子組件的name'
}
},
methods:{
showMessage(){
console.log('mxcnb')
}
}
}
}
})
</script>
</body>
點擊(父組件)按鈕之後:
因爲是數組,所以我們可以通過比如:this.$children[2]
來拿到第三個子組件的數據。
但是這麼做有一個問題:比如開發時突然在這三個子組件中又插入了一個子組件(可能相同,也可能不同),這時候【2】就不再是我們需要的了。。。
所以我們可以用vue-DOM之光:$refs
:
<body>
<div id="app">
<mxc></mxc>
<mxc></mxc>
<mxc ref="aaa"></mxc>
<button @click="btnClick">顫抖吧</button>
</div>
<template id="mxc">
<div>我是子組件啊</div>
</template>
<script>
const app=new Vue({
el:'#app',
data:{
message:'你好'
},
methods:{
btnClick(){
console.log(this.$refs)
console.log(this.$refs.aaa)
}
},
components:{
mxc:{
template:'#mxc',
data(){
return{
name:'我是子組件的name'
}
},
methods:{
showMessage(){
console.log('mxcnb')
}
}
}
}
})
</script>
</body>
點擊(父組件)按鈕之後:
爲什麼叫“DOM之光”呢?因爲它和原生JS中的
document.querySelector('xxx')
功能一樣,它可以在vue中獲取元素/匹配組件
子訪問父:$parent
<body>
<div id="app">
<mxc></mxc>
</div>
<template id="mxc">
<div>我是子組件啊</div>
<button @click="btnClick">更加顫抖的child</button>
</template>
<script>
const app=new Vue({
el:'#app',
data:{
message:'你好'
},
components:{
mxc:{
template:'#mxc',
methods:{
btnClick(){
console.log(this.$parent)
}
}
}
}
})
</script>
</body>
如法炮製:
圖中el屬性在有些瀏覽器(或添加了vue插件)會顯示未Vue?
因爲當前子組件的父組件就是vue實例啊!
(但是在實際中$parent
用的非常少——考慮到耦合度的原因)
子組件訪問根組件:$root
<body>
<div id="app">
<mxc></mxc>
</div>
<template id="mxc">
<div>
<div>我是mxc組件</div>
<cdn></cdn>
</div>
</template>
<template id="mxca">
<div>
<div>我是子子組件啊</div>
<button @click="btnClick">巨顫祖child</button>
</div>
</template>
<script>
const app=new Vue({
el:'#app',
data:{
message:'你好'
},
components:{
mxc:{
template:'#mxc',
data(){
return{
name:'我是中間子組件的name'
}
},
components:{
cdn:{
template:'#mxca',
methods:{
btnClick(){
console.log(this.$parent.name)
console.log(this.$root.message)
}
}
}
}
}
}
})
</script>
</body>