【问题标题】:Fix infinity loop. Vue.js修复无限循环。 Vue.js
【发布时间】:2020-05-07 19:33:12
【问题描述】:

我正在尝试检查用户发表的每条评论和评论回复,并检查他们是否在 30 分钟前发表评论然后他们无法编辑它,但是我这样做的方式不起作用我收到了这个错误

[Vue 警告]:组件渲染函数中可能存在无限更新循环。

这是有问题的代码

<div v-for="comment in forum.comments">
    <el-card shadow="never">

    //check for other things 
    //set the comment info and layout

        <div style="text-align: end" v-if="comment.user_id === $page.auth.user.auth.user.id">
            {{minutes(comment)}}
            <div v-if="editRemove === false" class="btn-link-edit action-button"
                @click="edit(comment)">
                <i class="fas fa-pencil-alt"></i>
            </div>
        </div>

        <div v-for="reply in comment.replies">

        //check for other things 
        //set the reply info and layout

            <div style="text-align: end" v-if="reply.user_id === $page.auth.user.auth.user.id">
                {{minutes(reply)}}
                <div v-if="editRemove === false" class="btn-link-edit action-button"
                    @click="edit(reply)">
                    <i class="fas fa-pencil-alt"></i>
                </div>
            </div>
        </div>
    </el-card>
</div>

数据返回

editRemove: false,

方法

minutes(item) {
    var minutes = moment().diff(moment(item.comment_time), 'minutes');
    if (minutes >= 30) {
        this.editRemove = true;
    } else if (minutes <= 29) {
        this.editRemove = false;
    }
}

我应该怎么做才能解决这个问题?

【问题讨论】:

  • 因为你有 2 个 if 并且没有默认情况,也许这就是原因,编译器会抱怨。尝试将} else if (minutes &lt;= 29) { 更改为} else {。你也可以用this.editRemove=minutes &gt;= 30 写得更短
  • @thopaw 我改了,没区别
  • 您有两个 v-for,您在模板 v-for 迭代中有一个函数,即 minutes(comment),您正在该函数中编辑相同的变量 editRemove。所以你不断地改变同一个变量值。
  • @AJT82 因为我正在尝试使其成为动态的并且对于未知数量的 cmets 我将如何解决这个问题?
  • 我会为 cmets 和回复制作哑组件(子组件),您可以使用计算属性来计算您的分钟数。无论如何,即使你不会遇到这个无限循环问题,它也永远不会只使用一个变量editRemove,所有 cmets 和回复都需要有一个唯一标识符。

标签: vue.js


【解决方案1】:

正如我在评论中提到的,您不断地更改同一个变量this.editRemove,因此正在发生更改检测并因此导致类似于无限循环的情况。如前所述,我将为 cmets 和回复制作子组件。虽然我说你可以使用计算属性,但在第二次考虑它时它不会起作用;)因为它不是反应性的。因此,我会在子组件中使用一个时间间隔,每分钟检查一次自发布评论/回复以来经过的分钟数。

所以我会创建一个孩子,比如说Comment,将 v-for 中的当前 comment 传递给孩子:

<div v-for="comment in forum.comments">
  <Comment :comment="comment"/>
</div>

然后孩子会有按钮并检查时间以及是否显示编辑按钮:

<button v-if="isEdit" @click="editComment">Edit</button>

isEdit 在组件创建时确定,之后每 60 秒确定一次。销毁组件时,记得清除间隔。

孩子:

props: {
  comment: Object
},
data() {
  return {
    isEdit: Boolean,
    interval: null
  };
},
methods: {
  editComment() {
    console.log(this.comment)
    // do your magic
  },
  checkTime() {
    var minutes = moment().diff(moment(this.comment.comment_time), "minutes");
    if (minutes >= 30) {
      this.isEdit = true;
      // here you could also already clear the interval, since it won't change
    } else if (minutes <= 29) {
      this.isEdit = false;
    }
  }
},
created() {
  this.checkTime();
  this.interval = setInterval(() => {
    this.checkTime();
  }, 60000);
},
beforeDestroy() {
  clearInterval(this.interval);
}

此演示仅适用于 cmets,但同样适用于回复。

CODESANDBOX,为了演示,我对时间间隔做了一些更改,将分钟更改为秒。所以 10 秒后应该会出现另外 2 个按钮。

【讨论】:

  • 好的我有一个问题,对于回复,我是否创建另一个组件并以与您在此处相同的方式调用它,只是使用回复组件? ```
    ```
  • 另外,我有编辑和删除 cmets 和回复的功能,我是否将它们移动到组件文件?
  • 你的评论和回复是不是一模一样的道具?我会认为他们是不同的。但如果没有。然后我可能会再制作一个子组件,它只显示文本并计算时间。 Comment 组件将被包裹在它周围,您可以 v-for 回复 Comment 组件中的每个评论,并在两者中都使用子组件。是的,我会将编辑和删除移动到组件。当然,您可以将这些信息传达给父母以进行处理。这取决于你。
  • 几乎一样,只是布局不同,少了一个按钮,无法回复。我还想发送另一个对象以及评论,因为我在评论布局中使用它,我该怎么做?
  • 只需在标签中添加一个新的道具。无论你需要它是什么:&lt;Comment :comment="comment" :someobject="myobject"/&gt;。伪代码。在Comment 组件中注册您传递给props 部分的对象。
猜你喜欢
  • 1970-01-01
  • 2020-12-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-21
  • 1970-01-01
  • 2021-02-28
  • 1970-01-01
相关资源
最近更新 更多