zoukankan      html  css  js  c++  java
  • 【原】react做tab切换的几种方式

    最近搞一个pc端的活动,搞了一个多月,甚烦,因为相比于pc端,更喜欢移动端多一点。因为移动端又能搞我的react了.

      今天主要总结一下react当中tab切换的几种方式,因为tab切换基本上都会用到。当然,你也可以在react当中用jquery或者zepto来实现,不过既然都用react了,能不能用jq,就尽量不用jq。不过不得不吐槽一下,在jquery很简单的东西,在react中稍微复杂化了一点。

    目前我用到的tab切换只有两种方式,所以暂时总结这两种,以后有遇到其他的再总结。

    第一种、只是子标签在换,内容的布局不换。类似于下面这种

    这类的切换只需要点击上面的标签,发送不同的请求而已,下面内容的布局都是一样的。

    第二种就是标签页和内容都需要切换的,也是比较常见的这种。如下

    Talk is cheap. Show me the code     (觉得比较有意思的翻译是:废话少说,放码过来)

    第一种,只是tab标签切换的方式

    import React from 'react';
    
    class NewsList extends React.Component {
    
        constructor(props) {
            super(props);
            this.state = {
                tabs:[
                    {tabName:"热点新闻",id:1},
                    {tabName:"合作播报",id:2},
                    {tabName:"行业咨询",id:3},
                    {tabName:"运营攻略",id:4}
                ],
                currentIndex:1,
            };
        }    
        componentDidMount() {
            
        }
        tabChoiced=(id)=>{
            // tab切换的方法
            this.setState({
                currentIndex:id
            });
        }
        render(){
            var _this=this;
              var tabList= this.state.tabs.map(function(res,index) {
                  // 遍历标签页,如果标签的id等于tabid,那么该标签就加多一个active的className
                var tabStyle=res.id==this.state.currentIndex ? 'subCtrl active' : 'subCtrl';
    
                return    <li key={index} onClick={this.tabChoiced.bind(_this,res.id)} className={tabStyle}>{res.tabName}</li>
    
            }.bind(_this));
            return (
                <div className="listWrap">
                    <ul className="subNavWrap">
                        {tabList}
                    </ul>
                    <div className="newsList">
                        {/**这里通用的新闻列表**/}
                    </div>
                </div>
            )
        }
    }
    
    export default NewsList;

        首先我们初始化已给tab标签的数组,并给数组里面的每一项加个id,然后设置一个当前显示第几个的currendIndex.然后将标签遍历出来,如果该标签的id等于currendIndex,那么就加多一个active的className,否则没有。从而实现点击标签,显示高亮的状态

      每次点击新的标签,都会将该标签对应的id传过去,从而让currendIndex等于被点击的标签的id。比如点击了id为2的标签,这样下次遍历的时候currendIndex也等于2了,从而让第二个处于高亮,从而实现tab的切换。

    第二种,内容随着标签一起切换

    这个也是比较常见的。暂时我这里有两种方法实现。

    方法1:在前面只是标签切换形式上改进一下:

    import React from 'react';
    
    class NewsList extends React.Component {
    
        constructor(props) {
            super(props);
            this.state = {
                tabs:[
                    {tabName:"社会新闻",id:1},
                    {tabName:"体育世界",id:2},
                    {tabName:"娱乐圈",id:3},
                ],
                currentIndex:1,
            };
        }    
        componentDidMount() {
            
        }
        tabChoiced=(id)=>{
            //tab切换到方法
            this.setState({
                currentIndex:id
            });
        }
        render(){
            var _this=this;
            var isBox1Show=this.state.currentIndex==1 ? 'block' : 'none';
            var isbox2Show=this.state.currentIndex==2 ? 'block' : 'none';
            var isbox3Show=this.state.currentIndex==3 ? 'block' : 'none';
    
              var tabList= this.state.tabs.map(function(res,index) {
                  // 遍历标签页,如果标签的id等于tabid,那么该标签就加多一个active的className
                var tabStyle=res.id==this.state.currentIndex ? 'subCtrl active' : 'subCtrl';
    
                return    <li key={index} onClick={this.tabChoiced.bind(_this,res.id)} className={tabStyle}>{res.tabName}</li>
    
            }.bind(_this));
            return (
                <div className="listWrap">
                    <ul className="subNavWrap">
                        {tabList}
                    </ul>
                    <div className="newsList">
                        <div style={{"display":isBox1Show}} >
                            社会新闻
                        </div>
                        <div style={{"display":isBox2Show}}>
                            体育世界
                        </div>
                        <div style={{"display":isBox3Show}}>
                            娱乐圈
                        </div>
                    </div>
                </div>
            )
        }
    }
    
    export default NewsList;

     虽然这种方法比较傻瓜式,不过很方便。在第一个代码的的基础上稍加改进。判断当前的currenIndex等于几,如果是1,那么内容页的第一个的display就设为block, 其他内容页的display为noe。以此类推。哈哈,确实有点点傻瓜式。管它呢,好用就好。

    方法2:做成一个组件的形式,也可以说是写一个小小的插件

    还是废话少说,放码过来

    var React=require("react");
    var ReactDOM=require("react-dom");
    
    class TabsControl extends React.Component{
    
        constructor(){
            super();
            this.state={ 
                currentIndex : 0
            };
        }
    
        check_tittle_index(index){
            return index===this.state.currentIndex ? "Tab_tittle active" : "Tab_tittle";
        }
    
        check_item_index(index){
            return index===this.state.currentIndex ? "Tab_item show" : "Tab_item";
        }
    
        render(){
            let _this=this;
            return(
                <div>
                    {/*动态生成Tab导航*/}
                    <div className="Tab_tittle_wrap">
                        { React.Children.map( this.props.children , (element,index) => {
                            return(
                                /*箭头函数没有自己的this,这里的this继承自外围作用域,即组件本身*/
                                <div onClick={ () => { this.setState({currentIndex : index}) } } className={ this.check_tittle_index(index) }>{ element.props.name }</div>
                                );
                        }) }
                    </div>
                    {/*Tab内容区域*/}
                    <div className="Tab_item_wrap">
                        {React.Children.map(this.props.children,(element,index)=>{
                            return(
                                <div className={ this.check_item_index(index) }>{ element }</div>
                                );
                        })}
                    </div>
                </div>
                );
        }
    }
    
    class TabComponent extends React.Component{
    
        render(){
            return(
                <div className="container">
                    <TabsControl>
                        <div name="社会新闻">
                            社会新闻的内容
                        </div>
                        <div name="体育世界">
                            体育世界的内容
                        </div>
                        <div name="娱乐圈">
                            娱乐圈的内容
                        </div>
                    </TabsControl>
                </div>
                );
        }
    }
    
    ReactDOM.render(<TabComponent/>,document.getElementById("app"));

        这个稍微复杂一点,稍加解释,不过如果你看懂了前面两个的例子,很很好懂。

     首先我们定义了一个子组件叫TabsControl ,然后我们遍历它的子标签。子标签的内容从哪里来呢,是在该组件里面的name值那里获取。

      this.props.children 是React内建的一个属性,用来获取组件的子元素。因为子元素有可能是Object或者Array,

    所以React提供了一些处理children的辅助方法用来遍历:React.Children.map。

      比如上面这段代码中,this.props.children获取了里面三个divd数组,但是假如你只要一个div呢,那么获取的就是对象。所以需要

    React.Children.map()来配合进行遍历。

      通过上面的这段代码,我们就很方便的进行遍历了。比如一个页面需要有多个tab切换,那么我们只需要引入这个TabsControl 一次就可以了。

    当然,我那个傻瓜式的方式也挺好的。哈哈,任君喜欢

  • 相关阅读:
    vue第十单元(动态组件 keep-alive(钩子函数) 递归组件(name) 组件命名约定)
    vue第九单元(非父子通信 events 单向数据流)
    vue第八单元(组件通信 子父,父子组件通信 自定义事件 事件修饰符 v-model props验证 )
    vue第七单元(vue的单文件组件形式-单文件组件的加载原理-vue-cli构建的开发环境以及生命周期)
    vue第六单元(vue的实例和组件-vue实例的相关属性和方法-解释vue的原理-创建vue的组件)
    vue第四单元(初识vue-在页面中直接引入vue框架-学习使用vue语法-vue的指令-介绍data用法-methods用法)
    vue第三单元(webpack的应用-能根据具体的需求构建对应的开发环境)
    vue第二单元(webpack的配置-学习webpack的常用配置)
    vue第一单元(初识webpack-webpack的功能-webpack的初步使用)
    ◆◆0如何debug后台Job程序(JDBG)
  • 原文地址:https://www.cnblogs.com/xianyulaodi/p/5634843.html
Copyright © 2011-2022 走看看