在 Vue 3 中使用 Computed 创建搜索输入过滤器
Creating a Search Input Filter with Computed in Vue 3
我已通过 this guide 创建搜索过滤器输入字段,但无法弄清楚如何在 v-model
.
中正确实施 computed
我已将指南中的代码转换为:
<template>
<div id="table-cms" class="table-cms">
<input class="search-field textfield-closed" type="search" placeholder="Search" v-model="filter">
<p>{{ filter }}</p>
<p>{{ state.array }}</p>
</div>
</template>
<script setup>
import {computed, reactive} from "vue";
const state = reactive({
search: null,
array: [
{id: 1, title: 'Thanos', content: '123'},
{id: 2, title: 'Deadpool', content: '456'},
{id: 3, title: 'Batman', content: '789'}
]
})
const filter = computed({
get() {
console.log('check1')
return state.search
},
set() {
if (state.search) {
console.log('check2a')
return state.array.filter(item => {
return state.search
.toLowerCase()
.split(" ")
.every(v => item.title.toLowerCase().includes(v))
});
} else {
console.log('check2b')
return state.array;
}
}
})
</script>
但是控制台显示:
check1
check2b
check2b
check2b
...
这意味着 computed
被执行但它没有进入 if (state.search) {}
(实际过滤器)。显示 state.array
确实会呈现初始数组,但不会通过在输入字段中键入不同的标题来更新:
<p>{{ state.array }}</p>
渲染:
[
{
"id": 1,
"title": "Thanos",
"content": "123"
},
{
"id": 2,
"title": "Deadpool",
"content": "456"
},
{
"id": 3,
"title": "Batman",
"content": "789"
}
]
我做错了什么?
您必须使用 state.search
作为输入的 v-model
:
<input class="search-field textfield-closed" type="search" placeholder="Search" v-model="state.search">
否则它将永远保持 null
,因为它不会改变,这会导致代码跳过 if 语句。
此外,您的计算过滤器中不需要 setter。
<template>
<div id="table-cms" class="table-cms">
<input
class="search-field textfield-closed"
type="search"
placeholder="Search"
v-model="state.search"
/>
<p>{{ state.array }}</p>
</div>
</template>
<script setup>
import { computed, reactive } from "vue";
const state = reactive({
search: null,
array: [
{ id: 1, title: "Thanos", content: "123" },
{ id: 2, title: "Deadpool", content: "456" },
{ id: 3, title: "Batman", content: "789" },
],
});
const filter = computed(() => {
if (state.search) {
//console.log('check2a')
return state.array.filter((item) => {
return state.search
.toLowerCase()
.split(" ")
.every((v) => item.title.toLowerCase().includes(v));
});
} else {
console.log("check2b");
return state.array;
}
});
</script>
我已通过 this guide 创建搜索过滤器输入字段,但无法弄清楚如何在 v-model
.
computed
我已将指南中的代码转换为:
<template>
<div id="table-cms" class="table-cms">
<input class="search-field textfield-closed" type="search" placeholder="Search" v-model="filter">
<p>{{ filter }}</p>
<p>{{ state.array }}</p>
</div>
</template>
<script setup>
import {computed, reactive} from "vue";
const state = reactive({
search: null,
array: [
{id: 1, title: 'Thanos', content: '123'},
{id: 2, title: 'Deadpool', content: '456'},
{id: 3, title: 'Batman', content: '789'}
]
})
const filter = computed({
get() {
console.log('check1')
return state.search
},
set() {
if (state.search) {
console.log('check2a')
return state.array.filter(item => {
return state.search
.toLowerCase()
.split(" ")
.every(v => item.title.toLowerCase().includes(v))
});
} else {
console.log('check2b')
return state.array;
}
}
})
</script>
但是控制台显示:
check1
check2b
check2b
check2b
...
这意味着 computed
被执行但它没有进入 if (state.search) {}
(实际过滤器)。显示 state.array
确实会呈现初始数组,但不会通过在输入字段中键入不同的标题来更新:
<p>{{ state.array }}</p>
渲染:
[
{
"id": 1,
"title": "Thanos",
"content": "123"
},
{
"id": 2,
"title": "Deadpool",
"content": "456"
},
{
"id": 3,
"title": "Batman",
"content": "789"
}
]
我做错了什么?
您必须使用 state.search
作为输入的 v-model
:
<input class="search-field textfield-closed" type="search" placeholder="Search" v-model="state.search">
否则它将永远保持 null
,因为它不会改变,这会导致代码跳过 if 语句。
此外,您的计算过滤器中不需要 setter。
<template>
<div id="table-cms" class="table-cms">
<input
class="search-field textfield-closed"
type="search"
placeholder="Search"
v-model="state.search"
/>
<p>{{ state.array }}</p>
</div>
</template>
<script setup>
import { computed, reactive } from "vue";
const state = reactive({
search: null,
array: [
{ id: 1, title: "Thanos", content: "123" },
{ id: 2, title: "Deadpool", content: "456" },
{ id: 3, title: "Batman", content: "789" },
],
});
const filter = computed(() => {
if (state.search) {
//console.log('check2a')
return state.array.filter((item) => {
return state.search
.toLowerCase()
.split(" ")
.every((v) => item.title.toLowerCase().includes(v));
});
} else {
console.log("check2b");
return state.array;
}
});
</script>