React視角下的輪播圖


天貓購物網站最顯眼的就是輪播圖了。我在學習一樣新js庫,一個新框架或新的編程思想的時候,總是感嘆“入門必做選項卡,進階須擼輪播圖。”作為一個React組件,它是狀態操控行為的典型,拿來練手是個不錯的選擇。
為了復習,這次就嘗試用原生的javascript+React來完成。


輪播圖原生實現

所謂輪播圖其實是擴展版的選項卡。

先布局

主干架構

<div id="tabs">
        <ul id="btns">
            <li><a href="javascript:;"></a></li>
            <li><a href="javascript:;"></a></li>
            <li><a href="javascript:;"></a></li>
            <li><a href="javascript:;"></a></li>
            <li><a href="javascript:;"></a></li>
            <li><a href="javascript:;"></a></li>
        </ul>
        <ul id="imgs">
            <li><img src="images/banner1.jpg"></li>
            <li><img src="images/banner2.jpg"></li>
            <li><img src="images/banner3.jpg"></li>
            <li><img src="images/banner4.jpg"></li>
            <li><img src="images/banner5.jpg"></li>
            <li><img src="images/banner6.jpg"></li>
        </ul>
  </div>

樣式如下

/*css-reset*/
*{
  margin:0;
  padding: 0;
}
ul li{
  list-style: none;
}
img{
    border: none;
}
a{
  text-decoration: none;
}

/******************/
#tabs{
    width: 1130px;
    height: 500px;
    margin: 100px auto;
    position: relative;
    overflow: hidden;
}
#tabs li{
    float: left;
}
#tabs img{
    width: 1130px;
    height: 500px;
}
#btns{
    position: absolute;
    top:88%;
    left:395px;
    z-index: 9;
}
#btns a{
    display: block;
    width: 17px;
    height: 17px;
    background: rgba(0,0,0,0.3);
    border-radius: 50%;
    border: 2px solid rgba(0,0,0,0.3);
}
#btns li{
    margin: 10px;
}

大概效果

純javascript實現

事件

一個簡單的輪播圖包括多個事件。

  • 鼠標移入移出:當鼠標移出,或者是鼠標不在輪播圖上面,執行自動播放
  • 當鼠標移入:不再自動播放,而且點擊按鈕會執行跳轉到相應的頁面。

漸變

因為6張圖不是很多。所以考慮六張圖全部做絕對定位,按照順序疊加在一起。然再通過一個透明度的運動框架,實現之。
在此我選用這個運動框架:

function getStyle(obj,attr){
    if(obj.crrentStyle){
        return obj.currentStyle[attr];
        //兼容IE8以下
    }else{
        return getComputedStyle(obj,false)[attr];
        //參數false已廢。照用就好
    }
}

function startMove(obj,json,fn){
    //清理定時器
    if(obj.timer){
        clearInterval(obj.timer);
    }
    obj.timer=setInterval(function(){
        var bStop=false;//如果為false就停了定時器!
        var iCur=0;
        // 處理屬性值
        for(var attr in json){
            if(attr=='opacity'){
                iCur=parseInt(parseFloat(getStyle(obj,attr))*100);
            }else{
                iCur=parseInt(getStyle(obj,attr));
            }
            //定義速度值
            var iSpeed=(json[attr]-iCur)/8;
            iSpeed=iSpeed>0?Math.ceil(iSpeed):Math.floor(iSpeed);
            //檢測停止:如果我發現某個值不等於目標點bStop就不能為true。
            if(iCur!==json[attr]){
                bStop=false;
            }
            if(attr=='opacity'){
                obj.style[attr]=(iCur+iSpeed)/100;
                obj.style.filter='alpha(opacity:'+(iCur+iSpeed)+')';
            }else{
                obj.style[attr]=iCur+iSpeed+'px';
            }
        }
        //檢測是否停止,是的話關掉定時器
        if(bStop===true){
            if(iCur==json[attr]){
                clearInterval(obj.timer);
                if(fn){
                    fn();
                }
            }
        }
    },30);
}

這個框架可以指定樣式值進行漸變。

不得不說,這確實是一個很棒的運動框架。可以把它單獨放在為一個名為move.js的文件中再引入。

根據這個思路寫出原生的代碼:

window.onload=function(){
    var oTab=document.getElementById('tabs');
    var oBtns=document.getElementById('btns');
    var aBtns=document.getElementsByTagName('a');
    var oImgs=document.getElementById('imgs');
    var aImgsLi=oImgs.getElementsByTagName('li');
    var bCheck=true;
    var iNow=0;

    // 以下是初始化設置:
    aBtns[0].style.background='rgba(255,255,255,0.5)';
    aImgsLi[0].style.zIndex=6;


    function iNowlistener(){//改變的核心函數
        // 初始化
        for(var i=0;i<aBtns.length;i++){
            aBtns[i].style.background='rgba(0,0,0,0.3)';
        }
        aBtns[iNow].style.background='rgba(255,255,255,0.5)';
        for(var j=0;j<aBtns.length;j++){
            aImgsLi[j].style.opacity=0;
            if(j!==iNow){
                aImgsLi[j].style.display='none';
            }else{
                aImgsLi[j].style.display='block';
                startMove(aImgsLi[j],{'opacity':100});
            }
        }
    }


    var timer=null;
    timer=setInterval(function(){
        if(bCheck){
            if(iNow==5){//將最后一個變為0
                iNow=0;
            }else{
                iNow++;
            }
            iNowlistener();
        }else{
            return false;
        }
    },2000);


    oTab.onmouseover=function(){
        bCheck=false;
        for(var i=0;i<aBtns.length;i++){
            aBtns[i].index=i;
            aBtns[i].onmouseover=function(){
                if(this.index==iNow){
                    return false;
                }else{
                    iNow=this.index;
                    iNowlistener();
                }
            };
        }

    };

    oTab.onmouseout=function(){
        bCheck=true;
    };

};

效果如下:

不得不說,原生的代碼寫起來好長好長。

很長嗎?后面的更長。


React思路

以上原生代碼已經經過了初步的封裝——比如INowListener。但是在React的價值觀來說,顯然還需要進一步的封裝。甚至重新拆分。最理想的情況是:頂層組件作為主干架構和狀態機。下層組件接收狀態並運行方法。

多少個組件?

在這個輪播圖中,就三個組件。

- Tabs
   -imgs
   -btns
var Tabs=React.createClass({
            render:function(){

                return (
                    <div id="tabs">
                        <Btns/>
                        <Imgs/>
                    </div>
                );
            }
        });

        var Btns=React.createClass({
            render:function(){
                var arr=[];
                for(var i=0;i<6;i++){
                    var btnContent=
                      <li key={i.toString()}><a href="javascript:;"></a></li>
                    arr.push(btnContent);
                }
                return (
                    <ul id="btns">{arr}</ul>
                )
            }
        });

        var Imgs=React.createClass({
            render:function(){
                var arr=[];
                for(var i=0;i<6;i++){
                    var imgContent=
                      <li key={i.toString()}><img src={"images/banner"+(i+1)+".jpg"}/></li>
                    arr.push(imgContent);
                    console.log(arr)
                }
                return (
                    <ul id="imgs">{arr}</ul>
                );
            }
        });

        ReactDOM.render(
            <Tabs/>,
            document.getElementById('example')
        )

這樣寫就把樣式寫出來了。

哪個是狀態?

iNOW是狀態。而且是最重要的狀態!既然這樣,就考慮把狀態iNow放頂層。

鼠標懸停看起來也是狀態,但懸停按鈕上,觸發iNow改變——因此還是iNow。

鼠標移入移出事件,應該是狀態。但是這個移入移出的狀態依賴於iNow。所以不能單獨用。

需要哪些props?

構造組件時,為了靈活性,一般都不考慮把組件框架寫死。比如圖片張數,id名,等等都應該是props。但是這些暫時來說,都是次要的。

狀態肯定是一個核心props,此外,底層設置狀態的回調也是核心的props之一。

空談太多無意義,接下來嘗試實現!


自動按鈕

現在先不考慮其它,單看按鈕。
在插入文檔之后,開啟一個定時器,每隔2000ms執行一次狀態更新。

setState的寫法

那涉及到了iNow狀態根據前一個狀態更新,官方文檔不建議這種寫法:

this.setState({
    return {
        iNow:this.state.iNow+1
    }
})

因為狀態更新可能是異步的。這樣寫很容易出問題。
事實上,官網提供了這樣的寫法:

this.setState(function(prev,props){
    return {
        iNow:prev.iNow+1
    }
})

在這里只用第一個參數就夠了。

想當然的按鈕

定時器應該是一個狀態計算器。

所以按鈕可以這么寫:

var Btns=React.createClass({
            getInitialState:function(){
                return ({
                    iNow:0
                })
            },
            componentDidMount:function(){
                var _this=this;
                setInterval(function(){
                    _this.setState(function(prev){
                        //console.log(prev)
                        if(prev.iNow==5){
                            return {
                                iNow:0
                            };
                        }else{
                            return {
                                iNow:prev.iNow+1
                            };
                        }
                    })
                },2000);
            },
            render:function(){
                var arr=[];
                for(var i=0;i<6;i++){
                    var btnContent=null;
                    if(i==this.state.iNow){
                        btnContent=
                          <li key={i.toString()}><a style={{background:'rgba(255,255,255,0.5)'}} href="javascript:;"></a></li>
                    }else{
                        btnContent=
                          <li key={i.toString()}><a href="javascript:;"></a></li>
                    }

                    arr.push(btnContent);
                }
                
                return (
                    <ul id="btns">{arr}</ul>
                );
            }
        });

按鈕就實現了。
看起來不錯,但是這樣寫可能在未來造成極大的不便。

懸停交互

再強調一次價值觀這個概念,按照React的價值觀,狀態應該從頂層傳下去,況且在這個案例中,頂層Tabs組件做一件事就夠了:狀態機,在Btn組件插入到文檔之后,打開這個定時器。底層組件比如Btns根據狀態每隔2000ms通過props刷新變化。

同時,我還要實現一個簡單的交互功能:當鼠標懸停在Tabs上時,不再允許iNow自動更新。——可以做一個bCheck開關,當Tabs組件鼠標移入/移出時,觸發bCheck的來回變化。

此處可能有個小問題,就是鼠標一道按鈕組上時,會造成bCheck抖動。但是最后又變回false。所以認為不影響。

很自然想到,bCheck為false時,關閉定時器。但是這樣做又等於浪費了定時器的功能,回調方法中一旦關掉定時器,再重新定時器就不是一般的麻煩了,為什么不直接在定時器做判斷呢?所以我認為不應該讓定時器停下來。只需要改變定時器計算iNow的行為就行了。

var Tabs=React.createClass({
            getInitialState:function(){
                return {
                    iNow:0,
                    bCheck:true//為false時不允許定時器計算更新iNow
                }
            },
            setInow:function(){
            var _this=this;
            var timer=setInterval(function(){
                  if(_this.state.bCheck){
                      //console.log(_this.state.bCheck)
                      _this.setState(function(prev){
                          if(prev.iNow==5){
                              return {
                                  iNow:0
                              };
                          }else{
                              return {
                                  iNow:prev.iNow+1
                              };
                          }
                      });
                  }else{
                      console.log('該停了!')
                      return false;
                  }

              },2000);

          },
            checkSwitch:function(){
                this.setState(function(prev){
                    return {
                        bCheck:!prev.bCheck,
                    }
                })
            },
            render:function(){
                return (
                    <div id="tabs" onMouseOver={this.checkSwitch} onMouseOut={this.checkSwitch}>
                        <Btns iNow={this.state.iNow} setInow={this.setInow}/>
                        <Imgs/>
                    </div>
                );
            }
        });

        var Btns=React.createClass({
            componentDidMount:function(){
                this.props.setInow();//插入后就執行回調方法
            },
            render:function(){
                var arr=[];
                for(var i=0;i<6;i++){
                    var btnContent=null;
                    if(i==this.props.iNow){
                        btnContent=
                          <li key={i.toString()}>
                          <a style={{background:'rgba(255,255,255,0.5)'}} href="javascript:;"></a>
                          </li>
                    }else{
                        btnContent=
                          <li key={i.toString()}><a href="javascript:;"></a></li>
                    }

                    arr.push(btnContent);
                }

                return (
                    <ul id="btns">{arr}</ul>
                );
            }
        });

圖片動畫

一件事三個步驟

圖片組件雖說只是做一件事情(根據iNow渲染效果),但是也得分三步來做。

  • 首先,渲染前應該保證索引值非iNow的所有圖片display為none。索引值為iNow的圖片透明度為0。(初始化)

  • 其次,在首次插入文檔完畢之后(componentDidMount),對第0張圖執行startMove函數。

  • 第三,需要一個監聽頂層iNow的方法。定時器已經給Btns組件用了,再用就會出錯。

    留意到Imgs組件實際上只接受一個會變化的props那就是iNow。因此采用componentWillReceiveProps

生命周期方法

componentWillReceiveProps

組件接收到新的props時調用,並將其作為參數nextProps使用,此時可以更改組件propsstate

    componentWillReceiveProps: function(nextProps) {
        if (nextProps.bool) {
            this.setState({
                bool: true
            });
        }
    }

這里采用的兩個組件周期方法都是組件真實存在時的方法。所以可以直接使用真實的DOM命令。

實現

var Tabs=React.createClass({
        getInitialState:function(){
            return {
                iNow:0,
                bCheck:true
            };
        },
        setInow:function(){
            var _this=this;
            var timer=setInterval(function(){
                if(_this.state.bCheck){
                    //console.log(_this.state.bCheck)
                    _this.setState(function(prev){
                        if(prev.iNow==5){
                            return {
                                iNow:0
                            };
                        }else{
                            return {
                                iNow:prev.iNow+1
                            };
                        }
                    });
                }else{
                    console.log('該停了!')
                    return false;
                }

            },2000);

        },
        checkSwitch:function(){
            console.log(this.state.bCheck)
            this.setState(function(prev){
                return {
                    bCheck:!prev.bCheck
                };
            });
        },
        render:function(){
            return (
                <div id="tabs"
                  onMouseOver={this.checkSwitch}
                  onMouseOut={this.checkSwitch}>
                    <Btns iNow={this.state.iNow}
                      setInow={this.setInow} />
                    <Imgs iNow={this.state.iNow}/>
                </div>
            );
        }
    });

    var Btns=React.createClass({
        componentDidMount:function(){
            this.props.setInow();
        },

        render:function(){
            var arr=[];
            for(var i=0;i<6;i++){
                var btnsContent=null;
                if(i==this.props.iNow){
                    btnsContent=
                        <li key={i.toString()}>
                            <a style={{background:'rgba(255,255,255,0.5)'}} href="javascript:;"></a>
                        </li>
                }else{
                    btnsContent=
                        <li key={i.toString()}>
                            <a href="javascript:;"></a>
                        </li>
                }
                arr.push(btnsContent);
            }

            return (
                <ul id="btns">{arr}</ul>
            );
        }
    });

    var Imgs=React.createClass({
        componentDidMount:function(){//剛開始加載時,就執行動畫函數
            var iNow=this.props.iNow;
            var obj=document.getElementById('imgs').getElementsByTagName('li')[iNow].childNodes[0];
            startMove(obj,{'opacity':100});
        },
        componentWillReceiveProps:function(nextProps){
            var obj=document.getElementById('imgs').getElementsByTagName('li')[nextProps.iNow].childNodes[0];
            //console.log(obj)
            startMove(obj,{'opacity':100});
        },
        // this.startMove:startMove(),
        render:function(){
            var arr=[];
            for(var i=0;i<6;i++){
                var imgsContent=null
                if(i==this.props.iNow){
                    imgsContent=
                        <li key={i.toString()}>
                            <img style={{opacity:'0'}} src={'images/banner'+(i+1)+'.jpg'} />
                        </li>
                    arr.push(imgsContent);
                }else{
                    imgsContent=
                        <li key={i.toString()}>
                            <img style={{display:'none'}} src={'images/banner'+(i+1)+'.jpg'} />
                        </li>
                    arr.push(imgsContent);
                }

            }

            return (
                <ul id="imgs">{arr}</ul>
            )
        }
    })

    ReactDOM.render(
        <Tabs/>,
        document.getElementById('example')
    );

看起來Imgs組件已經很完備了。——就它的功能來說已經沒有什么需要添加了。


鼠標懸停改變iNow

這個事件只能在底層組件Btns上實現。所以要拿到懸停的索引值。

然后通過回調,把該按鈕的索引值設置為整個組件Tabs的狀態iNow。

為了干這兩件事,還是用一個changeInow(e)函數來包裝它們。

給誰綁定?加什么事件?

為了忠實原來的代碼。我給a標簽加onMouseOver事件。

加了事件直接,秉承這React的核心價值觀(一個組件只干一件事),我把get到的index值通過this.props.setInow傳遞回去。只要頂層的iNow變了,下面的組件不管什么狀態,都會乖乖聽話了。

如何獲取當前懸停的索引值?

在Jquery很容易使用index方法來獲取索引值。但是在原生方法中,還得費一番周章。

給所有a綁定一個onMouseOver事件,假設該事件方法的參數為e,那么e.target就是該參數的方法。

這需要寫一個getIndex方法

...
getIndex:function(e){
  var list=e.target.parentNode.parentNode.childNodes;
  for(var i=0;i<list.length;i++){
    if(list[i]===e.target.parentNode){
      return  i;
    }
  }
},
...

拿到索引值之后

——就把它設置為頂層的iNow。

既然決定通過this.props.setInow回調,那么還得傳一個索引值參數,回到頂層稍微修改下方法,就實現了。

全部代碼:

var Tabs=React.createClass({//頂層組件
        getInitialState:function(){
            return {
                iNow:0,
                bCheck:true
            };
        },
        setInow:function(index){//核心狀態計算工具:依賴定時器進行實時刷新
            if(index!==undefined){//如果參數有內容。
                this.setState({
                    iNow:index
                });
            }else{
                var _this=this;
                this.timer=setInterval(function(){
                    if(_this.state.bCheck){
                        //console.log(_this.state.bCheck)
                        _this.setState(function(prev){
                            if(prev.iNow==5){
                                return {
                                    iNow:0
                                };
                            }else{
                                return {
                                    iNow:prev.iNow+1
                                };
                            }
                        });
                    }else{
                        //console.log('該停了!')
                        return false;
                    }
                },2000);
            }
        },
        checkSwitch:function(){
            //console.log(this.state.bCheck)
            this.setState(function(prev){
                return {
                    bCheck:!prev.bCheck
                };
            });
        },
        render:function(){
            return (
                <div id="tabs"
                  onMouseOver={this.checkSwitch}
                  onMouseOut={this.checkSwitch}>
                    <Btns iNow={this.state.iNow}
                      setInow={this.setInow} />
                    <Imgs iNow={this.state.iNow}/>
                </div>
            );
        }
    });

    var Btns=React.createClass({
        componentDidMount:function(){
            this.props.setInow();
        },
        getIndex:function(e){//獲取a的父級索引值
            var list=e.target.parentNode.parentNode.childNodes;
            for(var i=0;i<list.length;i++){
                if(list[i]===e.target.parentNode){
                    return i;
                }
            }
        },
        changeInow:function(e){//回調方法
            //console.log($(e.target).parent().index());
            //console.log(this.getIndex(e));
            var index=this.getIndex(e);
            this.props.setInow(index)
        },

        render:function(){
            var arr=[];
            for(var i=0;i<6;i++){
                var btnsContent=null;
                var index=i;
                if(i==this.props.iNow){
                    btnsContent=
                        <li key={i.toString()}>
                            <a onMouseOver={this.changeInow} style={{background:'rgba(255,255,255,0.5)'}} href="javascript:;"></a>
                        </li>
                }else{
                    btnsContent=
                        <li key={i.toString()}>
                            <a  onMouseOver={this.changeInow} href="javascript:;"></a>
                        </li>
                }
                arr.push(btnsContent);
            }

            return (
                <ul id="btns">{arr}</ul>
            );
        }
    });

    var Imgs=React.createClass({
        componentDidMount:function(){//剛開始加載時,就執行動畫函數
            var iNow=this.props.iNow;
            var obj=document.getElementById('imgs').getElementsByTagName('li')[iNow].childNodes[0];
            startMove(obj,{'opacity':100});
        },
        componentWillReceiveProps:function(nextProps){
            var obj=document.getElementById('imgs').getElementsByTagName('li')[nextProps.iNow].childNodes[0];
            //console.log(obj)
            startMove(obj,{'opacity':100});
        },
        // this.startMove:startMove(),
        render:function(){
            var arr=[];
            for(var i=0;i<6;i++){
                var imgsContent=null
                if(i==this.props.iNow){
                    imgsContent=
                        <li key={i.toString()}>
                            <img style={{opacity:'0'}} src={'images/banner'+(i+1)+'.jpg'} />
                        </li>
                    arr.push(imgsContent);
                }else{
                    imgsContent=
                        <li key={i.toString()}>
                            <img style={{display:'none'}} src={'images/banner'+(i+1)+'.jpg'} />
                        </li>
                    arr.push(imgsContent);
                }

            }

            return (
                <ul id="imgs">{arr}</ul>
            )
        }
    })

    ReactDOM.render(
        <Tabs/>,
        document.getElementById('example')
    );

完善

我們要讓這個組件可復用,換言之就是把之前寫死的東西比如圖片數量,樣式,id名都變成Tabs的props屬性。

這下工作量夠了吧。原來50多行的東西改寫完之后大概150多行。

var Tabs=React.createClass({//頂層組件
        getInitialState:function(){
            return {
                iNow:0,
                bCheck:true
            };
        },
        setInow:function(index){//核心狀態計算工具:依賴定時器進行實時刷新
            if(index!==undefined){//如果參數有內容。
                this.setState({
                    iNow:index
                });
            }else{
                var _this=this;
                this.timer=setInterval(function(){
                    if(_this.state.bCheck){
                        //console.log(_this.state.bCheck)
                        _this.setState(function(prev){
                            if(prev.iNow==this.props.nums-1){
                                return {
                                    iNow:0
                                };
                            }else{
                                return {
                                    iNow:prev.iNow+1
                                };
                            }
                        });
                    }else{
                        //console.log('該停了!')
                        return false;
                    }
                },this.props.timer);
            }
        },
        checkSwitch:function(){
            //console.log(this.state.bCheck)
            this.setState(function(prev){
                return {
                    bCheck:!prev.bCheck
                };
            });
        },
        render:function(){
            return (
                <div id={this.props.idNames.main}
                  onMouseOver={this.checkSwitch}
                  onMouseOut={this.checkSwitch}>

                    <Btns iNow={this.state.iNow}
                      setInow={this.setInow}
                      nums={this.props.nums}
                      idNames={this.props.idNames} />

                    <Imgs iNow={this.state.iNow}
                    nums={this.props.nums}
                    idNames={this.props.idNames}
                    imgType={this.props.imgType} />

                </div>
            );
        }
    });

    var Btns=React.createClass({
        componentDidMount:function(){
            this.props.setInow();
        },
        getIndex:function(e){//獲取a的父級索引值
            var list=e.target.parentNode.parentNode.childNodes;
            for(var i=0;i<list.length;i++){
                if(list[i]===e.target.parentNode){
                    return i;
                }
            }
        },
        changeInow:function(e){//回調方法
            //console.log($(e.target).parent().index());
            //console.log(this.getIndex(e));
            var index=this.getIndex(e);
            this.props.setInow(index)
        },

        render:function(){
            var arr=[];
            for(var i=0;i<this.props.nums;i++){
                var btnsContent=null;
                var index=i;
                if(i==this.props.iNow){
                    btnsContent=
                        <li key={i.toString()}>
                            <a onMouseOver={this.changeInow} id={this.props.idNames.active} href="javascript:;"></a>
                        </li>
                }else{
                    btnsContent=
                        <li key={i.toString()}>
                            <a  onMouseOver={this.changeInow} href="javascript:;"></a>
                        </li>
                }
                arr.push(btnsContent);
            }

            return (
                <ul id={this.props.idNames.btns}>{arr}</ul>
            );
        }
    });

    var Imgs=React.createClass({
        componentDidMount:function(){//剛開始加載時,就執行動畫函數
            var iNow=this.props.iNow;
            var obj=document.getElementById(this.props.idNames.imgs).getElementsByTagName('li')[iNow].childNodes[0];
            startMove(obj,{'opacity':100});
        },
        componentWillReceiveProps:function(nextProps){//每當收到新的props就執行動畫
            var obj=document.getElementById(this.props.idNames.imgs).getElementsByTagName('li')[nextProps.iNow].childNodes[0];
            //console.log(obj)
            startMove(obj,{'opacity':100});
        },

        render:function(){
            var arr=[];
            for(var i=0;i<this.props.nums;i++){
                var imgsContent=null;
                var src=this.props.imgType.url+this.props.imgType.name+(i+1)+'.'+this.props.imgType.type;
                if(i==this.props.iNow){
                    imgsContent=
                        <li key={i.toString()}>
                            <img style={{opacity:'0'}} src={src} />
                        </li>
                    arr.push(imgsContent);
                }else{
                    imgsContent=
                        <li key={i.toString()}>
                            <img style={{display:'none'}} src={src} />
                        </li>
                    arr.push(imgsContent);
                }
            }

            return (
                <ul id={this.props.idNames.imgs}>{arr}</ul>
            )
        }
    })

    ReactDOM.render(
        <Tabs
          nums={6}
          timer={2000}
          idNames={
              {
                  main:"tabs",
                  btns:"btns",
                  imgs:"imgs",
                  active:"btn-active"
              }
          }
          imgType={
              {
                  type:"jpg",
                  url:"images/",
                  name:"banner"
              }
          }
           />,
        document.getElementById('example')
    );

其中多設置了一個#btn-active樣式。

#btn-active{
    background:rgba(255,255,255,0.5)!important;
}

是不是好長好長呢?

demo地址:

http://djtao.top/tabs/

但是這個確實是一個可復用的,而且還是原生js寫成的組件。

不得不說,作為一個初學幾天的人,寫這東西時的時候遭遇好多的坑。但是最后“驀然回首,那人卻在燈火闌珊處”,也有種人生三境界的感悟了!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM