reactjs 基础概念

2020-04-14  本文已影响0人  SlowGO
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() 是这个 class 中的唯一一个方法,每个组件都需要有一个 render(),用于描述组件的 UI 界面。

ReactDOM.render 接收2个参数:

  1. 想要渲染的组件
  2. 想要在哪个 DOM 节点上渲染这个组件

render() 中的内容类似 HTML,叫做 “JSX”,可以把类似 HTML 的内容转为 JS 对象,react 可以使用这些 JS 对象与 “virtual DOM” 交互。

上面的 JSX 实际会被编译为:

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

用户事件改变 state -> 重新渲染虚拟DOM -> 比较新旧虚拟DOM -> 更新实际DOM中的必要部分

现在已经了解到的概念:

最好可以描述出来他们的概念作用。

每个组件都可以管理自己的 state,并可以传递给子组件。

假设有一个用户组件,管理着用户信息,有另一个组件也需要用户信息,但他不是用户组件的子组件,那么需要创建一个新组件,作为用户组件和此组件的父组件。父组件可以通过 props 向下传递 state。

class HelloUser extends React.Component {
  constructor(props) {
    super(props)

    this.state = {
      username: 'tylermcginnis'
    }
  }
  render() {
    return (
      <div>
        Hello {this.state.username}
      </div>
    )
  }
}

这里使用了 constructor,用于设置组件的 state,其中任何放到 this.state 中的数据都会成为组件 state 的一部分。

改变数据 -> 重绘虚拟DOM -> 比较新旧虚拟DOM -> 更新实际DOM中的必要部分

setState 就是用于“改变数据”。

只要 setState 被调用,虚拟DOM就会重新渲染。

class HelloUser extends React.Component {
  constructor(props) {
    super(props)

    this.state = {
      username: 'tylermcginnis'
    }

    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 每次用户输入时都会被调用,handleChange 调用 setState 修改 username。

setState 会改变虚拟DOM,从而改变实际DOM。

onChange 会在每次 input 的值变化时调用绑定的方法。

这个示例的流程:

用户在 input 中输入 -> handleChange 被调用 -> setState 修改组件的 state -> 重新渲染虚拟dom -> 比较 -> 更新实际DOM

现在已经了解到的概念:

props 用于向子组件传递数据,在最高层父组件中管理数据,如果子组件需要,就可以通过 props 向下传递。

props 示例:

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

class HelloUser extends React.Component {
  render() {
    return (
      <div> Hello, {this.props.name}</div>
    )
  }
}

ReactDOM.render(<HelloUser name="Tyler" />, document.getElementById('root'));

父子组件示例:

class FriendsContainer extends React.Component {
  constructor(props) {
    super(props)

    this.state = {
      name: 'Tyler McGinnis',
      friends: ['Jake Lingwall', 'Sarah Drasner', 'Merrick Christensen']
    }
  }
  render() {
    return (
      <div>
        <h3> Name: {this.state.name} </h3>
        <ShowList names={this.state.friends} />
      </div>
    )
  }
}

设置了初始的 state,把部分数据传递给了子组件。

class ShowList extends React.Component {
  render() {
    return (
      <div>
        <h3> Friends </h3>
        <ul>
          {this.props.names.map((friend) => <li>{friend}</li>)}
        </ul>
      </div>
    )
  }
}

this.props.names.mapArray.prototype.map,map 会创建一个新的数组,对数组中的每个元素调用 callback 方法,并使用返回值填充数组。

例如:

const friends = ['Jake Lingwall', 'Sarah Drasner', 'Merrick Christensen'];
const listItems = friends.map((friend) => {
  return "<li> " + friend + "</li>";
});

// 结果
// ["<li> Jake Lingwall</li>", "<li> Sarah Drasner</li>", "<li> Merrick Christensen</li>"];

记住:哪里的数据,就应该在哪里操作。如果需要在外部操作,应该把 getter/setter 传递过去。

class FriendsContainer extends React.Component {
  constructor(props) {
    super(props)

    this.state = {
      name: 'Tyler McGinnis',
      friends: [
        'Jake Lingwall',
        'Sarah Drasner',
        'Merrick Christensen'
      ],
    }

    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>
    )
  }
}

prop-types 用于描述 props,例如 类型、是否必须。

import React from 'react'
import PropTypes from 'prop-types'

class AddFriend extends React.Component {
  constructor(props) {
    super(props)

    this.state = {
      newFriend: ''
    }
  }
  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}> Add Friend </button>
      </div>
    )
  }
}

AddFriend.propTypes: {
  addNew: PropTypes.func.isRequired
}

defaultProps 用于指定 props 的默认值

class ShowList extends React.Component {
  render() {
    return (
      <div>
        <h3> Friends </h3>
        <ul>
          {this.props.names.map((friend) => {
            return <li> {friend} </li>
          })}
        </ul>
      </div>
    )
  }
}

ShowList.defaultProps = {
  names: []
}

现在已经了解到的概念:

如果想请求初始化数据,在哪儿做?props 变动的时候做一些逻辑处理,在哪儿做?这就涉及组件的生命周期。

class App extends React.Component {
  constructor(props) {
    super(props)

    this.state = {
      name: 'Tyler McGinnis'
    }
  }
  componentDidMount(){
    // 组件挂载到DOM后触发
    // 适合发起 AJAX requests
  }
  static getDerivedStateFromProps(nextProps, prevState) {
    // 从该函数返回的对象将与当前状态合并.
  }
  componentWillUnmount(){
    // 组件被挂载前触发
    // 适合清理 listeners
  }
  render() {
    return (
      <div>
        Hello, {this.state.name}
      </div>
    )
  }
}

参考 https://tylermcginnis.com/reactjs-tutorial-a-comprehensive-guide-to-building-apps-with-react/

上一篇 下一篇

猜你喜欢

热点阅读