Vue 2 无限刷新循环问题求助:疑似框架Bug?
Vue 2 无限刷新循环问题分析与解决
问题根源
- 父组件模板中绑定
:scope="{}"时,每次父组件重新渲染都会创建一个全新的空对象(JavaScript中对象是引用类型,字面量{}每次执行都会生成新引用)。 - 子组件对
scope属性设置了deep: true+immediate: true的监听器:- 当父组件传递新的对象引用时,Vue会判定
scopeprops发生变化,触发watch的handler。 - handler调用
update方法,通过$emit('counter')让父组件的counter自增,父组件因此重新渲染,再次生成新的{}传递给子组件,形成无限循环。
- 当父组件传递新的对象引用时,Vue会判定
- 注释掉
{{counter}}时,父组件不会因为counter变化触发重新渲染,所以不会重复生成新对象,循环不会启动。
解决方案
方案1:复用固定对象引用
将父组件中传递的空对象放到data中,确保每次渲染传递的都是同一个引用:
<!-- App.vue 修改后 --> <template> <div id="app"> <HelloWorld :scope="emptyScope" @counter="counter++" /> <br> <p> Parent Counter: {{counter}} </p> </div> </template> <script> import HelloWorld from './components/HelloWorld.vue' export default{ name: 'App', components: { HelloWorld }, data () { return { counter: 0, emptyScope: {} // 复用这个固定对象 }; }, }; </script>
方案2:调整子组件的监听器配置
如果不需要监听scope的深层属性变化,去掉deep: true(空对象没有深层属性,不需要深度监听):
<!-- HelloWorld.vue 修改后 --> <script> export default{ name: "helloWorld", props: { scope: Object, }, data () { return{ counter: 0, mounted: 0 }; }, watch: { scope:{ handler: function(){ console.log("helloWorld scope Changed"); this.update(); }, immediate: true, // deep: true // 移除深度监听 }, }, methods: { update: async function(){ this.counter ++; console.log("HelloWorld UPDATE CALLED: ", this.counter); this.$emit("counter", 1); }, } }; </script>
方案3:传递静态值(如果业务允许)
如果子组件的scope属性非必填,或者可以接受静态值,直接传递null或固定值,避免每次生成新对象:
<!-- App.vue 中修改绑定 --> <HelloWorld :scope="null" @counter="counter++" />
内容的提问来源于stack exchange,提问作者Stephen Rich
相关产品推荐
相关产品推荐

