React.js

作者: 刘昊2018 | 来源:发表于2018-02-03 10:06 被阅读28次

    文档

    前言

    本来学习了Vue.js之后,没有再想学习React.js。但是,又非常想使用阿里的ant design项目,为了不再纠结,还是用了一两天,进行了一些粗略的学习。

    脚手架

    下载create-react-app

    cnpm install create-react-app -g
    

    初始化项目

    create-react-app react-demo
    

    脚手架会优先使用yarn下载依赖

    查看package.json

    {
      "name": "react-demo",
      "version": "0.1.0",
      "private": true,
      "dependencies": {
        "react": "^16.2.0",
        "react-dom": "^16.2.0",
        "react-scripts": "1.1.0"
      },
      "scripts": {
        "start": "react-scripts start",
        "build": "react-scripts build",
        "test": "react-scripts test --env=jsdom",
        "eject": "react-scripts eject"
      }
    }
    

    需要注意的是,我们发现依赖非常之少,没有看见,webpack,babel,学过Vue.js之后对这些东西是非常敏感的。

    scripts中,我们发现,构建脚本好像在使用一个叫react-scripts的东西,按照直觉,我们应该去看看这个包是干什么用的。

    node_modules中,我们找到react-scripts文件夹,结构如下:

    bin
    config
    node_modules
    scripts
    package.json
    README.md
    

    bin中我们发现有react-scripts.js,接收命令行参数。
    scripts中,我们发现有start.js,我们在里面发现了webpackwebpack-dev-server这些东西。
    此时,解除了我们之前的疑惑,react-scripts将webpack等开发中使用的工具为我们进行了封装,是我们不必要直接接触,只需要使用react-scripts命即可。不得不说,这是对开发人员非常友好的。

    运行项目

    cnpm start
    

    如果运行正常,将在3000端口起来一个HelloWorld。

    React知识点

    入口函数

    ReactDOM.render(<App />, document.getElementById('root'));
    

    将App组件渲染到root div中。
    类似与Vue中:

    new Vue({
        el:"#id",
        components:{
          App.name:App
        },
        template:<app/>
    });
    

    JSX

    使用React,jsx是我们避免不了的东西,虽然我也是非常不喜欢。但是,也没有办法...

    简单记录一下

    const element = <h1>Hello, world!</h1>;
    const element = <img src={this.avatarUrl}></img>;
    
    function formatName(user) {
      return user.firstName + ' ' + user.lastName;
    }
    const user = {
      firstName: 'Harper',
      lastName: 'Perez'
    };
    const element = (
      <h1>
        Hello, {formatName(user)}!
      </h1>
    );
    
    

    组件

    组件是我们构建应用的基本单元,在Vue中我们使用的是.vue的单文件组件,在React也类似,不过文件名还是.js。

    组件基本模板

    import React, { Component } from 'react';
    
    class MyComponent extends Component {
        constructor(props) {
            super(props);
            this.state = {  }
        }
        render() { 
            return ( 
            <div>
    
            </div>
         );
        }
    }
     
    export default MyComponent;
    

    我们可以在VSCode中,安装相关插件,书写代码非常快。

    可以看到,我们的自定义组件首先继承React的Component,在render方法中书写web骨架。

    React数据三兄弟

    我们在上面的代码中,敏感的发现有两个东西应该值得我们关注,那就是stateprops。还有一个没有出现的是context。这些是比较重要的东西,我们一个一个介绍。

    state

    state用来维护界面view和模型的model的绑定。类似与vue中的data。

    import React, { Component } from 'react';
    
    class MyComponent extends Component {
        constructor(props) {
            super(props);
            this.state = { 
                msg : 'hello react',
                number:0
            }
        }
        add = () => {
            this.setState({ 
                number:this.state.number + 1
            });
        }
        render() { 
            return ( 
            <div>
                <p>{this.state.msg}</p>
                <p>{this.state.number}</p>
                <button onClick={this.add}>点我加1</button>
            </div>
         );
        }
    }
     
    export default MyComponent;
    

    this.state是一个json对象,使用时用{}表示引用变量。
    当我们点击按钮后,界面上的数字将增加1。
    需要注意的有:

    • onClick中c大写。
    • 自己的方法要写箭头函数,才能正确拿到this引用。
    props

    props用来处理父组件向子组件传参,vue中也是使用的同样的关键字。不过与vue中有非常大的不同。react中的props更加易用。

    创建一个子组件

    import React, { Component } from 'react';
    
    class Child extends Component {
        constructor(props) {
            super(props);
            console.log(props)
            this.state = {  }
        }
        render() { 
            return ( 
                <div>
                    <p>{this.props.say}</p>
                </div>
             );
        }
    }
     
    export default Child;
    

    修改MyComponent.js

     this.state = { 
        msg : 'hello react',
        number:0,
        say : 'hello child'
     }
    
    <Child say={this.state.say} />
    

    这样,child组件就能接收并使用say变量。
    需要注意的是,props并不是固定的,props作为构造函数的第一个参数传入,我们可以修改形参为其他的代号,也就说,如果我们这样:

     constructor(p) {
            super(p);
        }
     <p>{this.p.say}</p>
    

    也是可行的,只不过我们一般都会使用props。见名知意。

    现在我们来思考一个问题,刚才我们都是从父组件向子组件传递数据,那么子组件如何向父组件传递数据呢?以如上实例中,子组件如何控制父组件的数字加1操作呢?这里就要用到一些技巧了,我们来看:

    我们大发脑洞,将add函数传给child。

    <Child add={this.add}/>
    

    在child中:

    this.state = {
         parantAdd : props.add
    }
    
     <button onClick={()=>{ this.state.parantAdd();}}>点我给父亲加1</button>
    

    这样就实现了子组件控制父组件的view和model。大家可以体会一下。

    context

    比前两个用的少,暂且不介绍。

    组件生命周期

    老生常谈的问题,列举几个常用的,没有什么好说的。

    • componentWillMount 渲染之前
    • componentDidMount 第一次渲染之后
    • componentWillUnmount 组件从DOM中被移除时。

    再补充一下,使用组件只需引入后在需要的地方用<>来表示。
    如App,就写<App/>。

    React Router

    react-router是react生态中的路由项目,最新版本是4.2。由于4.x是从2.x直接上来的,API变化较大。而且也没有比较好文档,官方的文档基本上是代码示例的堆砌,没有细节的解释。这一点,确实比vue-router做的要差一些。

    下载
    cnpm install react-router-dom --save
    

    在根组件中注册

    import {
      BrowserRouter as Router,
      Route,
      Switch
    } from 'react-router-dom';
    
    import Welcome from './Welcome'
    import NotFound from './NotFound'
    

    Welcome.js

    import React, { Component } from 'react';
    import { Route } from 'react-router-dom';
    
    import User from './User';  
    
      
      class Welcome extends Component {
          constructor(props) {
              super(props);
              this.state = {  }
          }
          render() { 
              return ( 
              <div>
                  <p>welcome page </p>
                  <Route path="/welcome/:userId" component={User}/>
              </div>
             );
          }
      }
       
      export default Welcome;
    

    welcome中使用到了嵌套路由。

    User.js

    import React, { Component } from 'react';
    
    class User extends Component {
        constructor(props) {
            super(props);
            this.state = { 
                userId : this.props.match.params.userId
            }
        }
        render() { 
            return ( 
            <div>
                <p>id:{this.state.userId}</p>
            </div>
         );
        }
    }
     
    export default User;
    

    NotFound.js

    import React, { Component } from 'react';
    
    class NotFound extends Component {
        constructor(props) {
            super(props);
            this.state = {  }
        }
        render() { 
            return ( 
            <div>
                <p>404 Not Found</p>
            </div>
         );
        }
    }
     
    export default NotFound;
    

    推荐在根组件中做路由分发时,写成如下结构形式:

    <Router>
      <Switch>
          <Route path="/welcome" component={Welcome}/>
          <Route path="/" component={Welcome} exact/>
          <Route path="*" component={NotFound}/>
      </Switch>
    </Router>
    

    Flux

    Redux

    dva

    相关文章

      网友评论

          本文标题:React.js

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