美文网首页程序员Android技术知识React.js
React战记之玩转Flex布局(上篇--容器属性)

React战记之玩转Flex布局(上篇--容器属性)

作者: e4e52c116681 | 来源:发表于2018-12-09 13:56 被阅读33次

    零、前言

    最近一直在总结Android,前端这块感觉忘得也差不多了
    Flex布局以前也听过,但没有详细学习过,趁机会用React玩转一下,
    遇到一个新的知识怎么学,一大堆的参数让人发懵,我最喜欢的一句话:能应对变化的只有变化本身
    用自己的能力让学习的对象非静态,就像与你交流的是一个活的人而非人偶
    本文并非React基础教程,也非Flex布局讲解教程,只是做一个Flex布局演示器
    源码见文尾捷文规范

    不废话了,留图镇楼:
    效果图

    一、搭建React项目:

    1.创建+scss配置

    个人比较喜欢scss,最新的create-react-app的webpack已经对scss进行了配置
    只需添加node-sass就行了

    npm i create-react-app
    npm i node-sass -D
    

    2.搭建静态页面
    静态页面.png
    2.1:.Flex矩形div(默认长宽1000*300px)
    .Flex {
      border: red 2px solid;
      margin-top: 20px;
      margin-left: 20px;
      width: 1000px;
      height: 300px;
      background-color: rgba(71,71,71,.6);
      display: flex;
      .title {
        border-radius: 10px;
        font-size: 30px;
        text-align: center;
      }
    }
    
    Flex.png
    2.2:生成若干的条目
    1.准备动态数据
    let justifyContent = {
        index: 0,
        data: ["normal", "flex-start", "flex-end", "center", "space-between", "space-around"]
    };
    let flexDirection = {
        index: 0,
        data: ["row", "row-reverse", "column", "column-reverse"]
    };
    let flexWrap = {
        index: 0,
        data: ["nowrap", "wrap", "wrap-reverse"]
    };
    let alignItems = {
        index: 0,
        data: ["normal", "stretch", "flex-start", "flex-end", "center", "baseline"]
    };
    let alignContent = {
        index: 0,
        data: ["normal", "stretch", "flex-start", "flex-end", "center", "space-between", "space-around"]
    };
    
    <div className="Flex" style={{
        width: this.state.ctrl[1].data + "px",
        height: this.state.ctrl[2].data + "px",
        flexDirection: flexDirection.data[flexDirection.index % flexDirection.data.length],
        flexWrap: flexWrap.data[flexWrap.index % flexWrap.data.length],
        justifyContent: justifyContent.data[justifyContent.index % justifyContent.data.length],
        alignItems: alignItems.data[alignItems.index % alignItems.data.length],
        alignContent: alignContent.data[alignContent.index % alignContent.data.length]
    }}>
        {this.formItem()}
    </div>
    
    加条目.png

    辅助函数:随机颜色:Logic.randomRGB

    /**
     * 随机颜色
     * @param a 透明度--默认为1
     * @returns {string}
     */
    static randomRGB(a = 1) {
        return `rgba(${this.rangeInt(0, 255)},${this.rangeInt(0, 255)},${this.rangeInt(0, 255)},${a})`
    }
    

    根据数组动态生成随机颜色的条目:Flex.formItem

    formItem() {
        let color = [];
        for (let i = 0; i < this.state.ctrl[0].data; i++) {
            color.push(Logic.randomRGB(.8))
        }
        return (
            color.map((item, index) => {
                return (
                    <div className={"title"} style={{backgroundColor: item}} key={index}>
                        Toly{index}
                    </div>
                );
            })
        )
    }
    

    3.底部栏的组件:ListInfo.js
    底部+点击回调.png
    <ListInfo data={this.state.flexObj}
              onItemClick={this.onItemClick.bind(this)}/>
    

    3.1:数据的获取:flexObj

    可以说是以其人之道还治其人之身,用.Flexdiv的自身属性自动生成对象

    notifyChanged() {
        this.setState({
            flexObj: {
                "flex-direction": flexDirection.data[flexDirection.index],//元素排列方向
                "flex-wrap": flexWrap.data[flexWrap.index],//换行
                "justify-content": justifyContent.data[justifyContent.index],//水平对齐方式
                "align-items": alignItems.data[alignItems.index],//垂直对齐方式
                "align-content": alignContent.data[alignContent.index],//多行垂直对齐方式,
            }
        });
    }
    

    3.2:数据的显示:ListInfo.js
    import React, {Component} from 'react';
    import './ListInfo.scss'
    
    class ListInfo extends Component {
        render() {
            return (
                <div className="ListInfo" >
                    {this.formList(this.props.data)}
                </div>
            )
        }
    
        formList(data) {//对象转化数组
            let datas = [];
            for (let key in data) {
                datas.push({
                        name: key,
                        data: data[key]
                    }
                );
            }
    
            return (
                <div id="list-container">
                    {datas.map((item, index) => {
                        return (//此处点击回调onItemClick,捕获索引
                            <div key={index} className="card" onClick={() => {
                                this.props.onItemClick && this.props.onItemClick(index);
                            }}>
                                {item.name}:<br/>
                                {item.data}<br/>
                            </div>
                        )
                    })}
                </div>
            )
        }
    }
    

    3.3:样式:ListInfo.scss
    #list-container {
      display: flex;
    
      .card{
        background-color: #26A5F8;
        cursor: pointer;
        margin-top: 20px;
        margin-left: 30px;
        padding: 10px;
        font-weight: bold;
        font-size: 24px;
        border-radius: 10px;
        box-shadow: #61dafb 2px 2px 10px 2px;
      }
    }
    

    4.右栏的控制界面:
    右侧控制.png
    4.1:数据样式:Flex.js
    this.state = {
        flexObj: '',
        ctrl: [
            {
                data: 10,
                info: "条目数量",
                fun: this.onCountChanged.bind(this)
            },
            {
                data: 1000,
                info: "容器宽度",
                fun: this.onBoxWidthChanged.bind(this)
            },
            {
                data: 300,
                info: "容器高度",
                fun: this.onBoxHeightChanged.bind(this)
            },
            {
                data: "auto",
                info: "条目宽度",
                fun: this.onItemWidthChanged.bind(this)
            },
            {
                data: "auto",
                info: "条目高度",
                fun: this.onItemHeightChanged.bind(this)
            }
        ]
    }
    

    4.2:接收数据,渲染界面+回调CtrlBox.js
    import React, {Component} from 'react';
    import './CtrlBox.scss'
    
    class CtrlBox extends Component {
    
        render() {
            return (
                <div className="right-ctrl">
                    {this.createItem(this.props.ctrl)}
                </div>
            )
        }
    
        createItem(ctrl) {
            return (
                ctrl.map((item, index) => {
                    return (
                        <div className={"container"} key={index}>
                            <label>{this.props.ctrl[index].info}:</label>
                            <input
                                onChange={
                                    (v) => {
                                        this.bindCallback(index, v);
                                    }}
                                defaultValue={this.props.ctrl[index].data}/>
                            <label>px</label>
                        </div>
                    );
                })
            )
        }
    
        /**
         * 绑定回调事件
         * @param index
         * @param v
         */
        bindCallback(index, v) {
            switch (index) {
                case 0:
                    this.props.onCountChanged(v.target.value);
                    break;
                case 1:
                    this.props.onBoxWidthChanged(v.target.value);
                    break;
                case 2:
                    this.props.onBoxHeightChanged(v.target.value);
                    break;
                case 3:
                    this.props.onItemWidthChanged(v.target.value);
                    break;
                case 4:
                    this.props.onItemHeightChanged(v.target.value);
                    break;
                default:
                    break;
            }
        }
    }
    
    export default CtrlBox;
    

    4.3、回调函数与使用:Flex.js
    <CtrlBox
        ctrl={this.state.ctrl}
        onCountChanged={this.state.ctrl[0].fun}
        onBoxWidthChanged={this.state.ctrl[1].fun}
        onBoxHeightChanged={this.state.ctrl[2].fun}
        onItemWidthChanged={this.state.ctrl[3].fun}
        onItemHeightChanged={this.state.ctrl[4].fun}/>
    
    /**
     * 数量变化时的处理
     * @param count
     */
    onCountChanged(count) {
      
    }
    /**
     * flex盒子宽变化时处理
     * @param num
     */
    onBoxWidthChanged(num) {
        
    }
    /**
     * flex盒子高变化时处理
     * @param num
     */
    onBoxHeightChanged(num) {
       
    }
    /**
     * item宽变化时处理
     * @param num
     */
    onItemWidthChanged(num) {
      
    }
    /**
     * item高变化时处理
     * @param num
     */
    onItemHeightChanged(num) {
      
    }
    
    静态界面.png

    这样静态页面和回调都实现了,下面只要对回调具体逻辑进行编写就行了


    三、回调的具体逻辑


    1.点击下方条目时,动态改变数据
    /**
     * 点击下方条目
     * @param index
     */
    onItemClick(index) {
        switch (index) {
            case 0:
                flexDirection.index++;
                break;
            case 1:
                flexWrap.index++;
                break;
            case 2:
                justifyContent.index++;
                break;
            case 3:
                alignItems.index++;
                break;
            case 4:
                alignContent.index++;
                break;
            default:
                break;
        }
        this.notifyChanged();
    }
    

    2.输入框的回调:
    /**
     * 数量变化时的处理
     * @param count
     */
    onCountChanged(count) {
        let ctrl = this.state.ctrl;
        ctrl[0].data = count;
        this.setState({
            ctrl
        })
    }
    /**
     * flex盒子宽变化时处理
     * @param num
     */
    onBoxWidthChanged(num) {
        let ctrl = this.state.ctrl;
        ctrl[1].data = num;
        this.setState({
            ctrl
        });
    }
    /**
     * flex盒子高变化时处理
     * @param num
     */
    onBoxHeightChanged(num) {
        let ctrl = this.state.ctrl;
        ctrl[2].data = num;
        this.setState({
            ctrl
        });
    }
    /**
     * item宽变化时处理
     * @param num
     */
    onItemWidthChanged(num) {
        let ctrl = this.state.ctrl;
        ctrl[3].data = num;
        this.setState({
            ctrl
        });
    }
    /**
     * item高变化时处理
     * @param num
     */
    onItemHeightChanged(num) {
        let ctrl = this.state.ctrl;
        ctrl[4].data = num;
        this.setState({
            ctrl
        });
    }
    

    看似功能挺复杂,其实也就这点代码,重点在于数据的把握与对象的封装
    我并非一开始就能把数据统筹成这样,也是遇到了,看能合并,就合并一下,零散的属性看着烦心
    这也全靠Android(或java)让我对对象认识深刻,所以什么事就是有联系的,思想有了,一切好办


    后记:捷文规范

    1.本文成长记录及勘误表
    项目源码 日期 备注
    V0.1--github 2018-12-9 React战记之玩转Flex布局(上篇--容器属性)
    2.更多关于我
    笔名 QQ 微信 爱好
    张风捷特烈 1981462002 zdl1994328 语言
    我的github 我的简书 我的掘金 个人网站
    3.声明

    1----本文由张风捷特烈原创,转载请注明
    2----欢迎广大编程爱好者共同交流
    3----个人能力有限,如有不正之处欢迎大家批评指证,必定虚心改正
    4----看到这里,我在此感谢你的喜欢与支持


    icon_wx_200.png

    相关文章

      网友评论

        本文标题:React战记之玩转Flex布局(上篇--容器属性)

        本文链接:https://www.haomeiwen.com/subject/ilohhqtx.html