我拼命想让淘汰赛对我的项目进行实时搜索。此搜索需要能够区分查询中的空格并将其用作分离的搜索查询。例如;如果用户输入" Matrix"它可以同时播放DVD和Bluray Matrix电影...但如果用户输入Matrix DVD则没有任何内容。
我试图让它搜索查询中空格分隔的数据中的所有内容。
这是我的小提琴:https://jsfiddle.net/neosketo/eLgscy1t/10/
HTML:
<div id="container">
<h1>Movie Search</h1>
<form>
<input id="search" type="search" name="search" placeholder="Search for a user" data-bind="value: query, valueUpdate: 'keyup'" autocomplete="off" />
</form>
<table data-bind="visible: movies().length > 0">
<thead><tr><th>Type</th><th>Name</th><th>Media</th></tr></thead>
<tbody data-bind="foreach: movies">
<tr>
<td data-bind="text: type"></td>
<td data-bind="text: name"></td>
<td data-bind="text: media"></td>
</tr>
</tbody>
</table>
</div>
JAVASCRIPT:
var movies = [
{ type: 'action', name: 'The Matrix', media: 'DVD'},
{ type: 'action', name: 'The Matrix', media: 'Bluray'},
{ type: 'fantasy', name: 'Lord of the Rings', media: 'DVD'},
{ type: 'fantasy', name: 'Lord of the Rings', media: 'Bluray'},
{ type: 'comedy', name: 'Dumb and Dumber', media: 'DVD'},
{ type: 'comedy', name: 'Dumb and Dumber', media: 'Bluray'}
];
var viewModel = {
movies: ko.observableArray([]),
query: ko.observable(''),
search: function(value) {
viewModel.movies.removeAll();
if (value == '') return;
for (var movie in movies) {
if (movies[movie].name.toLowerCase().indexOf(value.toLowerCase()) >= 0) {
viewModel.movies.push(movies[movie]);
}
}
}
};
viewModel.query.subscribe(viewModel.search);
ko.applyBindings(viewModel);
答案 0 :(得分:2)
我首先要扩展您的电影对象,以包含他们自己的搜索字词集合。每次键入字符时都不想重新计算:
var moviesWithSearchString = movies.map(function(movie) {
var ogKeys = Object.keys(movie);
return Object.assign({}, movie, {
_searchProps: ogKeys
.map(function(key) {
return movie[key].toLowerCase();
})
});
});
_searchProps
属性包含一系列搜索词。第一部电影:["action", "the matrix", "dvd"]
现在,在您的search
方法中,我们还需要将搜索查询转换为小写单词数组:
var searchVals = value
.toLowerCase()
.split(" ");
然后,有趣的部分开始了。我们希望每个(Array.prototype.every
)搜索字出现(String.prototype.includes
)至少一次({{3我们电影的属性:
viewModel.movies(moviesWithSearchString.filter(function(movie) {
return searchVals.every(function(searchVal) {
return movie._searchProps.some(function(searchProp) {
return searchProp.includes(searchVal);
});
});
}));
工作示例:
stack snippet:
var movies = [{
type: 'action',
name: 'The Matrix',
media: 'DVD'
}, {
type: 'action',
name: 'The Matrix',
media: 'Bluray'
}, {
type: 'fantasy',
name: 'Lord of the Rings',
media: 'DVD'
}, {
type: 'fantasy',
name: 'Lord of the Rings',
media: 'Bluray'
}, {
type: 'comedy',
name: 'Dumb and Dumber',
media: 'DVD'
}, {
type: 'comedy',
name: 'Dumb and Dumber',
media: 'Bluray'
}];
var moviesWithSearchString = movies.map(function(movie) {
var ogKeys = Object.keys(movie);
return Object.assign({}, movie, {
_searchProps: ogKeys
.map(function(key) {
return movie[key].toLowerCase();
})
});
});
var viewModel = {
movies: ko.observableArray([]),
query: ko.observable(''),
search: function(value) {
var searchVals = value
.toLowerCase()
.split(" ");
viewModel.movies(moviesWithSearchString.filter(function(movie) {
return searchVals.every(function(searchVal) {
return movie._searchProps.some(function(searchProp) {
return searchProp.includes(searchVal);
});
});
}));
}
};
viewModel.query.subscribe(viewModel.search);
ko.applyBindings(viewModel);
body {
margin: 2em;
text-align: center;
}
form {
margin-bottom: 2em;
}
table {
text-align: left;
margin: 0 auto;
}
th,
td {
padding: .2em;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<div id="container">
<h1>Movie Search</h1>
<form>
<input id="search" type="search" name="search" placeholder="Search for a user" data-bind="value: query, valueUpdate: 'keyup'" autocomplete="off" />
</form>
<table data-bind="visible: movies().length > 0">
<thead>
<tr>
<th>Type</th>
<th>Name</th>
<th>Media</th>
</tr>
</thead>
<tbody data-bind="foreach: movies">
<tr>
<td data-bind="text: type"></td>
<td data-bind="text: name"></td>
<td data-bind="text: media"></td>
</tr>
</tbody>
</table>
</div>
请注意,旧浏览器不支持某些Array
和String
方法。查看关于polyfills的链接文章。
答案 1 :(得分:0)
您可以按空格拆分查询字词,然后使用.some
数组方法搜索电影。
search: function(value) {
viewModel.movies.removeAll();
if (!value) return;
var values = value.split(' ');
for (var movie in movies) {
var found = values.some(function(word) {
return !!word && movies[movie].name.toLowerCase().indexOf(word.toLowerCase()) >= 0;
});
if (found) {
viewModel.movies.push(movies[movie]);
}
}
}
!!word
只是在用户输入多个空格的情况下短暂搜索,导致分割中出现空字符串。