第三个React组件-遮罩层显示图片


pic

一、效果

或者jsbin地址

二、HTML结构

1
2
3
4
5
6
7
<div class="small_img">
<img class="pic4layer" src="" alt="" />
<img class="pic4layer" src="" alt="" />
<img class="pic4layer" src="" alt="" />
<img class="pic4layer" src="" alt="" />
</div>
<div id="layer"></div>
  • 含有pic4layer类名的图片会在点击时再遮罩层显示;
  • id为layer的区域用来容纳遮罩层;

三、React类结构

1
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
var ImgLayer = React.createClass({
getInitialState: function() {
return {
src: '', //表示遮罩层图片的src
srcs: [], //存放所有pic4layer图片的地址
layer_style: { //此样式用于控制显示/隐藏切换
display: "none"
},
navbar_style: [] //导航条的样式
};
},
componentDidMount: function() {}, //装载完毕,执行某些初始化操作
initNavbar: function() {}, //初始化navbar样式
restoreNavbar: function() {}, //恢复navbar样式
switchPic: function(num, e) {}, //切换图片
handlerClick: function(e) {}, //处理点击事件:隐藏遮罩层
render: function() {
var temp = [];
var pics = this.state.srcs;
for (var i = 0; i < pics.length; i++) { //使用bind来传递参数
temp.push(<div key={i} ref={"item"+i} style={this.state.navbar_style[i]} onClick={this.switchPic.bind(null,i)}></div>);
}
return (
<div id="img_layer" style={this.state.layer_style} onClick={this.handlerClick}>
<img src={this.state.src} alt="pic" />
<div id="navbar">
{temp}
</div>
</div>
);
}
});

ReactDOM.render(<ImgLayer></ImgLayer>, document.getElementById("layer"));

四、关键函数

1. handlerClick

1
2
3
4
5
6
7
handlerClick: function(e) {
this.state.layer_style["display"] = "none"; //隐藏遮罩层
this.restoreNavbar(); //恢复navbar的颜色为红色(绿色表示当前序列)
this.setState({
src: ''
});
}

2. handlerClick

1
2
3
4
5
6
7
8
9
10
switchPic: function(num, e) {
this.restoreNavbar(); //恢复navbar
this.state.navbar_style[num] = {
background: "#3f3" //根据点击navbar_item时传递过来的参数重新设置当前图片的src
};
this.setState({
src: this.state.srcs[num]
});
e.stopPropagation(); //停止冒泡(冒泡会触发上层的click事件)
}

3. componentDidMount

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
componentDidMount: function() {
this.initNavbar();
this.setState();
document.addEventListener("click", function(e) {
if (e.target.className === "pic4layer") {
var src = e.target.src;
var num = this.state.srcs.indexOf(src);
this.state.navbar_style[num] = {
background: "#3f3"
};
this.state.layer_style["display"] = "block";
this.setState({
src: src
});
}
}.bind(this));
}

感觉把初始化的逻辑放在这里是不对的,React会有警告:

Warning: setState(…): You passed an undefined or null state object; instead, use forceUpdate().

初始化操作应该尽量放在getInitialState中,因为在装载完成之前就会使用state,使用时如果是空的就会报错。

于是稍微改造一下initNavbar函数,把逻辑移到getInitialState中,警告消失了,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
getInitialState: function() {
document.addEventListener("click", function(e) {
if (e.target.className === "pic4layer") {
var src = e.target.src;
var num = this.state.srcs.indexOf(src);
this.state.navbar_style[num] = {
background: "#3f3"
};
this.state.layer_style["display"] = "block";
this.setState({
src: src
});
}
}.bind(this));

var tmp = this.initNavbar();
return {
src: '',
srcs: tmp.srcs,
layer_style: {
display: "none"
},
navbar_style: tmp.navbar_style
};
}

五、总结

在React中使用bind函数传递参数时要注意,传递的参数会出现在接收函数的arguments前面。此外我还试过用箭头函数传参,发现不好使。