Vue.js是否强制重新计算已计算的属性?

plupiseo  于 2022-11-17  发布在  Vue.js
关注(0)|答案(4)|浏览(323)

下面是我的组件的computed属性:

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>

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

kr98yfug

kr98yfug1#

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

data() {
  return {
    refreshKey: 0,
    // ...
  }
},
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++;

    // the rest of my method
  },
},
r3i60tvu

r3i60tvu2#

不需要强制更新计算值。如果更改了所需的值,将始终自动重新计算计算属性。
因此,在您的情况下,您将需要更改singlePlacesfilteredPlaces将自动更新。
如文件(https://v2.vuejs.org/v2/guide/reactivity.html#For-Arrays)中所示,数组和对象的React性有一点需要注意。
在您的示例中,添加收藏夹位置时没有包含代码,但您可能需要执行类似以下操作:

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

alen0pnh3#

首先,如果不使用标记,只需切换类,就可以保存两倍的事件处理、两倍的DOM节点创建和两倍的重新计算和重新绘制。另外,我不确定在@click事件中调用函数是否不会立即触发该函数,而是将其 Package 为匿名函数。另外,请注意,我将整个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属性,你可以在init上map它,或者强制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)
  },
},
p1tboqfb

p1tboqfb4#

下面是我对它的看法,使用组合API:

使用可刷新.ts

import { ref } from "vue";

export function useRefreshable<T>(getter: () => T): {
  getter(): T;
  refresh(): void;
} {
  const refreshKey = ref(0);

  return {
    getter() {
      refreshKey.value;
      return getter();
    },
    refresh() {
      refreshKey.value++;
    },
  };
}

使用可刷新.test.ts

import { computed, nextTick } from "vue";
import { useRefreshable } from "@/composition/useRefreshable";

describe("useRefreshable", () => {
  test("", async () => {
    let notReactiveValue = 1;

    function getValue() {
      return notReactiveValue;
    }

    const normalComputed = computed(getValue);

    const refreshable = useRefreshable(getValue);
    const refreshableComputed = computed(refreshable.getter);

    expect(normalComputed.value).toEqual(1);
    expect(refreshableComputed.value).toEqual(1);

    notReactiveValue++;
    await nextTick();

    expect(normalComputed.value).toEqual(1);
    expect(refreshableComputed.value).toEqual(1);

    refreshable.refresh();
    await nextTick();

    expect(normalComputed.value).toEqual(1);
    expect(refreshableComputed.value).toEqual(2);
  });
});

您可以用许多不同的方式 Package 它,例如:

import { computed, ComputedRef } from "vue";
import { useRefreshable } from "@/composition/useRefreshable";

export function useRefreshableComputed<T>(getter: () => T): {
  readonly comp: ComputedRef<T>;
  refresh(): void;
} {
  const refreshable = useRefreshable(getter);
  return {
    comp: computed(() => refreshable.getter()),
    refresh: refreshable.refresh,
  };
}

相关问题