【问题标题】:Vue.js Force computed properties to recompute?Vue.js 强制计算属性重新计算?
【发布时间】:2018-02-09 06:43:54
【问题描述】:

这是我的组件的计算属性:

methods: {
  addFavoritePlace(place_id) {
    axios.post('/api/add-favorite-place', { place_id: place_id })
      .then(response => {
        // I need here force command.
      });
  },
},

computed: {
  filteredPlaces: function () {
    var is_open;

    if (this.showOpened) {
      is_open = 'open'
    } else {
      is_open = 'close'
    }

    return this.singlePlaces.filter((j) => {
        return j.name.toLowerCase().match(this.search.toLowerCase();
    });
  }
}

还有我的标记:

<span @click="addFavoritePlace(place.id)" class="favorite-btn active" v-if="place.is_favorited == true">
  <i class="icon-heart"></i>
</span>

<span @click="addFavoritePlace(place.id)" class="favorite-btn" v-else>
  <i class="icon-heart"></i>
</span>

我需要再次调用计算里面的过滤函数。 激活收藏按钮。

【问题讨论】:

  • 您不应该“重新计算”该属性,因为当涉及的数据之一发生变化时,它会自行完成。在我看来,您只需更新原始列表中的数据,this.singlePlaces
  • 我试过了。但是不是更新数据,而是再次添加。
  • 你是在找到索引后更新了元素还是刚刚推送了一个新条目?
  • 更新了数据库中的数据,但是又重新添加了未更新的状态。
  • 我的意思是“更新了 Vue.js 中的元素”。您的 post 应该返回更新后的值,只需将其分配给同一索引处的数组,您的计算将自行更新。

标签: vue.js vuejs2


【解决方案1】:

无需强制更新计算值。如果需要的值发生更改,将始终自动重新计算计算属性。

因此,在您的情况下,您需要更改 singlePlaces 并且 filteredPlaces 将自动更新。

如文档 (https://vuejs.org/v2/guide/reactivity.html#For-Arrays) 中所示,关于数组和对象反应性有一点需要注意。

在您的示例中,您在添加喜欢的地方时没有包含代码,但您可能需要执行以下操作:

Vue.set(this.singlePlaces, indexOfItem, updatedItem)

【讨论】:

  • 我想问:如果该值是基于 localStorage 中的值设置的,但似乎我可以围绕 localStorage.getItem 进行卷曲,并且它会更新。
【解决方案2】:

如果您想强制更新计算属性并重新计算它的值,您可以简单地使用数据属性并在计算函数中提及该属性(您不必使用它,只要有就足够了),然后更改该数据属性;这将强制更新计算值。

代码如下:

data() {
  return {
    refreshKey: false,
    // ...
  }
},
computed: {
  myComputedValue() {
    // just mentioning refreshKey
    this.refreshKey;

    // rest of the function that actualy do the calculations and returns a value
  },
},
methods: {
  myMethod() {
    // the next line would force myComputedValue to update
    this.refreshKey = !this.refreshKey;

    // the rest of my method
  },
},

【讨论】:

    【解决方案3】:

    首先,只需切换类,您就可以减少两倍的事件处理、减少两倍的 DOM 节点创建以及减少两倍的重新计算和重绘,而不是您的标记。此外,我不确定在 @click 事件中调用函数是否不会立即触发此函数,以防万一将其包装到匿名函数中。另外,请注意,我将整个 place 对象引用传递给 addFavoritePlace,而不是 place.id

    <span
        @click="() => addFavoritePlace(place)"
        class="favorite-btn"
        :class="{active: place.is_favorited}">
            <i class="icon-heart"></i>
    </span>
    

    其次,filteredPlaces 代码的一部分没有意义,因为您正在设置未在其他地方使用或返回的变量,因此垃圾收集器无论如何都会立即将其杀死。相反,您可以选择:

    computed: {
      filteredPlaces () {
        const search = this.search.toLowerCase()
        return this.singlePlaces.filter((p) => {
            return p.name.toLowerCase().includes(search)
        });
      }
    }
    

    最后,你可以只更新singlePlaces 项目,它们会自动影响filteredPlaces,不需要做任何特别的事情,如果你在每个place 中没有is_favorited 属性,你可以map 它打开init 或强制 Vue 使用set 方法跟踪其更新。另外,正如我所说,我会传递整个 place 引用而不是 id,这样我们就不必在堆栈中再次找到这个元素:

    methods: {
      async addFavoritePlace (place) {
        await axios.post('/api/add-favorite-place', { place_id: place.id })
        this.$set(place, 'is_favorited', true)
      },
    },
    

    【讨论】:

      猜你喜欢
      • 2020-12-10
      • 1970-01-01
      • 2018-07-11
      • 2019-06-18
      • 2017-07-29
      • 2017-08-26
      • 1970-01-01
      • 2014-04-17
      • 2015-01-28
      相关资源
      最近更新 更多