美文网首页React.js程序员
react 官方文档学习笔记

react 官方文档学习笔记

作者: Bruce陈 | 来源:发表于2017-07-04 09:47 被阅读0次

本文是我在重新学习react文档时针对自己之前忽视或易被忽视细节的整理,对应的React版本v15.6.1。原文react官方文档
这篇文章初衷是帮助自己加深记忆和理解,如有我理解不对的地方,还请大家指正。

Hello World

ReactDOM.render(
  <h1>Hello, world!</h1>,
  document.getElementById('root')
);

JSX

  • JSX被赋值给一个变量或常量是可以在两端加入小括号来调整格式
const element = (
  <h1>
    Hello, {formatName(user)}!
  </h1>
);
  • JSX中可以运行js,需要在两端加入大括号
  • JSX表达式就像一种JS对象一样,可以被赋值,传参,return
  • JSX中可以设置属性,也可以用大括号将JS表达式写入属性中
  • 空标签,需要最后用/>结尾
  • class需要写为className,tabindex需要写为tabIndex
  • JSX最后通过React.createElement将JSX转化为React Object

渲染Element

  • element不同于组件
  • element是一成不变的,一旦元素被创建,就不能修改它的children和属性了,代表了某一时刻UI的快照
  • 截止目前,更新UI的方法只有新建一个element然后再次传入React.render
  • React app大多只调用一次ReactDOM.render
  • React只在必要时更新DOM,即使每次均传入一个新的元素到React.render,也只有其中被更新的子元素会被修改。

组件和属性(props)

  • 组件定义可以通过函数或者类
function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}
class Welcome extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}</h1>;
  }
}

基于class会有额外的特性,后续展开

  • 自定义组件应大写首字母
  • 组件使用需要组件定义在作用域内
  • 组件之间可以互相封装,组件最外层一定要返回一个单独的根元素
  • 属性是只可读的

State和生命周期

  • 相对于props,state是私有且完全被组件控制的
  • 如果定义组件的state,就需要采用类的方法整理组件(class语法),这里需要注意基于class开发后,props需要通过this.props读取,state同样通过this.state读取
  • 需要给组件加入构造函数来初始化状态
constructor(props) {
    super(props);
    this.state = {date: new Date()};
}

注意由于继承时子类没有自己的this,一定要调用super(props)

  • 组件的生命周期中,初始化被称为mounting,卸载被称为unmounting,所以可以在组件的这两个阶段定义方法componentDidMountcpmponentWillUnmount
  • 组件的一些相关属性可以直接保存在this上,当然这些属性应该是不和渲染直接相关的,否则就要保存在this.state
  • 组件的一些方法也可以像render一样定于与class上,之后通过this.XXX()调用
  • 除去render之外的方法中可以通过
this.setState({
    date: new Date()
});

从而来修改state

  • 不要直接修改state,这不会重新触发渲染,一定采取setStete的方法,只有在constructor中才可以通过this.state来初始化state
  • state和props的改动可能是异步更新的,所以如果需要基于前一状态来更新state,应该通过如下方式
this.setState((prevState, props) => ({
  counter: prevState.counter + props.increment
}));
  • setState函数内部是在marge的,被改动的会被更新,未改动的会被保存
  • 组件的state应该是封装在内部的,只有当他选择传递时才可以暴露在外,比如父组件可以通过设置子组件属性的方式与子组件通信,这是一种自顶向下的数据流
<FormattedDate date={this.state.date} />

事件绑定

  • 可以通过如下方式进行事件绑定
<button onClick={activateLasers}>
  Activate Lasers
</button>

但是不能通过return false;来阻止默认行为发生,一定要调用e.preventDefault();实现

  • 事件绑定触发的方法可以定义在class内,之后通过this访问
  • 如果事件绑定的函数中有对this的访问,那么需要在constructor中进行this的绑定
this.handleClick = this.handleClick.bind(this);

原因在于我们是通过onClick={this.handleClick}读取的函数方法,而不是this.handleClick()
方法二是借助property initializer syntax,如下(create-react-app中可用)

// This syntax ensures `this` is bound within handleClick.
// Warning: this is *experimental* syntax.
handleClick = () => {
  console.log('this is:', this);
}

方法三基于箭头函数,因为箭头函数的作用域在定义时被决定

class LoggingButton extends React.Component {
  handleClick() {
    console.log('this is:', this);
  }

  render() {
    // This syntax ensures `this` is bound within handleClick
    return (
      <button onClick={(e) => this.handleClick(e)}>
        Click me
      </button>
    );
  }
}

方法三中每次渲染时会绑定不同的函数,因而可能触发组件的再次渲染,因而推荐方法一、二

条件渲染

  • 可以根据state和props进行判断,return出不同的渲染结果
  • 可以将不同JSX保存在变量中,之后在return中调用这个变量
  • 可以通过短路运算符&&来写出更加简明的条件渲染
function Mailbox(props) {
  const unreadMessages = props.unreadMessages;
  return (
    <div>
      <h1>Hello!</h1>
      {unreadMessages.length > 0 &&
        <h2>
          You have {unreadMessages.length} unread messages.
        </h2>
      }
    </div>
  );
}
  • 也可以通过三目运算符完成条件渲染
  • 如果希望一个组件不显示,可以在render中return null。这只使组件不显示,不会影响其生命周期

Lists and Keys

  • 在JSX中用{}包裹一个数组元素(元素用JSX表示),那么就可以渲染出一个元素list。其中每个元素可以再添加属性,如key。如果希望渲染一个list的元素,一定要加上key属性来帮助react区分元素。list中的key一定要不同
    key最好选用不同的字符串,不建议采用index进行区分
const todoItems = todos.map((todo) =>
  <li key={todo.id}>
    {todo.text}
  </li>
);
  • key应该在被从array通过map得到list时添加,而不是在list中每一项的子元素上再添加
  • key在通过数组渲染的siblings之间应该是互不相同的,但是不用组的siblings之间是可以存在重复的
  • key只是为了帮助React的暗示信息,并不会真的被传送到组件上,如组件需要,可以再加入其它props

Forms

Controlled Components

  • 指值被React所控制的输入表单元素
  • 表单元素的value一旦在JSX中被设置,如
<input type="text" value={this.state.value} onChange={this.handleChange} />

那么它所显示的值就是this.state.value,通过onChange中绑定的函数修改this.state.value,从而控制这个表单元素输入的值,让其随用户输入而更新

  • 用户的输入时对表单元素的修改和有效性检测等,此时就被直接控制了
  • select组件,通过设置value与某个option中的value相同,来表示这个option被选中
  • 对于一个组件内的多个表单元素,可以通过设置name,在一个函数通过e.target.name来区分更改state,这样就可以用一个函数来监听多个元素的输入
  • uncontrolled component在某些情境下,可能是更灵活的针对表单的方案

Lifting State Up

对于一个在多个组件间需要同步的数据,可以将其提升到最近的共同祖先组件的stete上,之后通过props传递给各个子组件,使各个子组件中取到同一个值。也是是自顶向下数据流思想的一种体现

Composition vs Inheritance(组成与继承)

  • 类似boxes模式的组件,可以通过children属性访问在其内部写入的其他通过JSX表达的组件
function FancyBorder(props) {
  return (
    <div className={'FancyBorder FancyBorder-' + props.color}>
      {props.children}
    </div>
  );
}
function WelcomeDialog() {
  return (
    <FancyBorder color="blue">
      <h1 className="Dialog-title">
        Welcome
      </h1>
      <p className="Dialog-message">
        Thank you for visiting our spacecraft!
      </p>
    </FancyBorder>
  );
}
  • 一些组件可以理解为一些通用组件的特例化,这种特殊组件可以返回被设置了特有props值得通用组件实现
  • 综上,用组合的方法开发各个组件是推荐的,继承并不十分实用

Thinking in React

  • 基于React开发,可以先从静态页面入手,此时不应引入state,因为state应面向交互
  • 衡量是否采用state三个角度:是否来自父组件的传递,是否总是不变的,是否可以通过其他state或者props得到
  • React数据流除自顶向下,同样可以自下向上,这需要将在顶层组件中设置修改顶层state的方法,之后将这个方法作为属性传入子组件,子组件调用这个方法,即可修改顶层组件中的state

相关文章

网友评论

    本文标题:react 官方文档学习笔记

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