• React 入门之路


    React

    React简介

    是由Facebook公司推广的一套框架,已经应用instagram等产品

    React就是为了提供应用程序性能而设计的一套框架

    在angular中,对dom提供了一些指令,让dom具有一些功能,例如ng-repeat让dom具有动态循环渲染的功能,ng-show让dom元素具有动态显隐的功能等等

    比如将页面比作一辆汽车,

    Angular的实现就是为汽车添加一些装饰,增加一些功能,让汽车看上去很高大尚,这样势必要加大油门

    React的实现就是重新制造一辆汽车,是有四个轱辘,即可启动,不要很大的油门

      React有三大创新

        虚拟dom

        组件开发

        多端适配

          一处开发,处处适用

        react在0.13版本之后,做了一个处理

          将react文件分成了两个部分     

             React.js核心库文件(创建虚拟dom的,核心模块,写的应用程序可以兼容所有端)

             React-dom.js在浏览器端渲染虚拟dom

    创建虚拟dom

      由react对象提供的一个方法createElement

      第一个参数表示虚拟dom的名称,例如div

        有时我们还可以传递组件

      第二个参数是一个对象,表示虚拟dom中拥有的属性

        从第三个参数开始表示该虚拟dom元素的子元素

      子元素也要由createElement创建,但是文本节点可以直接写

      方法的返回值是一个虚拟dom(js对象)

    Render

      由ReactDOM提供的一个方法

        三个参数

          1 渲染虚拟dom元素

          2 真实的dom元素

          3 渲染完成回调函数(不常用)

    复制代码
    1// 创建虚拟dom
    2var h1 = React.createElement(
    3        'h1', 
    4        {
    5            title: '这是标题'
    6        }, 
    7        '我是文本内容啦啦啦'
    8    )
    9// 将h1渲染到页面中
    10ReactDOM.render(h1, document.getElementById('app'), function () {
    11    console.log(arguments)
    12    console.log(this)
    })
    复制代码

    组件

      在react中定义的一个虚拟dom很难复用,所以通常我们将一组虚拟dom定义在组件中来复用

        createClass可以用来创建一个组件

      参数是一个对象,用来描述组件的

      可以在对象中定义render方法,通过返回值来渲染这组组件

      返回值,通常所有虚拟dom都在一个容器内

      组件式一个类,因此组件名称要以大写字母开头

      组件要想渲染到页面中,就要将组件转化成虚拟dom,通过React.createElement方法(由React-dom.js提供)

    复制代码
    1var List = React.createClass({
    2    // 通过render渲染页面
    3    render: function () {
    4        return (
    5             React.createElement(
    6                'ul', 
    7                null, 
    8                React.createElement('li', null, '六间房秀场'),
    9                React.createElement('li', null, '斗鱼TV'),
    10                React.createElement('li', null, '美女秀场'),
    11                React.createElement('li', null, '秀色直播')
    12            )
    13        )
    14    }
    15})
    16// 将组件渲染到页面中
    17// 转化组件到虚拟DOM
    18var ul = React.createElement(List)
    ReactDOM.render(ul, document.getElementById('app'))
    复制代码

    JSX语法

      我们写虚拟dom的最大问题,创建一个虚拟dom成本太高了(写的太麻烦了),React团队为了简化对createElement的书写,为我们提供了jsx语法

        react团队提供了两种处理方法

          第一种,在浏览器端编译 

              引入编译库,例如browser.js可以对jsx语法编译

              此时定义的script标签的type类型要定义成text/babel, 在里面可以写jsx语法

           第二种,在工程化中编译(最常见的)

              编译jsx语法,跟以前编译less,sass,stylus很像

              首先要获取这些jsx文件(通常我们将写jsx语法的文件拓展名改成.jsx)

      以fis为例

    复制代码
    1fis.match('**.jsx', {
    2    // 编译
    3    parser: 'babel2',
    4    // 更改后缀名称
    5    rExt: '.js'
    })
    复制代码

    特殊属性

    Class

      Class在js中是保留字,因此在react定义虚拟dom的时候,将class写成className

    For (是label元素特有的属性)

      For是js中的关键字,因此在react定义虚拟dom的时候,将for属性写成htmlFor

    复制代码
    1var h1 = (<h1 className="red">我是文本内容啦啦啦</h1>);
    2// 将虚拟dom渲染到页面中
    3ReactDOM.render(h1, document.getElementById('app'))
    4
    5// 创建一个组件
    6var User = React.createClass({
    7    render: function() {
    8        // 返回虚拟dom
    9        return (
    10            <div>
    11                <label htmlFor="user_name">用户名</label>
    12                <input id="user_name" type="text" />
    13            </div>
    14        );
    15    }
    }) 
    复制代码

    插值

      React支持插值语法,我们在jsx语法中使用,语法是  {}

      一对{}提供了一个js环境,因此我们可以在大括号里面设置虚拟dom元素的属性,设置虚拟dom元素的内容

      我们可以在插值符号中使用js中的任何表达式

    非元素属性

      Key 为列表元素定义react-id,绑定id。这样可以方便获取页面中哪些元素更新了,哪些元素需要更新

      Render方法的作用域是组件实例化对象,可以访问到组件中定义的方法

    复制代码
    1createChildList: function () {
    2    // 遍历数组,处理每一个成员,然后映射一个新数组,就是map方法
    3    return data.map(function (value, index) {
    4        // 每一个li要绑定内容,还要设置key
    5        return <li key={index}>{value}</li>;
    6    })
    },
    复制代码

    属性

      在html中,对于同一类元素来说,之所以展现的样式不一样,是因为他们具有不同的属性,所以属性可以让同一类元素展现出不同的状态

      同样的道理,在react中,对于同一个组件来说,可以创建一组虚拟dom树,如果想让虚拟dom树展现出不同的状态,我们就要为其添加属性

      在虚拟dom上添加属性跟在html中元素上添加属性是一样的,通过添加一个属性实现(只不过在组件上添加的都是自定义属性)

      我们添加的自定义属性,会存储在组件的props属性中,我们通过this.props可以访问到里面的数据

      组件的默认属性我们定义在getDefaultProps中,通过返回值设置默认属性数据

    复制代码
    1// 创建导航标题组件
    2var Nav = React.createClass({
    3    // 定义默认属性数据
    4    getDefaultProps: function () {
    5        // 通过返回值定义默认属性数据
    6        return {
    7            data: ['默认标题']
    8        }
    9    },
    10    // 封装渲染内容的方法
    11    createChildList: function () {
    12        var me = this;
    13        // 遍历this.props.data渲染
    14        return this.props.data.map(function (value, index) {
    15            return (<a href="" key={index}>{value}{index != me.props.data.length - 1 ? '/' : ''}</a>)
    16        })
    17    },
    18    // 通过render方法渲染虚拟dom树
    19    render: function () {
    20        return (
    21            <div>
    22                {this.createChildList()}
    23            </div>
    24        )
    25    }
    26})
    27var data1 = ['财经', '证券', '理财'];
    28// 渲染
    ReactDOM.render(<Nav data={data1} />, document.getElementById('app'))
    复制代码

    样式

      在虚拟dom中我们可以为元素定义样式

      在react中,虚拟dom上不能使用行内样式字符串,行内样式只能定义成对象,Css属性名称如果出现多个单词,要使用驼峰式命名,例如

        border-color => borderColor

      还要求浏览器前缀第一个字母要大写,例如

        -webkit-box-shadow  => WebkitBoxShadow

      在createElement方法中,样式写在style中,直接赋值对象,在jsx语法中,样式写在style中,要使用插值语法

    复制代码
    1// 定义虚拟dom
    2var h1 = React.createElement('h1', {
    3    style: {
    4        color: 'red',
    5        fontSize: '40px'
    6    }
    7}, '我是文本内容啦啦啦');
    8
    9// jsx语法,定义虚拟dom
    10var h1 = (<h1 style={{
    11    color: 'green',
    12    fontSize: '100px'
    }}>文本内容</h1>)
    复制代码

    事件

      React中定义事件,跟在html中定义事件很像

      在html中定义事件

        <button onclick="console.log('hello')">按钮</button>

      在react中jsx语法中定义事件,跟html中定义事件很像

        <button onClick={this.clickBtn}>按钮</button>

      on+事件名称=回调函数 
        事件名称首字母大写

        事件回调函数通常绑定组件中的方法

        事件回调函数不要执行(后面不要加())

      事件回调函数

        作用域是组件实例化对象(可以通过this访问组件上的方法以及属性数据)

        可以通过bind方法更改作用域

        可以通过bind方法传递自定义参数(很少用)

      参数有三个

        React封装的事件对象(最常用)

        React-id

        源生的事件对象

    复制代码
    1var Demo = React.createClass({
    2    // 定义事件回调函数
    3    clickBtn: function () {
    4        console.log(arguments)
    5        console.log(this)
    6    },
    7    render: function () {
    8        return (
    9            <div>
    10                <button onClick={this.clickBtn.bind(this, 11)}>这是个按钮</button>
    11            </div>
    12        )
    13    }
    }) 
    复制代码

    这个就是参数

    状态

      状态跟属性一样都是在组件内部存储数据的

        属性是组件外部传递的数据

        状态是组件内部维护的数据

          有状态组件以及无状态组件

            无状态组件

              对于一个组件来说,如果组件没有状态,也就是说组件式一成不变的,组件在创建之后,不会发生交互,请求数据等等,这类组件叫无状态组件,

              组件自身不会维护状态

            有状态组件

              对于一个组件来说,自从创建以后,组件会产生一些交互,请求一些数据,来完成自身状态的更新,这类组件内部必须维护一个状态来存储这些变化的数据,这类组件叫有状态

        组件处于哪种状态由其自身存储的数据决定,组件的存储跟属性一样,在组件实例化对象中有个state属性,就是用来存储状态数据

        初始化状态用getInitialState方法定义,通过return 将初始化状态的数据返回

        修改状态,用setState方法

          参数是一个对象,对象中的属性就是即将修改的状态

        状态或者属性的改变都会触发render方法的执行,这句话很重要

    最后是一个小小的换肤案例

      html代码

    复制代码
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title></title>
        <link rel="stylesheet" type="text/css" href="less/15.less">
    </head>
    <body>
        <div id="app"></div>
    <script type="text/javascript" src="lib/react.js"></script>
    <script type="text/javascript" src="lib/react-dom.js"></script>
    <script type="text/javascript" src="lib/jquery.js"></script>
    <script type="text/javascript" src="code/15.jsx"></script>
    </body>
    </html>
    复制代码

      less代码

    复制代码
    * {
        list-style: none;
        margin: 0;
        padding: 0;
    }
    body {
        background-repeat: no-repeat;
        background-attachment: fixed;
        background-position: center 0;
        background-size: cover;
    }
    #app {
         1118px;
        margin: 50px auto;
        ul {
            margin-right: -10px;
        }
        li {
             178px;
            margin-right: 10px;
            float: left;
            margin-bottom: 10px;
        }
        p {
            line-height: 30px;
            text-align: center;
        }
        img {
            cursor: pointer;
        }
    }
    复制代码

      jsx代码

    复制代码
    // 定义换肤组件
    var Skin = React.createClass({
        // 初始化状态数据
        getInitialState: function () {
            return {
                list: []
            }
        },
        // 定义事件回调函数
        chooseImage: function (e) {
            // 获取li元素
            var li = e.currentTarget;
            // 获取
            var id = li.getAttribute('data-id')
            // 用id获取大图片的地址,渲染body
            document.body.style.backgroundImage = 'url(img/skin/big_' + id + '.jpg)'
            // console.log(id)
        },
        // 定义渲染列表的方法
        getImageList: function () {
            var me = this;
            // 通过状态来渲染了
            return this.state.list.map(function (obj, index) {
                return (<li key={index} data-id={obj.id} onClick={me.chooseImage}>
                        <img src={"img/skin/" + obj.src} alt=""/>
                        <p>{obj.title}</p>
                    </li>)
            })
        },
        render: function () {
            return (
                <ul>{this.getImageList()}</ul>
            )
        },
        // 发送请求获取数据
        componentDidMount: function () {
            var me = this;
            $.get('data/skin.json', function (res) {
                // 请求成功,更新状态数据
                if (res && res.errno === 0) {
                    me.setState({
                        list: res.data
                    })
                }
            })
        }
    })    
    
    // 渲染到页面中
    ReactDOM.render(<Skin />, document.getElementById('app'))
    复制代码
  • 相关阅读:
    [CSP-S模拟测试]:party?(霍尔定理+最小割+树链剖分)
    [CSP-S模拟测试]:marshland(最大费用可行流)
    [CSP-S模拟测试]:Revive(点分治)
    [CSP-S模拟测试]:Lighthouse(哈密顿回路+容斥)
    [CSP-S模拟测试]:Lost My Music(凸包)
    [CSP-S模拟测试]:God Knows(线段树维护单调栈)
    [CSP-S模拟测试]:Star Way To Heaven(最小生成树Prim)
    [CSP-S模拟测试]:gcd(莫比乌斯反演)
    [CSP-S模拟测试]:water(BFS)
    BZOJ3462 DZY Loves Math II 【多重背包 + 组合数】
  • 原文地址:https://www.cnblogs.com/libin-1/p/6550921.html
Copyright © 2020-2023  润新知