最大值 以及 分割数 计算
1 | // echarts 支持callback函数 |
1 | // echarts 支持callback函数 |
1 | const { fileList } = this.state; // 取得文件列表 |
div
最外侧 负责 1️⃣鼠标 交互,2️⃣超出隐藏div
负责整体动画,通过marginTop
属性实现动画效果1 | <div |
在请求数据的回调函数 中 设置state, 利用回调 执行 动画方法1
2
3
4
5
6
7
8
9
10getOnDutyListData() {
axios({
method: 'GET',
url: `/OnDutyList`,
}).then(res => {
this.setState({
dutyList: res.data.result
}, () => this.animationInterval()) // 在这里,利用 回调 执行 动画方法。可以避免 在其他 周期里面获取不到 异步数据的情况
})
}
1 | animationInterval() { |
操作重点
shift()
, 2️⃣push(dutyList[0])
setState
鼠标移入移出/ 组件卸载
清除定时器1 | removeAnimationInterval() { |
CarouselList.js1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79export default class CarouselList extends Component {
constructor(props) {
super(props);
this.state = {
data: this.props.data,
scrollData: 0
};
}
componentDidMount = () => {
this.addHandleTimer();
};
componentWillUnmount = () => {
this.removeHandleTimer();
}
//timers
addHandleTimer = () => {
let { data, scrollData } = this.state;
if (!data || !data.length) return null;
// 定时器
this.timer = setInterval(() => {
if (scrollData > -27) {
scrollData--;
this.setState({
scrollData: scrollData
})
} else {
scrollData = 0;
let firstData = data[0];
data.shift();
data.push(firstData);
}
}, 70);
}
removeHandleTimer = () => {
this.timer && clearInterval(this.timer);
}
handleScroll = e => {
const ev = e || window.event;
e.preventDefault();
const conDom = this.refs["content"];
const speed = 5; // scroll speed
if (ev.deltaY > 0) {
conDom.scrollTop += speed;
} else {
conDom.scrollTop -= speed;
}
};
render() {
const { data, scrollData } = this.state;
return (
<div
ref="content"
onMouseEnter={this.removeHandleTimer}
onMouseLeave={this.addHandleTimer}
onWheel={this.handleScroll}
>
<ul style={{ marginTop: scrollData + "px" }}>
{
data.length > 0 && data.map((item, index) => {
return (
this.props.type === 'simple' ?
<li key={index}><p title={item.value}>{item.value}</p></li>
: <li key={index}><span>{item.id}</span><p title={item.intelligence}>{item.intelligence}</p></li>
)
// 默认:complex
{/*<li key={index}><span>{item.id}</span><p title={item.intelligence}>{item.intelligence}</p></li>*/ }
}
)
}
</ul>
</div>
);
}
}
CarouselList2.js1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95export default class CarouselList2 extends Component {
constructor(props) {
super(props);
console.log('是大法官',this.props.data)
this.state = {
data: this.props.data,
scrollData: 0
};
}
componentDidMount = () => {
this.addHandleTimer();
};
componentWillUnmount = () => {
this.removeHandleTimer();
};
//timers
addHandleTimer = () => {
let {data, scrollData} = this.state;
if (!data || !data.length) return null;
if(data.length < 5 ) return false;
this.timer = setInterval(() => {
if (scrollData > -52) {
scrollData--;
this.setState({
scrollData: scrollData
})
} else {
scrollData = 0;
let firstData = data[0];
data.shift();
data.push(firstData);
let firstData1 = data[0];
data.shift();
data.push(firstData1);
}
}, 70);
}
removeHandleTimer = () => {
this.timer && clearInterval(this.timer);
}
handleScroll = e => {
const ev = e || window.event;
e.preventDefault();
const conDom = this.refs["content"];
const speed = 6; // scroll speed
if (ev.deltaY > 0) {
conDom.scrollTop += speed;
} else {
conDom.scrollTop -= speed;
}
};
render() {
const {data, scrollData} = this.state;
return (
<div
ref="content"
onMouseEnter={this.removeHandleTimer}
onMouseLeave={this.addHandleTimer}
onWheel={this.handleScroll}
>
<ul style={{marginTop: scrollData + "px"}}>
{
data.length > 0 && data.map((item, index) => {
return (
this.props.type === 'superior' ?
<li key={item.id}>
<p title={item.name}>{item.name}</p>
<p title={item.card}>{item.card}</p>
<p title={item.show}>{item.show}</p>
<p title={item.feedback}>{item.feedback}</p>
<p title={item.state}>{item.state}</p>
</li>
: <li key={item.id}>
<p title={item.name}>{item.name}</p>
<p title={item.card}>{item.card}</p>
<p title={item.time}>{item.time}</p>
<p title={item.origin}>{item.origin}</p>
<p title={item.destination}>{item.destination}</p>
</li>
)
}
)
}
</ul>
</div>
);
}
}
InformationOnDuty.js1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128import "./InformationOnDuty.scss"
import { hidden } from "ansi-colors";
class InformationOnDuty extends Component {
constructor(props) {
super(props);
this.state = {
dutyList: [],
scrollData: 0,
inital: true
};
this.getOnDutyListData = this.getOnDutyListData.bind(this);
this.animationInterval = this.animationInterval.bind(this);
this.removeAnimationInterval = this.removeAnimationInterval.bind(this);
this.getOnDutyListData();
}
getOnDutyListData() {
axios({
method: 'GET',
url: `/OnDutyList`,
}).then(res => {
this.setState({
dutyList: res.data.result
}, () => this.animationInterval())
})
}
animationInterval() {
let { scrollData, dutyList } = this.state;
if (!dutyList.length) return;
this.state.animationInterval = setInterval(() => {
this.setState({
scrollData: scrollData--
});
let firstItem = dutyList[1];
if (scrollData < 0 && scrollData > -2) {
if (this.state.inital) {
dutyList.push(dutyList[0]);
this.setState({
inital: false
})
}
}
// dutyList.push(firstItem);
if (scrollData % 128 === 0) {
// debugger
dutyList.shift();
dutyList.push(firstItem);
scrollData = 0;
// debugger
}
// if (scrollData > -113) {
// let firstItem = dutyList[0];
// // dutyList.shift();
// // dutyList.push(firstItem);
// this.setState({
// scrollData: scrollData--
// })
// } else {
// scrollData = 0;
// let firstItem = dutyList[0];
// dutyList.shift();
// dutyList.push(firstItem);
// }
}, 60)
}
removeAnimationInterval() {
this.state.animationInterval && clearInterval(this.state.animationInterval);
}
componentDidMount() {
}
componentWillReceiveProps() {
debugger
}
componenWillUnmount() {
this.removeAnimationInterval();
}
render() {
let { dutyList, scrollData } = this.state;
return (
<div className="InformationOnDuty">
<div className="title">
<div className="tit1"><span>值班信息</span></div>
<div className="tit2"><span>查看值班表</span></div>
</div>
<div
className="contetn"
ref="content"
onMouseEnter={this.removeAnimationInterval}
onMouseLeave={this.animationInterval}
style={{overflow: "hidden"}}
// onWheel={}
>
<div style={{ marginTop: scrollData + "px" }}>
{
dutyList.map((item, index) => {
return (
<div className="card" key={`${item.title}:${item.name}${index}`}>
<div className="row1">
<span>{item.title} </span><b> | </b><span>{item.name}</span>
</div>
<div className="row2">
<span className={item.title.length > 3 ? 'nbsp4' : 'nbsp3'}>电话 </span><b> | </b><span>{item.phone}</span>
</div>
</div>
)
})
}
</div>
</div>
</div>
)
}
}
export default InformationOnDuty;
关键词:diff算法
唯一标识
当React作diff
时,只要子元素有key
属性,便会去原v-dom
树中相应位置(当前横向比较的层级
)寻找是否有同key元素
,比较它们是否完全相同
,若是则复用
该元素,免去不必要的操作。
key必须是字符串
类型,它的取值可以用数据对象的某个唯一属性,或是对数据进行hash
来生成key。
强烈 不推荐 用数组index来作为key。如果数据更新仅仅是数组重新排序或在其中间位置插入新元素,那么视图元素都将重新渲染。来看下例子:
1 | <ul>{list.map((v,idx)=><li key={idx}>{v}</li>)}</ul> |
React发现key为0,1,2的元素的text都变了,将会修改
三者的html,而不是移动
它们。
1 | {this.state.type ? |
如上述代码,每次按下按钮,原 Son_1与Son_2 组件的实例都将被销毁
,并创建新的Son_1与Son_2实例
,不能继承原来的状态
;而它们实际上只是调换了位置。给它们加上key可避免
问题:
1 | {this.state.type ? |
结论:
id
作为key
比使用 index
作为 key
性能更好分析补充:\
使用 index 作为 key 某些情况下影响性能。\
举个例子:
一个数组[a,b],渲染成两个不同类型的节点,key用index。然后数组变成[b,a],\
再次渲染时,react先判断变化前后同key的虚拟节点
是否相等,发现节点类型就不同,接下来的操作就是新建两个dom节点去替换原来的节点。这种情况下key等于没用。而如果用唯一id,react会知道同key节点没有变化,只是换了位置,只要打个移动节点的patch到dom上,而不是新建替换。
另外修改节点可能修改量无限大啊