React 小黑板-核心概念

115 阅读3分钟

组件

组件的的提取

从经验来看,某些可能被复用的部分可以被提取为组件,包括业务逻辑处理以及UI表示。当然,如果一个画面相当的大,那么我们也应该给拆分分组件

  1. 根据设计稿设计出组件数
  2. 一个组件负责一个功能,尽可能不在render中使用if...else if...else
  3. 先出静态画面,再完成交互。交互时,仅定义必须的state,严禁乱用state
    1. 该数据是否是由父组件通过 props 传递而来的?如果是,那它应该不是 state。
    2. 该数据是否随时间的推移而保持不变?如果是,那它应该也不是 state。
    3. 你能否根据其他 state 或 props 计算出该数据的值?如果是,那它也不是 state。
  4. 确定state的位置
    1. 找到根据这个 state 进行渲染的所有组件。
    2. 找到他们的共同所有者(common owner)组件(在组件层级上高于所有需要该 state 的组件)。
    3. 该共同所有者组件或者比它层级更高的组件应该拥有该 state。
    4. 如果你找不到一个合适的位置来存放该 state,就可以直接创建一个新的组件来存放该 state,并将这一新组件置于高于共同所有者组件层级的位置。
  5. 反向数据流的建设

函数声明组件与类声明组件

  1. 函数声明
const Acomponent = (props) => {
    return (
        <h2>Hello</h2>
    )
}

// 或
function Bcomponent(props){
    return (
        <h2>Hello</h2>
    )
}

  1. 类声明
class Bcomponent extends React.Component{
    constructor(props){
        super(props)
    }
    render(){
        return (
            <h2>Hello</h2>
        )
    }
}

有状态组件与无状态组件

props

React组件必须像纯函数一样,不改变入参,也就是props不可改变。与VUE中props的不同在于,React 的 props 中始终含有属性children 与vue不同之处还在与你可以把任何东西作为props传递给子组件,vue【槽 slot】的概念在React中并不存在,都可以使用props

state

  1. 不可以直接修改state
  2. setState更新是异步的,会把多个setState合并到一起完成更新,state的再赋值是在render函数中完成。所以在开发中常见的现象是使用完setState,然后在获取state值,发现值没有改变。应该setState中挂载回调函数比如setState({}, ()=>{//get state})
  3. 数据是向下传递的,state的作用域是局部的,setState是浅合并

event,事件处理

在函数声明组件中

function ActionLink() {
  function handleClick(e) {
      e.preventDefault();
      console.log('The link was clicked.');
  }
  return (
    <a href="#" onClick={handleClick}> 
        Click me
    </a>
  );
}

在类声明组件中

class Toggle extends React.Component {
    constructor(props) {
        super(props);
        this.state = {isToggleOn: true};

        // 为了在回调中使用 `this`,这个绑定是必不可少的  
        this.handleClick = this.handleClick.bind(this); 
    }

    handleClick() {
        this.setState(state => ({      isToggleOn: !state.isToggleOn    }));
    }
    render() {
        return (
            <button onClick={this.handleClick}>
                {this.state.isToggleOn ? 'ON' : 'OFF'}
            </button>
        );
    }
}

ReactDOM.render(
  <Toggle />,
  document.getElementById('root')
);
class LoggingButton extends React.Component {
  // 此语法确保 `handleClick` 内的 `this` 已被绑定。  // 注意: 这是 *实验性* 语法。  handleClick = () => {    console.log('this is:', this);  }
  render() {
    return (
      <button onClick={this.handleClick}>
        Click me
      </button>
    );
  }
}
class LoggingButton extends React.Component {
  handleClick() {
    console.log('this is:', this);
  }

  render() {
    // 此语法确保 `handleClick` 内的 `this` 已被绑定。    return (      <button onClick={() => this.handleClick()}>        Click me
      </button>
    );
  }
}

// 此语法问题在于每次渲染 `LoggingButton` 时都会创建不同的回调函数。在大多数情况下,这没什么问题,但如果该回调函数作为 prop 传入子组件时,这些组件可能会进行额外的重新渲染。我们通常建议在构造器中绑定或使用 class fields 语法来避免这类性能问题。

表单

  1. textare重新封装
  2. select封装

均使用了value和onChange

着重说明一下受控组件与非受控组件

状态提升

将子组件的状态提升到父组件中