【问题标题】:Template renders twice in vue.js模板在 vue.js 中渲染两次
【发布时间】:2021-04-13 12:23:48
【问题描述】:

在我的组件模板中,我有以下代码:

   <div
        class="program-point-container"
        v-for="p in programPoints"
        :key="p.id"
    >

        <div class="mt-6 mt-sm-3 mt-md-14 mb-3 font-weight-bold font-size-16" v-if="showDate(p.startsAt)">
            {{new Date(p.startsAt) | moment('DD.MM.YYYY')}} // Humboldt Carré
        </div>
</div>

我的 programPoints 数组中有 23 个对象。出于调试原因,我在控制台记录了一个字符串,以查看该函数被调用了 23 * 2 次。

在这种方法中,我将数据推送到数组中。并返回 true 或 false 以显示 div 容器。但是由于它已经在“第一次”渲染时推送并返回。我不能展示那个容器。

showDate(datetime) {
        const date = new Date(datetime).toDateString()
        // check if date already been pushed
        if(this.dates.includes(date)) {
            console.log('false')
            return false // date already been pushed
        }
        this.dates.push(date)
        console.log('true')
        return true

    },

【问题讨论】:

    标签: vue.js templates nuxt.js


    【解决方案1】:

    抛弃“JQuery 思维”。这不是 Vue 的工作方式。您的模板已经并且将被多次渲染 - 只是每次它使用的一些反应数据发生变化......

    您无需关心之前渲染的内容以及更新结果以获取新数据状态的操作。这是 Vue 的工作。只需以“我想在屏幕上看到的”样式编写您的模板,其余部分由 Vue 处理...

    只需删除与showDate 相关的所有内容 - 不需要。并阅读文档!

    更新

    在对象数组中,我有一个具有日期时间的属性。而且我只想在日期出现的第一个对象上显示一次日期。其余的忽略它。当出现新日期时,我希望它也显示它,但仅适用于第一个对象,依此类推

    我想为对象添加一个额外的键,它是第一个迭代并具有唯一日期的对象。其他的将被忽略,直到另一个带有唯一日期。

    搏击俱乐部的第一条规则...ehm Vue 是:在模板渲染期间,切勿修改模板中使用的任何数据。在最好的情况下,您最终会得到不正确的结果(就像您所做的那样)。在最坏的情况下,你最终会陷入无限循环......

    更好的解决方案是创建代表您想要的替代数据结构,并且感谢 Vue computed properties,即使原始数据发生更改,它也会保持最新...

    const vm = new Vue({
      el: "#app",
      data() {
        return {
          programPoints: [
            { id: 1, name: 'Program A', startsAt: '2021/04/13' },
            { id: 2, name: 'Program B', startsAt: '2021/04/14' },
            { id: 3, name: 'Program C', startsAt: '2021/04/14' },
            { id: 4, name: 'Program D', startsAt: '2021/04/18' },
            { id: 5, name: 'Program E', startsAt: '2021/04/13' },
            { id: 6, name: 'Program F', startsAt: '2021/04/18' },        
          ]
        }
      },
      computed: {
        programByDays() {
          return this.programPoints.reduce((acc, item) => {
            if(!acc[item.startsAt]) {
              acc[item.startsAt] = []
            }
            acc[item.startsAt].push(item)
            
            return acc
          }, {})
        }
      },
      mounted() {
        setTimeout(() => this.programPoints.push({ id: 7, name: 'Program SPECIAL', startsAt: '2021/04/20' }), 2000)
      }
    })
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
    <div id="app">
      <ul>
        <li v-for="(programs, date) in programByDays" :key="date">
          <p> {{ date }} </p>
          <ul>
            <li v-for="program in programs" :key="program.id">
              {{ program.name }}
            </li>
          </ul
        </li>
      </ul>
    </div>

    【讨论】:

    • 我明白了。那我该怎么走?在对象数组中,我有一个具有日期时间的属性。而且我只想在日期出现的第一个对象上显示一次日期。其余的忽略它。当出现新日期时,我希望它也显示它,但仅适用于第一个对象,依此类推。
    • 啊..我明白了。因此,您想要创建一组programPoints,其中每个组具有相同的startsAt 日期,然后呈现(唯一)日期列表(+ 可能是给定日期的programPoints 列表)。对吗?
    • 是的。我想为对象添加一个额外的键,它是第一个迭代并具有唯一日期的对象。其他的将被忽略,直到另一个带有唯一日期。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-04
    • 2016-06-06
    • 1970-01-01
    • 2017-11-10
    • 2012-06-12
    • 2020-08-11
    相关资源
    最近更新 更多