Vue 3 组合 API:计算过滤数组的问题
Vue 3 composition API: issue with computed to filter array
我正在学习 Vue 3 组合 API 我做了一个简单的 post 列表(简单地创建一个 post 的数组每个 posts) 的 setup() 带有标签,如下面的第一个代码部分。
然后我有一个组件 PostList 来显示那些 posts 和一个 TagCloud 来显示所有现有的标签。
我正在尝试通过单击标签来过滤 posts。
- 我设法从组件 TagCloud 发出标签
- 我尝试使用计算结果过滤我的 posts (tils) 列表,但是...它不起作用
以下是 3 个元素协同工作的结果,有人能找出问题所在吗?
主视图
<template>
<div class="home">
<h1>Today I learned (TIL)</h1>
<div class="layout">
<TagCloud :tils="tils" @tag="filterTils" />
<PostList :tils="filterTils" />
</div>
</div>
</template>
<script>
import PostList from "../components/PostList.vue";
import TagCloud from "../components/TagCloud.vue";
import { ref, computed } from "vue";
export default {
name: "Til",
components: { PostList, TagCloud },
setup() {
const tils = ref([
{
title: "Symbol#to_proc conversion",
description: "map(&:to_i) is exactly the same as map { |x| x.to_i }",
tags: ["ruby"],
},
{
title: "Symbol#to_proc conversion",
description:
"Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum ",
tags: ["lorem"],
},
{
title: "Symbol#to_proc conversion",
description: "map(&:to_i) is exactly the same as map { |x| x.to_i }",
tags: ["ruby"],
},
]);
const filterTils = computed((tag) => {
return tils.value.filter((til) => til.tags.includes(tag));
});
return { tils, filterTils };
}
};
</script>
标签云组件
<template>
<div class="tag-cloud">
<h3>Tags</h3>
<div v-for="tag in tags" :key="tag">
<div @click="filterTag(tag)" class="uniq-tag">#{{ tag }}</div>
</div>
</div>
</template>
<script>
import useTags from "../composables/useTags";
export default {
props: ["tils"],
setup(props, context) {
const { tags } = useTags(props.tils);
const filterTag = (tag) => {
context.emit("tag", tag);
};
return { tags, filterTag };
},
};
</script>
post 列表组件
<template>
<div class="til-list">
<div v-for="til in tils" :key="til">
<div class="til">
<h3>{{ til.title }}</h3>
<p>{{ til.description }}</p>
<span v-for="tag in til.tags" :key="tag"> #{{ tag }} </span>
</div>
</div>
</div>
</template>
<script>
export default {
props: ["tils"],
};
</script>
您正在尝试将 filterTils
用作 tag
事件的事件处理程序,以及 return 过滤结果的计算道具,但是这两件事应该是分开的。
另请注意,用 computed()
包装方法不一定 return 另一种方法。在 filterTils
的情况下,它 return 是一个 Array
。
解决方案
这是解决问题的一种方法:
添加一个 ref
来保存当前选择的标签:
import { ref } from 'vue'
export default {
setup() {
const currentTag = ref()
}
}
更改 @tag
事件处理程序以复制当前标签:
<template>
<TagCloud @tag="onTag" />
</template>
<script>
export default {
setup() {
return {
onTag: tag => currentTag.value = tag
}
}
}
</script>
更新filterTils
以根据当前标签计算筛选结果:
const filterTils = computed(() => {
return currentTag.value
? tils.value.filter(til => til.tags.includes(currentTag.value))
: tils.value;
})
我正在学习 Vue 3 组合 API 我做了一个简单的 post 列表(简单地创建一个 post 的数组每个 posts) 的 setup() 带有标签,如下面的第一个代码部分。 然后我有一个组件 PostList 来显示那些 posts 和一个 TagCloud 来显示所有现有的标签。 我正在尝试通过单击标签来过滤 posts。
- 我设法从组件 TagCloud 发出标签
- 我尝试使用计算结果过滤我的 posts (tils) 列表,但是...它不起作用
以下是 3 个元素协同工作的结果,有人能找出问题所在吗?
主视图
<template>
<div class="home">
<h1>Today I learned (TIL)</h1>
<div class="layout">
<TagCloud :tils="tils" @tag="filterTils" />
<PostList :tils="filterTils" />
</div>
</div>
</template>
<script>
import PostList from "../components/PostList.vue";
import TagCloud from "../components/TagCloud.vue";
import { ref, computed } from "vue";
export default {
name: "Til",
components: { PostList, TagCloud },
setup() {
const tils = ref([
{
title: "Symbol#to_proc conversion",
description: "map(&:to_i) is exactly the same as map { |x| x.to_i }",
tags: ["ruby"],
},
{
title: "Symbol#to_proc conversion",
description:
"Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum ",
tags: ["lorem"],
},
{
title: "Symbol#to_proc conversion",
description: "map(&:to_i) is exactly the same as map { |x| x.to_i }",
tags: ["ruby"],
},
]);
const filterTils = computed((tag) => {
return tils.value.filter((til) => til.tags.includes(tag));
});
return { tils, filterTils };
}
};
</script>
标签云组件
<template>
<div class="tag-cloud">
<h3>Tags</h3>
<div v-for="tag in tags" :key="tag">
<div @click="filterTag(tag)" class="uniq-tag">#{{ tag }}</div>
</div>
</div>
</template>
<script>
import useTags from "../composables/useTags";
export default {
props: ["tils"],
setup(props, context) {
const { tags } = useTags(props.tils);
const filterTag = (tag) => {
context.emit("tag", tag);
};
return { tags, filterTag };
},
};
</script>
post 列表组件
<template>
<div class="til-list">
<div v-for="til in tils" :key="til">
<div class="til">
<h3>{{ til.title }}</h3>
<p>{{ til.description }}</p>
<span v-for="tag in til.tags" :key="tag"> #{{ tag }} </span>
</div>
</div>
</div>
</template>
<script>
export default {
props: ["tils"],
};
</script>
您正在尝试将 filterTils
用作 tag
事件的事件处理程序,以及 return 过滤结果的计算道具,但是这两件事应该是分开的。
另请注意,用 computed()
包装方法不一定 return 另一种方法。在 filterTils
的情况下,它 return 是一个 Array
。
解决方案
这是解决问题的一种方法:
添加一个
ref
来保存当前选择的标签:import { ref } from 'vue' export default { setup() { const currentTag = ref() } }
更改
@tag
事件处理程序以复制当前标签:<template> <TagCloud @tag="onTag" /> </template> <script> export default { setup() { return { onTag: tag => currentTag.value = tag } } } </script>
更新
filterTils
以根据当前标签计算筛选结果:const filterTils = computed(() => { return currentTag.value ? tils.value.filter(til => til.tags.includes(currentTag.value)) : tils.value; })