之前在项目中有一个需求:在父组件那一层数据变动时,希望子组件的数据刷新(甚至让子组件的一些方法也能执行)。
如上图,点击button实现子组件的刷新。
那么,该怎么做呢,
1,props属性:
首先我们知道使用props属性,但只能使子组件有关props部分的属性刷新,别的部分还是不动的,可以解决很有限的刷新。对子组件的生命周期上的方法是完全操作不了的。
2,重新加载
用 v-if=false 让子组件去掉,再用v-if=true,让子组件重新渲染:
<template>
<div>
<button @click="refreshChild">refreshChild</button>
<Child v-if="childData"></Child> // 1
</div>
</template>
<script>
import Child from './Child.vue'
export default {
data () {
return {
childData : true
}
},
components:{
Child
},
methods:{
refreshChild () { // 2
this.childData = false
setTimeout(() => {
this.childData = true
},0)
}
}
}
</script>
<style>
</style>
如上面的注释1和注释2。通过setTimeout的异步作用,可以实现子组件的重新加载。效果很明显~
但这种方法,显得特别违和。因为给人的感觉很不靠谱,更何况在性能上表现也不会太出色。
那么,按照这个思想,还可以使用$nextTick.
3,使用$nextTick.
$nextTick 是在下次DOM更新循环结束后,执行延迟回调。因此用在这里非常合适。
refreshChild () {
this.childData = false
// setTimeout(() => {
// this.childData = true
// },0)
this.$nextTick(()=>{
this.childData = true
})
}
4,使用$refs
尽管存在 prop 和事件,有的时候你仍可能需要在 JavaScript 里直接访问一个子组件。为了达到这个目的,你可以通过
ref
特性为这个子组件赋予一个 ID 引用。
所以:
<template>
<div>
<button @click="refreshChild">refreshChild</button>
<Child ref="childData"></Child> // 1
</div>
</template>
<script>
import Child from './Child.vue'
export default {
data () {
return {
}
},
components:{
Child
},
methods:{
refreshChild () { // 2
this.$refs.childData.doSth() // 执行子组件里的doSth函数。
}
}
}
</script>
想要调用子组件里的某个方法,用这种方法很简便。