我正在研究一个应该能够做到的组件
按输入搜索-触发onBlur事件后,将使用输入字段调用一个函数。 onBlur 事件发生后, startSearch ()方法将运行。
按选定流派过滤-用户可以从其他组件中从具有流派的列表中选择流派。在 onClick 事件之后,将运行 startFilter ()方法。
好消息: 我已经完成了上面的两个功能。
坏消息: 上述2个功能无法正常使用。请参见下面的代码。在工作下面有2个调用,但是仅当我注释掉2个之一时。我试图以各种方式调整 startSearch ()方法,但我一直走到一堵胖墙。
//////Searching works
//////this.filter(this.state.searchInput);
//Filtering works
this.startFilter(this.state.searchInput);
问题 如何使过滤器/搜索方法起作用?。不幸的是,简单地将它们放在if / else中不是解决方案(请参阅代码中的注释)。
import { Component } from 'preact';
import listData from '../../assets/data.json';
import { Link } from 'preact-router/match';
import style from './style';
export default class List extends Component {
state = {
selectedStreamUrl: '',
searchInput: '',
showDeleteButton: false,
searchByGenre: false,
list: []
};
startFilter(input, filterByGenre) {
this.setState({
searchByGenre: true,
searchInput: input,
showDeleteButton: true
});
alert('startFilter ');
console.log(this.state.searchByGenre);
/////////---------------------------------
document.getElementById('searchField').disabled = false;
document.getElementById('searchField').value = input;
document.getElementById('searchField').focus();
// document.getElementById('searchField').blur()
document.getElementById('searchField').disabled = true;
console.log(input);
this.filter(input);
}
//search
startSearch(input) {
alert('startSearch ');
console.log(this.state.searchByGenre);
//komt uit render()
if (!this.state.searchByGenre) {
//check for input
this.setState({
searchInput: input.target.value,
showDeleteButton: true
});
//Searching works
//this.filter(this.state.searchInput);
//Filtering works
this.startFilter(this.state.searchInput);
// DOESNT WORK:
// if (this.state.searchInput != "") {
// this.filter(this.state.searchInput);
// } else {
// this.startFilter(this.state.searchInput);
// }
}
}
setAllLists(allLists) {
console.log('setAllLists');
console.log(this.state.searchByGenre);
this.setState({ list: allLists });
//document.body.style.backgroundColor = "red";
}
filter(input) {
let corresondingGenre = [];
let filteredLists = listData.filter(item1 => {
var test;
if (this.state.searchByGenre) {
alert('--this.state.searchByGenre');
//filterByGenre
//& item1.properties.genre == input
for (var i = 0; i < item1.properties.genre.length; i++) {
if (item1.properties.genre[i].includes(input)) {
corresondingGenre.push(item1);
test = item1.properties.genre[i].indexOf(input) !== -1;
return test;
}
this.setState({ list: corresondingGenre });
}
} else {
//searchByTitle
alert('--default');
test = item1.title.indexOf(input.charAt(0).toUpperCase()) !== -1;
}
return test;
});
console.log('filterdLists:');
console.log(filteredLists);
console.log('corresondingGenre:');
console.log(corresondingGenre);
//alert(JSON.stringify(filteredLists))
this.setState({ list: filteredLists });
}
removeInput() {
console.log('removeInput ');
console.log(this.state.searchByGenre);
this.setState({
searchInput: '',
showDeleteButton: false,
searchByGenre: false
});
document.getElementById('searchField').disabled = false;
this.filter(this.state.searchInput);
}
render() {
//alle 's komen in deze array, zodat ze gefilterd kunnen worden OBV title.
if (
this.state.list === undefined ||
(this.state.list.length == 0 && this.state.searchInput == '')
) {
//init list
console.log('render ');
console.log(this.state.searchByGenre);
this.filter(this.state.searchInput);
}
return (
<div class={style.list_container}>
<input
class={style.searchBar}
type="text"
id="searchField"
placeholder={this.state.searchInput}
onBlur={this.startSearch.bind(this)}
/>
{this.state.searchByGenre ? <h1>ja</h1> : <h1>nee</h1>}
{this.state.showDeleteButton ? (
<button class={style.deleteButton} onClick={() => this.removeInput()}>
Remove
</button>
) : null}
{this.state.list.map((item, index) => {
return (
<div>
<p>{item.title}</p>
</div>
);
})}
</div>
);
}
}
答案 0 :(得分:2)
您要问的问题不清楚。但是,请尝试对组件进行明确说明以帮助调试问题。例如,使用构造函数并在其中声明组件状态。另外,为简洁起见,请为您的.bind做事件。
以下示例在触发onBlur事件时将状态变量捕获为true,这与其初始状态值相同:
class List extends React.Component {
constructor(props) {
super(props);
this.state = {
searchByGenre: true
};
this.startSearch = this.startSearch.bind(this);
}
startSearch() {
// This value is true
console.log(this.state.searchByGenre)
}
render() {
return (
<input
type="text"
id="searchField"
placeholder="Search"
value={this.state.searchInput}
onBlur={this.startSearch}
/>
)
}
答案 1 :(得分:1)
要使搜索和过滤器正常工作,您需要两个数组。
macro_rules! match_token_pattern {
($parser:ident, $a:ident) => {{
let a = $parser.$a();
if a != None {
Some(a)
} else {
None
}
}};
($parser:ident, $a:ident, $b:ident) => {{
let a = $parser.$a();
let b = $parser.$b();
if a != None && b != None {
Some((a, b))
} else {
None
}
}};
($parser:ident, $a:ident, $b:ident, $c:ident) => {{
let a = $parser.$a();
let b = $parser.$b();
let c = $parser.$c();
if a != None && b != None && c != None {
Some((a, b, c))
} else {
None
}
}};
}
您的搜索功能将使用state = {
selectedStreamUrl: "",
searchInput: "",
showDeleteButton: false,
// searchByGenre: false, // removed, will use filter by from a list
// by default both arrays have the same value
list: listData, // holds the original data, doesn't change
filteredList: listData, // holds filterd list, filtered when the user types in input
// by default filter by title, will change when user, use a value from a list
filterBy: 'title',
}
值来过滤数组。无需创建多个功能。这样可以为您提供灵活性,因为您可以使用下拉菜单中的多个值进行过滤,而无需更改代码。
this.state.filterBy
删除输入功能
startSearch = (value) => {
const search = value.toLowerCase();
// get filter value title, genre, etc
const searchKey = this.state.filterBy;
this.setState({
searchInput: value,
filteredList: this.state.list.filter(item => {
// filter base on key item['title'] or item['genre'] etc
return item && item[searchKey].toLowerCase().includes(search)
}),
showDeleteButton: !!value,
})
}
我看到您正在做很多removeInput = () => {
this.setState({
filterBy: 'title',
showDeleteButton: false,
searchInput: '',
}, () => this.startSearch(this.state.searchInput));
}
。不要直接操纵dom,让react为您管理。
在下方查看演示
document.getElementById("searchField").disabled = false;
h1, p {
font-family: Lato;
}
.container {
display: flex;
flex-direction: row;
border-bottom-style: solid;
margin-bottom: 5px;
}
.image-container {
flex-grow: 0;
}
.info-container {
flex-grow: 1;
margin-left: 10px
}
.title {
margin-top: 0;
}
.cover {
width: 60px;
}
答案 2 :(得分:0)
两种方法:
将绑定更改为构造函数(以及状态!)
constructor(props) {
super(props);
this.state = { searchByGenre: true }
this.startSeach = startSearch.bind(this);
}
startSearch(searchByGenre) {
//This is false after the call
console.log(this.state.searchByGenre)
}
render() {
return (
<input class={style.searchBar} type="text" id="searchField" placeholder="Search" value={this.state.searchInput} onBlur={this.startSearch} >
</input>
)
}
这样,您可以将startSearch
与参数一起使用:
<input class={style.searchBar}
type="text"
id="searchField"
placeholder="Search"
value={this.state.searchInput}
onBlur={() => this.startSearch(this.state.searchByGenre)}
>
OR ,您可以将startSearch
更改为箭头函数,并从构造函数中删除绑定:
startSearch = (searchByGenre) => {
//This is false after the call
console.log(this.state.searchByGenre)
}
您可以查看为什么发生这种情况here。
编辑:该链接只讨论typeScript,但忽略它,而将重点放在 arrow function / bind 部分