一、效果
或者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: '', srcs: [], layer_style: { display: "none" }, navbar_style: [] }; }, componentDidMount: function() {}, initNavbar: function() {}, restoreNavbar: function() {}, switchPic: function(num, e) {}, handlerClick: function(e) {}, render: function() { var temp = []; var pics = this.state.srcs; for (var i = 0; i < pics.length; i++) { 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(); this.setState({ src: '' }); }
|
2. handlerClick
1 2 3 4 5 6 7 8 9 10
| switchPic: function(num, e) { this.restoreNavbar(); this.state.navbar_style[num] = { background: "#3f3" }; this.setState({ src: this.state.srcs[num] }); e.stopPropagation(); }
|
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前面。此外我还试过用箭头函数传参,发现不好使。