interface INumberPagerItem {
url: string;
text: string;
page: number;
title: string;
target: string;
iscurrent: boolean;
enabled: boolean;
}
interface INumberPager {
total: number;
current: number;
showcount: number;
items: INumberPagerItem[];
}
class NumberPagerItemModel implements INumberPagerItem {
url: string;
text: string;
page: number;
target: string;
iscurrent: boolean;
title: string;
enabled: boolean;
constructor(url: string, text: string, page: number, title: string, target: string, iscurrent: boolean, enabled: boolean) {
this.url = url;
this.text = text;
this.page = page;
this.title = title;
this.target = target;
this.iscurrent = iscurrent;
this.enabled = enabled;
}
}
class NumberPagerItem extends React.Component<INumberPagerItem, any>{
render() {
var a = null;
if (this.props.enabled) {
a = <a title={this.props.title} href={this.props.url + this.props.page} className={"ws-pager " + (this.props.iscurrent ? "ws-pager-current-page" : "ws-pager-page")} target={this.props.target} >{this.props.text}</a>
}
else {
a = <span title={this.props.title} className={"ws-pager " + (this.props.iscurrent ? "ws-pager-current-page" : "ws-pager-page")} >{this.props.text}</span>
}
return (a);
}
}
class NumberPager extends React.Component<INumberPager, any>{
constructor(props: INumberPager) {
super(props);
}
render() {
var items = this.props.items.map((i) => {
return (<NumberPagerItem key={i.text.toString() + i.page.toString()} title={i.title} enabled={i.enabled} text={i.text} url={i.url} page={i.page} iscurrent={i.iscurrent} target={i.target || '_self'} />);
});
return (
<span>
{items}
</span>);
}
}
interface IFastPager {
current: number;
totalpages: number;
fastToPage(next: number): void;
}
class FastPager extends React.Component<IFastPager, any>{
next: number;
constructor() {
super();
this.state = { current: 1, godisabled: true }
}
componentWillMount() {
this.state.current = this.props.current;
this.next = this.props.current;
}
handleChange(e) {
this.next = parseInt(e.target.value);
this.state.godisabled = this.next == this.state.current;
this.setState(this.state);
}
handleClick(e) {
if (this.next != this.state.current) {
this.next = this.next > this.props.totalpages ? this.props.totalpages : this.next;
this.props.fastToPage(this.next);
}
}
render() {
return (
<span className="ws-pager-fast">
<label>
到第
<input type="number" name="ws-pager-fast-number" className="ws-pager-fast-page-number" defaultValue={this.state.current} onChange={e => this.handleChange(e)} />
页
</label>
<input type="button" className="ws-pager-fast-confrim" value="确定" disabled={this.state.godisabled} onClick={e => this.handleClick(e)} />
</span>
);
}
}
interface IWsPager {
url: string;
target?: string;
total: number;
size: number;
current: number;
showcount: number;
needfast: boolean;
}
interface IWsPagerState {
current: number;
items: INumberPagerItem[];
}
class WsPager extends React.Component<IWsPager, IWsPagerState>{
constructor(props: IWsPager) {
super(props);
this.state = { current: this.props.current, items: [] };
}
componentWillMount() {
let numbers: number[] = [];
var total = parseInt((document.getElementById('ws_pager_total') as HTMLInputElement).value);
var current = parseInt((document.getElementById('ws_pager_current') as HTMLInputElement).value);
this.state.current = current;
let totalpage = Math.ceil(total / this.props.size);
let prepage = this.state.current - 1;
let nextpage = this.state.current + 1;
numbers.push(-10);
if (totalpage - this.props.showcount <= 0) {
for (var i = 1; i <= totalpage; i++) {
numbers.push(i);
}
}
else {
let half = (this.props.showcount - 1) / 2;
let pre = this.state.current - half;
let next = this.state.current + half;
numbers.push(1);
if (pre > half) {
numbers.push(-9);
}
var start = pre;
if (pre < 2) {
start = 2;
var end = start + this.props.showcount > totalpage ? totalpage : start + this.props.showcount
for (var i = start; i < end; i++) {
numbers.push(i);
}
}
else {
start = pre;
if (next >= totalpage) {
next = totalpage - 1;
start = next - this.props.showcount;
for (var i = start; i <= next; i++) {
numbers.push(i);
}
} else {
for (var i = pre; i < this.state.current; i++) {
numbers.push(i);
}
if (this.state.current != 1) {
numbers.push(this.state.current);
}
for (var i = this.state.current + 1; i <= next; i++) {
numbers.push(i);
}
}
}
if (next + 1 < totalpage) {
numbers.push(-2);
}
numbers.push(totalpage);
}
numbers.push(-1);
var items: INumberPagerItem[] = [];
for (var i = 0; i < numbers.length; i++) {
var num = numbers[i];
if (num == -10) {
items.push(new NumberPagerItemModel(this.props.url, '上一页', prepage, '上一页', null, false, prepage > 0));
} else if (num == -1) {
items.push(new NumberPagerItemModel(this.props.url, '下一页', nextpage, '下一页', null, false, nextpage <= totalpage));
} else if (num == -9) {
items.push(new NumberPagerItemModel(null, '...', num, '向前' + this.props.showcount.toString() + "页", null, false, false));
} else if (num == -2) {
items.push(new NumberPagerItemModel(null, '...', num, '向后' + this.props.showcount.toString() + "页", null, false, false));
} else {
items.push(new NumberPagerItemModel(this.props.url, num.toString(), num, num.toString(), null, this.state.current == num, this.state.current != num));
}
}
this.setState({ current: this.state.current, items: items });
}
handleFastToPage(e) {
window.location.href = this.props.url + e;
}
render() {
var p = null;
if (this.props.needfast) {
p =
(
<p>
<NumberPager items={this.state.items} total={this.props.total} current={this.state.current} showcount={this.props.showcount} />
<FastPager current={this.state.current} totalpages={Math.ceil(this.props.total / this.props.size)} fastToPage={e => this.handleFastToPage(e)} />
</p>
);
} else {
p =
(
<p>
<NumberPager items={this.state.items} total={this.props.total} current={this.state.current} showcount={this.props.showcount} />
</p>
)
}
return (p);
}
}
ReactDOM.render(
<WsPager url="/pager/index/" needfast={true} current={1} showcount={9} size={10} total={124} />,
document.getElementById('pager')
)
目前我就是最笨的判断,if else 嵌套,可有算法优化一下?
就是计算numbers数组的值的算法。
Copyright 2014-2024 //m.sbmmt.com/ All Rights Reserved | php.cn | 湘ICP备2023035733号
这个问题相当的不容易回答,我只能以目前的所知的范围提供一些思路而已。
不容易回答的原因:
代码中使用了TypeScript在撰写React组件,两者都要会的人不多
代码中完全乎没有注解,组件/方法/运行代码并未达到能自我文档化的程度,也没有具体的说明各方法或各组件的用途
这个代码的用途与对照的视觉介面、操作目的、事件触发规则,都没有额外的文档可以参考
代码的重构有几个方针可以参考:
撰写风格的统一
注释是很重要的,尤其是针对重要的某些运行代码行或方法。代码中混用了var/let/const。另外在变量的识别名的命名也有一些小地方,例如
godisabled
应为goDisabled
、iscurrent
应为isCurrent
。比较严重的风格是在React的JSX语法,一行的长度许多超过80字元,有些行已经超过屏幕的宽度,这建议要调整,不然真的不容易维护。分隔组件的清楚工作
既然要使用React,想必应该能理解React库是用来开发一个个的组件用的,组件是一个有上下(内外)层级的树状构造,每个组件中的state都是独立的,父子组件用props来传递数据,细节不多说网上教程很多。但首要的是需要先清楚各组件/模组该作的事。回到原来的代码,这里面的这些组件都有没有分割清楚的问题,像
FastPager
应该是个带有个文字框,然后按下按钮跳到第几页的功能,它就单纯作这事就行。以React的组件设计观点来说,FastPager
必然只是个子组件,它这中只会用来呈现这操作介面,然后准备让用户触发click事件,向父层说现在要跳转到第几页了,其它的事与它无关。现在的FastPager
里除了有state之外,还会传入totalpages(总页数),FastPager
并不需要知道总共有多少页,甚至连现在是第几页(current)都不需要,检查这事是它的父组件的触发相关方法中就行了。另外关于NumberPager
与NumberPagerItem
,它们的工作与FastPager
也很像,是用来跳转页面用的,但只是操作介面呈现上的差异,但现在父组件WsPager
中出现相当复杂的算法,也是因为工作不明所造成的,要优化这段代码,就是要从这两者的工作分隔著手。掌控数据流&生命周期
数据是从什么地方来的?事件是如何被触发的,触发时要调用哪个方法?数据流是整个应用的核心,数据该集中在何处,事件该在何处撰写它的业务逻辑,这些都是很重要的。
在React中,state与props的角色完全不同,state是一个状态机,记录了这个组件的目前与可能变动的状态。更动state代表著会触发重新渲染。以一个小型的React应用来说,大概只会在最上层的父组件有state,子组件中会避免使用state,state并不是都需要的,子组件中的state更动不见得会触发整个应用的重新渲染,这机制应该要理解。
componentWillMount
是一个React中的生命周期方法,在componentWillMount
中调用setState
方法并不会触发重新渲染,所以是用在与呈现无关的数据上使用。在componentDidMount
方法里中调用setState
方法会触发重新渲染。但它们都只在组件挂载到网页上调用一次而已,之后的更新期间并不会再调用,所以大概的用途是组件初始时加载数据用的,尤其是向外部服务器加载数据等等的工作。由简单开始改起
一开始的应用代码必定是很粗糙简单,也没什么太大的配置弹性。对于所有的应用来说,一次就要到位是不太可能作得到的,这个题目的代码已经作了相当程度的配置弹性,也就是说它已经在撰写时决定了要这些配置,当然这也让它增加了许多复杂的部份。为了要让整体的代码作重构,应该先把部份重要性不高的配置先移除,例如风格之类的,或是要能某些弹性配置的值。
简化复杂的运算
复杂的运算结构,或许是能达成目前的需求,例如内嵌(巢状)的for逥圈、递归、大量的if判断等等,但它们都有一定的复杂程度。在维护与未来扩展上,都会造成一定的困难程度,简化是必要的,如果因为过多的功能造成代码的复杂,那么是应退一步思考,看是先把某几个部份的功能分拆,或是某些功能上的调整,避免产生复杂的运算结构。
以上都是概念性的说词,只是一些感想而已。
上面废话说了太多,实际上直接看这应用在React里怎么实作才有用,因为我对题目中的代码也是看了许久一知半解,所以只能以所想到的几个功能来写,下面只是简单的演示,提供一些思路供参考,我在代码里面都有加注释了,看不懂再问吧。
演示的样子(图中的文字框输入触发事件后,应该要强制转为数字,代码已经改过了,图就不改了):
几个问题
document.getElementById('ws_pager_total')不应该出现
分页你的需求如果够了这样也可以,不然还要再拆分原子化
最好支持 smart 和 dumped