vue.js 组件呈现函数中可能存在无限更新循环,这是由方法中的副作用引起的

0sgqnhkj  于 2023-03-09  发布在  Vue.js
关注(0)|答案(1)|浏览(152)

我已经解决了我的问题,但我不明白它(也许我明白)。
我创建了一个错误处理插件,基本示例:

    • 主文件. js**
const bugStore = {
  state: [],
  addToState(bug) {
    this.state.push(bug);
  }
};

const ErrorLoggerPlugin = {
  install(Vue) {
    const app = new Vue({
      data: {
        bugStore: bugStore
      },
      methods: {
        bug(bug) {
          // Necessary to prevent re-rendering of components
          //setTimeout(() => {
          this.bugStore.addToState(bug);
          //});
        }
      }
    });
    Vue.prototype.$bug = app.bug;
    
  }
};

Vue.use(ErrorLoggerPlugin);

new Vue({
  el: "#app",
  components: {
    App
  },
  template: "<App/>",
  render: (h) => h(App)
});
    • 应用程序版本**
<template>
  <div>
    <img alt="Vue logo" src="./assets/logo.png" />
    {{ $injector("hello world") }}
  </div>
</template>

<script>
export default {
  name: "App",
  components: {},
  methods: {
    $injector(val) {
      try {
        breakme();
      } catch {
        this.$bug("anything");
      }
      return val;
    },
  },
};
</script>

这样做的结果是,App.vue的呈现函数中出现了一个无限循环
我不会在模板中使用方法。我知道要避免这种情况。但是我试图理解为什么这会导致组件重新呈现。
如果您取消注解main.js中的setTimeout,则可以防止该问题。
理解setTimeout,这允许方法在进一步执行bug处理程序插件之前返回值。
经过一夜的好休息,我想我知道发生了什么事。但这也回避了一个问题,什么是更好的处理方式?

    • 发生了什么**
  • 我认为当模板使用这个方法调用时,它会在方法的堆栈中创建通知依赖项,因此组件会对插件存储的状态做出React。如果我将其 Package 在setTimeout中,则相关的依赖项不会执行,直到当前堆栈清除为止。*

https://codesandbox.io/s/modest-babbage-cjuw71?file=/src/main.js
所以我想我需要重新考虑我是如何处理这个问题的。我有一个全局错误处理程序,它不会导致问题,但有时我想故意处理一个问题并将其报告给通知引擎。事实上,它甚至可能不是一个错误。这可以是任何事情。

    • 更新**

我创建了一个函数组件来替换以前用方法完成的功能。同样的问题。

    • 更新**

我从插件中删除了new Vue,如以下答案所示:https://stackoverflow.com/a/75625507/1447679
但在我的例子中,我需要在应用程序的另一个部分中使用React性,我在该组件自己的数据属性中引用了bug存储的状态,使其具有React性,然后一切都解决了。

    • 总结**

除非v-once另有指定,否则组件呈现过程中的任何内容都会从它所触及的任何内容中创建一个通知/依赖树。因此,如果方法更改了状态,即使看起来与特定组件无关,它也会对此更改做出React并重新呈现组件。

xa9qqrwz

xa9qqrwz1#

我发现问题是你在插件中创建了一个新的Vue应用程序。
这导致了主应用和插件应用之间的循环React依赖,从而引发了无限渲染循环。
如果您只是避免创建这个内部Vue应用程序(因为您不需要它),问题就解决了:

const bugStore = {
  state: [],
  addToState(bug) {
    this.state.push(bug);
  }
};

const ErrorLoggerPlugin = {
  install(Vue) {
    Vue.prototype.$bug = (bug) => {
      bugStore.addToState(bug);
      console.log("bug added");
    }
  }
};

相关问题