Javascript 同时使用onChange和onKeyDown
我正在寻找一种方法,将页码输入到输入标记中,然后仅在按下“enter”键时进行渲染,这样我在输入栏中输入的页码就会显示出来。但是,当使用onSearch时,每次我输入一些输入时,页面都会呈现,onKeyDown不允许我键入任何内容,也不能使用onSearch函数(或在其中调用的函数中)按下的键 有没有办法实现这个功能Javascript 同时使用onChange和onKeyDown,javascript,reactjs,input,Javascript,Reactjs,Input,我正在寻找一种方法,将页码输入到输入标记中,然后仅在按下“enter”键时进行渲染,这样我在输入栏中输入的页码就会显示出来。但是,当使用onSearch时,每次我输入一些输入时,页面都会呈现,onKeyDown不允许我键入任何内容,也不能使用onSearch函数(或在其中调用的函数中)按下的键 有没有办法实现这个功能 import React from 'react'; import './App.scss'; import {createApiClient, Ticket} from './a
import React from 'react';
import './App.scss';
import {createApiClient, Ticket} from './api';
export type AppState = {
tickets?: Ticket[],
hidden: {[key: string]: string}, //Obejct to keep hidden tickets
search: string,
pageInput: string,
currentPage: number,
}
const api = createApiClient();
export class App extends React.PureComponent<{}, AppState> {
state: AppState = {
hidden: {},
search: '',
currentPage: 1,
pageInput: '',
}
searchDebounce: any = null;
async componentDidMount() {
this.setState({
tickets: await api.getTickets(this.state.currentPage, this.state.search) //pass the page and the search to show
});
}
hideTicket = (id:string) => () => {}
restoreTickets = () => {}
renderTickets = (tickets: Ticket[]) => {
this.hideTicket = (id:string) => () => { //Hide ticket, deconstruct previous hidden Object and add new id
this.setState(prevState => ({
hidden: {
...prevState.hidden, [id]: id
}
}));
}
const ticketsToShow = tickets.filter((hiddenTicket) => !this.state.hidden[hiddenTicket.id]); //Filter if there are hidden tickets
return (<ul className='tickets'>
{ticketsToShow.map((ticket) => (<li key={ticket.id} className='ticket'>
<div><button className='hide' type='button' onClick={this.hideTicket(ticket.id)}>Hide</button></div>
<h5 className='title'>{ticket.title}</h5>
<p className='content'>{ticket.content}</p>
<footer>
<div className='meta-data'>By {ticket.userEmail} | { new Date(ticket.creationTime).toLocaleString()}</div>
<div id="tag-container">
{ticket.labels ? ticket.labels.map((label, index) => (
<span key={index} className="ticket-label">{label}</span>
)) : null}
</div>
</footer>
</li>))}
</ul>);
}
onSearch = async (val: string, newPage?: number) => {
clearTimeout(this.searchDebounce);
this.searchDebounce = setTimeout(async () => {
this.setState({
search: val,
currentPage: 1, //Go to the first page
tickets: await api.getTickets(1, val)
});
}, 300);
}
onChange = async (page: number) => {}
onJump = async(page: string) => {}
onEnter = async (event: string) => {}
render() {
const {tickets} = this.state;
this.restoreTickets = () => { //Clean the hidden tickets Object from tickets
for(const id in this.state.hidden){
delete this.state.hidden[id];
}
this.setState({
hidden:{}
});
}
this.onChange = async (page: number) => {
this.restoreTickets()
this.setState({
currentPage: page,
tickets: await api.getTickets(page, this.state.search) //Show next page
});
}
this.onEnter = async (event: string) => {
if(event.keyCode === 'enter')
this.restoreTickets();
this.setState({
currentPage: parseInt(this.state.pageInput),
pageInput: this.state.pageInput,
tickets: await api.getTickets(parseInt(this.state.pageInput), this.state.search)
})
}
return (<main>
<h1>Tickets List</h1>
<header>
<input type="search" placeholder="Search..." onChange={(e) => this.onSearch(e.target.value)}/>
</header>
{Object.keys(this.state.hidden).length === 0 && tickets ? <div className='results'>Showing {tickets.length} results</div>
: tickets ? <div className='results-hidden'>Showing {tickets.length - Object.keys(this.state.hidden).length} results <span id="hidden-tag">({Object.keys(this.state.hidden).length} tickets hidden -
<button className='restore-btn' onClick={this.restoreTickets}>restore</button>)</span></div> : null}
{tickets ? this.renderTickets(tickets) : <h2>Loading..</h2>}
<div><input type='search' onChange={(e) => this.onEnter(e.target.value)}></input>{this.state.currentPage === 1 && this.state.tickets && this.state.tickets.length < 20 ? null :
this.state.currentPage === 1 ? <div className="next-back-btn-container"><a className="next-btn" href="#" onClick={() => this.onChange(this.state.currentPage + 1)}>Next</a></div> :
this.state.tickets && this.state.tickets.length < 20 ? <div className="next-back-btn-container"><a className="back-btn" href="#" onClick={() => this.onChange(this.state.currentPage - 1)}>Back</a></div>:
<div className="next-back-btn-container">
<a className="back-btn" href="#" onClick={() => this.onChange(this.state.currentPage - 1)}>Back</a>
<a className="next-btn" href="#" onClick={() => this.onChange(this.state.currentPage + 1)}>Next</a>
</div>}</div>
</main>)
}
}
export default App;
从“React”导入React;
导入“/App.scss”;
从“/api”导入{createApiClient,Ticket};
导出类型AppState={
票?:票[],
隐藏:{[key:string]:string},//Obejct保留隐藏票据
搜索:字符串,
pageInput:string,
当前页面:编号,
}
const api=createApiClient();
导出类应用程序扩展了React.PureComponent{
状态:AppState={
隐藏:{},
搜索:“”,
当前页面:1,
页面输入:“”,
}
searchDebounce:any=null;
异步组件didmount(){
这是我的国家({
票证:wait api.getTickets(this.state.currentPage,this.state.search)//传递要显示的页面和搜索
});
}
hideTicket=(id:string)=>()=>{}
restoreTickets=()=>{}
renderTickets=(票证:票证[])=>{
this.hideTicket=(id:string)=>()=>{//隐藏票据,解构以前隐藏的对象并添加新id
this.setState(prevState=>({
隐藏的:{
…prevState.hidden,[id]:id
}
}));
}
const ticketsToShow=tickets.filter((hiddenTicket)=>!this.state.hidden[hiddenTicket.id]);//如果存在隐藏的票据,则进行筛选
返回(
{ticketsToShow.map((ticket)=>(-
隐藏
{ticket.title}
{ticket.content}
通过{ticket.userEmail}{new Date(ticket.creationTime.toLocaleString()}
{ticket.labels?ticket.labels.map((标签,索引)=>(
{label}
)):null}
)}
);
}
onSearch=async(val:string,newPage?:number)=>{
clearTimeout(this.searchDebounce);
this.searchDebounce=setTimeout(异步()=>{
这是我的国家({
搜索:val,
currentPage:1,//转到第一页
门票:等待api.getTickets(1,val)
});
}, 300);
}
onChange=async(页码)=>{}
onJump=async(页面:字符串)=>{}
onEnter=async(事件:字符串)=>{}
render(){
const{tickets}=this.state;
this.restoreTickets=()=>{//从tickets中清除隐藏的tickets对象
for(此.state.hidden中的常量id){
删除此.state.hidden[id];
}
这是我的国家({
隐藏:{}
});
}
this.onChange=async(页码)=>{
这个.restoreTickets()
这是我的国家({
当前页:第页,
票证:wait api.getTickets(第页,this.state.search)//显示下一页
});
}
this.onEnter=async(事件:字符串)=>{
如果(event.keyCode==='enter')
这个。restoreTickets();
这是我的国家({
currentPage:parseInt(this.state.pageInput),
pageInput:this.state.pageInput,
票证:wait api.getTickets(parseInt(this.state.pageInput)、this.state.search)
})
}
返回(
门票单
this.onSearch(e.target.value)}/>
{Object.keys(this.state.hidden).length==0&&tickets?显示{tickets.length}结果
:tickets?显示{tickets.length-Object.keys(this.state.hidden).length}结果({Object.keys(this.state.hidden).length}tickets隐藏-
还原):null}
{tickets?this.renderTickets(tickets):正在加载..}
this.oneter(e.target.value)}>{this.state.currentPage==1&&this.state.tickets&&this.state.tickets.length<20?空:
this.state.currentPage==1?:
this.state.tickets&&this.state.tickets.length<20?:
}
)
}
}
导出默认应用程序;