ReactJs学习

ReactJs是一个JavaScript库,支持前端web和在服务端运行,用于构建用户界面和web应用程序。

React Native是一个移动端框架,可编译为本地应用程序组件,允许使用JavaScript构建原生移动应用程序(IOS、Android、web),允许使用ReactJs构建组件。

以上两者都是facebook开源的。

此篇是学习reactjs的总结。

安装

# 安装CLI
sudo npm install -g create-react-app

# 创建一个项目
create-react-app react-app-demo

# 安装依赖
cd react-app-demo
npm install

# 本地启动预览
npm start

启动后预览:

编写第一个组件

import React from 'react';
import ReactDOM from 'react-dom';

class HelloWorld extends React.Component {
    render() {
      return (
        <div>Hello World!</div>
      )
    }
}
  
ReactDOM.render(<HelloWorld />, document.getElementById('root'));

预览:

注:上述组件中唯一的方法render(),每个组件都需要一个渲染方法,渲染组件的UI。

ReactDOM.render需要两个参数。第一个参数是要渲染的组件,第二个参数是要渲染组件的DOM节点。

使用JSX

class HelloWorld extends React.Component {
  render() {
    return React.createElement("div", null, "Hello World");
  }
}

每次发生状态时,通过重新呈现虚拟DOM,react可以轻松使得应用处于任何状态。

**用户事件改变程序状态 → 重新渲染虚拟DOM → 使用新的虚拟DOM区分以前的虚拟DOM → 只更新有变化的真实DOM **

state

将状态添加到组件。

使用内部状态的例子:

import React from 'react';
import ReactDOM from 'react-dom';

class HelloUser extends React.Component {
    constructor(props) {
      super(props)
  
      this.state = {
        username: 'summer'
      }
    }
    render() {
      return (
        <div>
          Hello {this.state.username}
        </div>
      )
    }
  }
  
ReactDOM.render(<HelloUser />, document.getElementById('root'));

预览:

this.state在构造函数中的任何数据都将成为该组件状态的一部分。

**通知应用程序一些数据已经改变 → 重新渲染虚拟DOM → 使用新的虚拟DOM区分以前的虚拟DOM → 只更新有变化的真实DOM **

通知数据已经改变的信号是setState,无论何时setState被调用,虚拟DOM都会重新渲染,则真正的DOM会更新。

使用input输入框,手动更新状态:

class HelloUser extends React.Component {
    constructor(props) {
      super(props)
  
      this.state = {
        username: 'summer'
      }
  
      this.handleChange = this.handleChange.bind(this)
    }
    handleChange (e) {
      this.setState({
        username: e.target.value
      })
    }
    render() {
      return (
        <div>
          Hello {this.state.username} <br />
          Change Name:
          <input
            type="text"
            value={this.state.username}
            onChange={this.handleChange}
          />
        </div>
      )
    }
  }

预览:

handleChange() - 每次输入,都用调用此方法,则会调用setState重新更新用户名。此时React创建一个新的虚拟DOM,比较差异,更新真实的DOM。

用户改变input文本框 → handleChange被调用 → 组件状态被设置一个新的值 → React重新呈现虚拟DOM → React比较差异 → 真实DOM被更新

从父组件接收状态(props, propTypes, getDefaultProps)

class HelloUser extends React.Component {
    render() {
      return (
        <div> Hello, {this.props.name}</div>
      )
    }
}
  
ReactDOM.render(<HelloUser name="Summer"/>, document.getElementById('root'));

预览:

同时存在两个组件,父组件将状态传给子组件:

class AddFriend extends React.Component {
    constructor(props) {
      super(props)
  
      this.state = {
        newFriend: ''
      }
  
      this.updateNewFriend = this.updateNewFriend.bind(this)
      this.handleAddNew = this.handleAddNew.bind(this)
    }
    updateNewFriend(e) {
      this.setState({
        newFriend: e.target.value
      })
    }
    handleAddNew() {
      this.props.addNew(this.state.newFriend)
      this.setState({
        newFriend: ''
      })
    }
    render() {
      return (
        <div>
          <input
            type="text"
            value={this.state.newFriend}
            onChange={this.updateNewFriend}
          />
          <button onClick={this.handleAddNew}> 添加朋友 </button>
        </div>
      )
    }
  }
  
  class ShowList extends React.Component {
    render() {
      return (
        <div>
          <h3> Friends </h3>
          <ul>
            {this.props.names.map((friend) => {
              return <li> {friend} </li>
            })}
          </ul>
        </div>
      )
    }
  }
  
  class FriendsContainer extends React.Component {
    constructor(props) {
      super(props)
  
      this.state = {
        name: '苏苏',
        friends: [
          'Summer',
          'Minya',
          'Sue'
        ],
      }
  
      this.addFriend = this.addFriend.bind(this)
    }
    addFriend(friend) {
      this.setState((state) => ({
        friends: state.friends.concat([friend])
      }))
    }
    render() {
      return (
        <div>
          <h3> Name: {this.state.name} </h3>
          <AddFriend addNew={this.addFriend} />
          <ShowList names={this.state.friends} />
        </div>
      )
    }
  }
  
  ReactDOM.render(<FriendsContainer />, document.getElementById('root'));
  

在addFriend方法中,调用setState方法。

使用AddFriend组件管理add friend。原因是FriendContainer组件不关心添加friend,只关心all friends作为一个整理(集合)。

defaaultProps允许使用默认值,如果没有值,则ShowList则将friends默认为一个空数组。

预览:

组件生命周期

每个组件都有自己的生命周期事件。比如想在初始渲染时异步(ajax)请求并获取数据,应该在哪里写?

class App extends React.Component {
    constructor(props) {
      super(props)
  
      this.state = {
        name: 'Summer'
      }
    }
    componentDidMount(){
      // 组件被装载到DOM就调用
      // 适合初始渲染时调用ajax
    }
    static getDerivedStateFromProps(nextProps, prevState) {
      // 从这个函数返回的对象会与当前对象合并
    }
    componentWillUnmount(){
      // 组件卸载之前调用,适合清理监听(listenrts)
    }
    render() {
      return (
        <div>
          Hello, {this.state.name}
        </div>
      )
    }
  }

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

componentDidMount - 在初始渲染后调用一次。由于在调用此方法时组件已被调用,如果需要,可以访问虚拟DOM。可以通过调用this.getDOMNode()来做到这一点 。因此,这是生命周期事件,适用初始渲染AJAX请求获取一些数据。

componentWillUnmount - 在组件从DOM中卸载之前立即调用此生命周期。这是可以做必要清理的地方。

getDerivedStateFromProps - 有时需要根据传入的props更新组件的状态。这是要执行此操作的生命周期方法。它会通过props和state,将返回的对象将与当前状态合并。

以上就是学习ReactJs的一个小总结。