渲染1000多条checkbox组件,选择点击选择checkbox组件的时候卡出新高度,怎么解决,跪求
渲染1000多条checkbox组件,选择点击选择checkbox组件的时候卡出新高度,怎么解决,跪求
wqvbwang
#3
确实能用一个函数最好,不过如果他要接受一个可变的i,这个就没有办法用一个函数。
这个问题我感觉重点是,你用的checkbox应该是一个包装的组件,不是原生的。用原生的会好很多。
我用ant的checkbox 4000卡到爆,原生4000还是相当流畅的
function test(){
dispatch({type:"main/initState"})
}
return (<div>{function () {
let t = Date.now()
let arr = [], i = 4000;
while (i--) {
arr.push(<label key={i}><input type="checkbox" onChange={function(e){test(),console.log(e)}}/>checkbox{i}</label>)
}
return arr;
}()}</div>)
oyb81076
#6
CheckboxItem再封装一次,然后用shouldComponentUpdate手工计算以下可以减少render次数
// tslint:disable:jsx-no-lambda
// tslint:disable:no-console
import * as React from 'react';
interface IData {
id: number
title: string
}
interface IState {
checkedValues: Set<IData>;
data: IData[];
}
interface IProps {
value: IData
checked: boolean
onChange: (v: IData) => void
}
class ItemComp extends React.Component<IProps> {
public shouldComponentUpdate(nextProps: IProps) {
const props = this.props;
return props.value !== nextProps.value || props.checked !== nextProps.checked
}
public render() {
const { value, checked } = this.props;
return (
<label>
<input
type="checkbox"
checked={checked}
onChange={this.onChange} />
{value.title}
</label>
)
}
private onChange = () => {
this.props.onChange(this.props.value);
}
}
// tslint:disable-next-line:max-classes-per-file
export default class App extends React.Component<{}, IState> {
constructor(props: {}) {
super(props)
const initValue: IState = {
checkedValues: new Set(),
data: []
}
for (let i = 0; i < 10000; i++) {
initValue.data.push({ id: Math.random(), title: "label" + i })
}
this.state = initValue;
}
public render() {
const onChange = this.onChange;
const { checkedValues, data } = this.state;
return (
<div className="App">
{data.map((value) =>
<ItemComp
key={value.id}
value={value}
checked={checkedValues.has(value)}
onChange={onChange} />
)}
</div>
);
}
private onChange = (active: IData) => {
const checkedValues = new Set(this.state.checkedValues);
if (checkedValues.has(active)) {
checkedValues.delete(active);
} else {
checkedValues.add(active);
}
this.setState({ checkedValues })
}
}
oyb81076
#7
用redux的话也可以避免不必要的render
import * as React from "react";
import * as ReactDOM from "react-dom";
import { connect, Provider } from "react-redux";
import { createStore } from "redux";
interface IData {
id: number
title: string
}
interface IState {
checkedValues: Set<IData>;
data: IData[];
}
const initValue: IState = {
checkedValues: new Set(),
data: []
}
for (let i = 0; i < 5000; i++) {
initValue.data.push({ id: Math.random(), title: "label" + i })
}
const reducer = (state = initValue, action: { type: string, index: number }): IState => {
if (action.type === "active") {
const { checkedValues } = state
const { data } = state
const value = data[action.index];
if (!checkedValues.has(value)) {
checkedValues.add(value)
} else {
checkedValues.delete(value)
}
return { data, checkedValues };
}
return state;
}
const store = createStore(reducer)
const ItemComp: React.SFC<{ checked: boolean, value: IData, onChange: () => void }> = (
{ checked, value: { title }, onChange }
) => {
// tslint:disable-next-line:no-console
console.log("render Item")
return (
<label>
<input
type="checkbox"
checked={checked}
onChange={onChange} />
{title}
</label>
)
}
const enhancer = connect<{ checked: boolean, value: IData }, { onChange: () => void }, { index: number }, IState>(
(state, { index }) => {
const value = state.data[index];
return { checked: state.checkedValues.has(value), value }
},
(dispatch, { index }) => ({ onChange() { dispatch({ type: "active", index }) } }))
const Item = enhancer(ItemComp);
const List = connect<{ len: number }, {}, {}, IState>(
(state) => ({ len: state.data.length })
)(function ListComponent({ len }: { len: number }) {
// tslint:disable-next-line:no-console
console.log("render List")
const children: any[] = []
for (let i = 0; i < len; i++) {
children.push(<Item key={i} index={i} />)
}
return (<>{children}</>)
})
function App() {
return (
<Provider store={store}>
<List />
</Provider>
)
};
ReactDOM.render(<App />,
document.getElementById('root') as HTMLElement
);
用这个方式, List只会渲染一次, 然后Item也只有在 title或者checked发生变化的时候渲染一次, 从console里面可以看到,当点击input的时候, List没有render, ItemComp也只运行了1遍