【发布时间】:2019-12-31 18:56:37
【问题描述】:
希望推断 Vue 中已广泛存在的 JSON 搜索/过滤/匹配功能可用于计算函数。这是我的情况。
我有一个本地 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 (axios.get()) 发出请求并将来自该 axios.get() 请求的响应分配给我的数据()中的空列表数组。然后,在 axios 请求并分配到空数组后,将标志设置为 true。
然后根据flag是真还是假,将返回新形成的JSON数据的list数组通过filteredList的computed属性注入vue组件,并将其赋值给最高级的v-for循环(以及用于其余嵌套内容的后续嵌套 v-for 循环)。
帮助区
我被挂断的地方是我有一个搜索输入,我需要根据查询字符串('searchString')过滤(.filter()函数)内容,然后(我认为我需要要做的是)根据其匹配(.match() 函数)将 JSON 对象重新渲染到查询字符串。我只需要过滤每个部分中的“项目”数组(并可能返回适用的 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(JSON.stringify(self.list.KEY_1.items));
这很好,但有点无关紧要。但它所做的只是确认我的嵌套设置正确(?)。
我在想也许我没有正确地遍历所有初始对象(带键)。或者/也由于我有一个带有多个子对象(2 个具有自定义键的兄弟对象(“KEY_1”、“KEY_2”))的通用 JSON 对象(“examplejson”),以及更多嵌套对象(“section_title”, “section_category”)和另一个嵌套的兄弟对象(“items”),其中包含对象数组,可能导致我的“简单”调用实际上需要更复杂的识别/操作顺序,因此需要更多复杂/强大的过滤机制?
或者可能仍然是因为比赛条件? (我对此表示怀疑,因为控制台日志显示首先发出 axios.get() 请求,然后在 flag 设置为 true 后运行计算函数条件)。
或者也许这是完全不同的东西,我什至没有注意到。
非常感谢任何有关方向或我做对/错的帮助或说明。我对 Vue 还很陌生,仍在尝试解决问题。提前致谢。
*****更新*****
我现在可以通过删除键(“KEY_1”、“KEY_2”)并将“examplejson”对象转换为数组(已在示例中更新)成功地根据“section_title”过滤结果)。我可以定位 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);
});
//-----//
}
}
}
现在的问题是,除了定位“section_title”字符串之外,我还需要更深入地定位items 数组中的内容。只是将.items 附加到searchItem 变量,所以它读取let searchItem = listData.section.item; 或let searchItem = listData.section.items; 不起作用并返回Cannot read property 'item' of undefined,所以我不确定如何正确定位items 数组中的对象除了section_title。
任何帮助表示赞赏
【问题讨论】:
-
TypeError: Cannot read property 'items' of undefined在尝试访问具有undefined值的.items时发生。在这种情况下,这意味着listData.section在listData.section.items中是undefined。 -
@WeiSengTan 如果我将
listData.section更改为listData.KEY_1.items中的listData.KEY_1之类的键,我没有得到未定义,但listData 过滤不起作用 -
你能提供一个示例输入(搜索字符串)和过滤列表的预期输出吗?
-
@WeiSengTan 是的。示例输入将是:“项目标题 2”或“2”的部分字符串,预期输出将是
"KEY_1"数组"items"对象和"title" : "item title 2"。理想情况下,我需要为较大的 JSON 对象"examplejson" -
@WeiSengTan 我已更新问题以显示最近的进展。除了这个
section_title
标签: json vue.js search filter axios