考虑到已经广泛存在的JSON搜索/筛选/匹配功能,以及Vue中的计算函数。这是我的情况。
我有一个本地JSON文件(缩写为示例):
更新了JSON以反映最近的进展
{
"examplejson": [
{
"section_title": "title 1",
"section_category": "category1",
"items": [
{
"category": "category1",
"title": "item title 1",
"url": "url 1",
"description": "Etiam turpis ipsum, gravida a odio ac, sollicitudin egestas tortor.",
"footnote": "footnote 1"
},
{
"category": "category1",
"title": "item title 2",
"url": "url 2",
"description": "Suspendisse consectetur lacus sed maximus consectetur. Etiam nunc magna, fringilla.",
"footnote": "footnote 2"
}
]
},
{
"section_title": "title 2",
"section_category": "category2",
"items": [
{
"category": "category2",
"title": "title 3",
"url": "url 3",
"description": "Donec venenatis justo at ligula dictum tempus. In euismod nulla.",
"footnote": "footnote 3"
},
{
"category": "category2",
"title": "title 4",
"url": "url 4",
"description": "Cras dui felis, pulvinar vel elit quis, imperdiet sollicitudin massa.",
"footnote": "footnote 4"
}
]
}
]
}这是我的Vue组件:
import Vue from 'vue';
import axios from 'axios';
Vue.component('searchableList', {
template: `
<!-- Searchable List Component -->
<div v-cloak>
<label class="search-bar">
<input type="text" class="search__input" v-model="searchString" placeholder="Search...">
</label>
<div class="searchable-content">
<ul class="list">
<li :class="section.section_category + '-section'" v-for="section in filteredList" :key="section.section_title">
<h3 class="section-title">{{ section.section_title }}</h3>
<ul :class="section.section_category + '-section-list'">
<li v-for="item in section.items">
<a :href="item.url">{{ item.title }}</a>
<p>{{ item.description }}</p>
<p class="note">{{ item.footnote }}</p>
</li>
</ul>
</li>
</ul>
</div>
</div>
`
//other items listed below are contained within this component but I separated into individual segments for clear explanation
});组件数据(“componentLoaded”标志,以消除计算属性和axios.get方法之间的竞争条件):
data() {
return {
componentLoaded: false,
list: [],
searchString: ''
}
},
// mounted lifecycle hook:
mounted() {
this.getListData();
}
// Axios JSON localized JSON get method:
methods: {
getListData() {
var self = this;
const url = '/path/to/localized/list.json';
axios.get(url)
.then(response => {
self.list = response.data.examplejson;
})
.then(function() {
self.componentLoaded = true;
console.log("content loaded");
})
.catch(error => {
console.log("The file:" + ` "${url}" ` + "does not exist or path/filename is incorrect.");
});
}
},
// Computed filtered list property (this is where im having trouble):
computed: {
filteredList: function() {
let self = this;
if (!self.componentLoaded) {
return null;
}
else {
console.log("list loaded successfully");
return self.list;
}
}
}DOM中的组件注入点(用于确定页面中是否存在类,需要单独的页面DOM控制,选择没有全局注入点):
if (document.getElementsByClassName("my-list")[0]){
new Vue({
el: ".my-list"
});
}HTML:
<div class="container">
<div class="my-list">
<searchable-list></searchable-list>
</div>
</div>我的一般问题是,我的筛选函数(filteredList)和内容呈现(getListData())变得过于复杂,因此我的搜索过滤无法工作,或者我只是没有正确构建我的搜索过滤器,因为我没有完全理解JSON数组。这就是我需要帮助的地方。
对预期行为的最简单解释:
为列表创建空数组。为搜索查询创建空字符串。为axios请求和计算属性注入之间的争用条件创建标志,并将其设置为false。
组件根据本地JSON文件数据呈现嵌套对象(“items”)列表,方法是向JSON ( axios.get() )发出请求,并将来自该axios.get ()请求的响应分配给数据()中的空列表数组。然后,在axios请求和赋值为空数组之后,将标志设置为true。
然后,根据标志是真还是假,通过filteredList的计算属性将带有新形成的JSON数据的列表数组注入vue组件,并将其赋值给最高级别的v-for循环(以及嵌套内容其余部分的后续嵌套的v-for循环)。
帮助区
挂起的地方是,我有一个搜索输入,需要过滤(.filter()函数)基于查询字符串('searchString')的内容,然后(我想我需要做的是)根据匹配(.match()函数)将JSON对象重新呈现到查询字符串。我只需要过滤每个部分中的“items”数组(并且可能返回适用的section_title)。
看来,计算属性上的基本筛选函数和返回到searchString数据查询的所有匹配项都不能正常工作。我一直在尝试以下几种方法:
computed: {
filteredList: function() {
let self = this;
if (!self.componentLoaded) {
return null;
}
else {
let listData = self.list;
//-- new search code --//
let searchItem = listData.section.items;
return calcData.filter((searchItem) => {
return searchItem.title.toLowerCase().match(this.searchString.toLowerCase());
});
//-----//
}
}
}或者像这样更强壮的东西:
computed: {
filteredList: function() {
let self = this;
if (!self.componentLoaded) {
return null;
}
else {
let listData = self.list;
//-- new search code --//
let searchItem = listData.section.items;
let searchTerm = (this.searchString || "").toLowerCase();
return listData.filter(function(searchItem) {
let title = (searchItem.title || "").toLowerCase();
let description = (searchItem.description || "").toLowerCase();
let footnote = (searchItem.footnote || "").toLowerCase();
return title.indexOf(searchTerm) > -1 || description.indexOf(searchTerm) > -1 || footnote.indexOf(searchTerm) > -1;
});
//-----//
}
}
}这两个函数在控制台中返回相同的错误:
TypeError: Cannot read property 'items' of undefined我可以使用以下内容来console.log每个键中的任何/所有项:
console.log(JSON.stringify(self.list.KEY_1.items));这很好,但有点不相干。但它真正做的就是确认我的嵌套设置是否正确(?)
我在想,也许我没有正确地遍历所有的初始对象(用键)。或者/还因为我有一个通用JSON对象("examplejson"),它有多个子对象(两个具有自定义键的兄弟对象("KEY_1","KEY_2")),还有进一步嵌套的对象("section_title","section_category"),还有另一个嵌套的兄弟对象("items"),其中包含一个对象数组,这可能导致我的“简单”调用实际上需要一种更复杂的识别/操作顺序,从而需要一种更加复杂/健壮的过滤机制?
还是因为比赛的原因?(我对此表示怀疑,因为控制台日志记录显示首先发出axios.get()请求,然后在标志设置为true之后运行计算函数条件)。
或者可能是完全不同的东西,我甚至没有注意到。
任何帮助或澄清的方向或我做的是对/错的,我们非常感谢。我对Vue很陌生,还在努力想办法解决问题。提前谢谢。
*更新*
I现在能够成功地根据"section_title“过滤结果,方法是删除键("KEY_1”、"KEY_2")并将"examplejson“对象转换为数组(在示例中已经更新)。我可以以section_title为目标,返回包含"section_title“的整个对象,该对象也包含"items”数组。
*只适用于"section_title“目标的更新计算函数**
computed: {
filteredList: function(){
let self = this;
if(! self.componentLoaded) {
return null;
} else {
let listData = self.list;
//-- new working search code for section objects ONLY --//
let searchItem = listData.section;
return listData.filter((searchItem) => {
return searchItem.section_title.match(this.searchString);
});
//-----//
}
}
}现在的问题是,除了以“items”字符串为目标之外,我还需要更深一层地针对section_title数组中的内容。只是将一个.items附加到searchItem变量,因此它读取let searchItem = listData.section.item;或let searchItem = listData.section.items;不工作,并返回Cannot read property 'item' of undefined,因此我不知道如何正确地针对section_title之外的items数组中的对象。
感谢你的任何帮助
发布于 2019-08-28 01:40:31
const list = [
{
"section_title": "title 1",
"section_category": "category1",
"items": [
{
"category": "category1",
"title": "item title 1",
"url": "url 1",
"description": "Etiam turpis ipsum, gravida a odio ac, sollicitudin egestas tortor.",
"footnote": "footnote 1"
},
{
"category": "category1",
"title": "item title 2",
"url": "url 2",
"description": "Suspendisse consectetur lacus sed maximus consectetur. Etiam nunc magna, fringilla.",
"footnote": "footnote 2"
}
]
},
{
"section_title": "title 2",
"section_category": "category2",
"items": [
{
"category": "category2",
"title": "title 3",
"url": "url 3",
"description": "Donec venenatis justo at ligula dictum tempus. In euismod nulla.",
"footnote": "footnote 3"
},
{
"category": "category2",
"title": "title 4",
"url": "url 4",
"description": "Cras dui felis, pulvinar vel elit quis, imperdiet sollicitudin massa.",
"footnote": "footnote 4"
}
]
}
];
const searchString = 'item';
const filteredList = list.filter((section) => {
// `section` here is an arbitrary variable name to represent the individual element in the `listData`
console.log('section', section);
// If section_title contains searchString, add the element to the filtered result
if (section.section_title.indexOf(searchString) > -1) {
return true;
}
// section_title does not contain searchString,
// proceed to check for each section.items if they contain searchString
const hasItemContainsSearchString = section.items.some((item) => {
// `item` here represents the individual element of section.items
console.log('item', item);
// Check if the title contains searchString
return item.title.indexOf(searchString) > -1;
});
return hasItemContainsSearchString;
});
console.log('filteredList', filteredList);
https://stackoverflow.com/questions/57677292
复制相似问题