React.js

2018-02-03  本文已影响28人  刘昊2018

文档

前言

本来学习了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。
需要注意的有:

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

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

组件生命周期

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

再补充一下,使用组件只需引入后在需要的地方用<>来表示。
如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

上一篇下一篇

猜你喜欢

热点阅读