React文档漫步-核心概念

JSX

const element1 = <h1>Hello, world!</h1>;
const name = 'Josh Perez';
const element2 = <h1>Hello, {name}</h1>;
  • 在 JSX 语法中,你可以在大括号内放置任何有效的 JavaScript 表达式

  • JSX本身也是一个表达式

  • 指定属性采用大驼峰

  • Babel 会把 JSX 转译成一个名为 React.createElement() 函数调用,返回一个对象。

  • 返回的对象我们称为React元素

    const element = (
      <h1 className="greeting">
        Hello, world!
      </h1>
    );
    // 等效
    const element = React.createElement(
      'h1',
      {className: 'greeting'},
      'Hello, world!'
    );
    // 实际上它创建了一个这样的对象。注意:这是简化过的结构
    const element = {
      type: 'h1',
      props: {
        className: 'greeting',
        children: 'Hello, world!'
      }
    };
    

元素渲染

  • React 元素是不可变对象。一旦被创建,你就无法更改它的子元素或者属性。
  • 尽管每一秒都会新建一个描述整个 UI 树的元素,React DOM 只会更新实际改变了的内容

组件&props

组件类似js函数:接收任意的props,返回React元素。

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}
class Welcome extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}</h1>;
  }
}
  • 组件名称必须以大写字母开头
  • 建议从组件自身的角度命名 props,而不是依赖于调用组件的上下文命名。
  • 所有 React 组件都必须像纯函数一样保护它们的 props 不被更改。

State&生命周期

  • 不要直接修改State
  • State是异步的
  • State更新会被浅合并
  • 数据是向下流动的。
    • 如果你把一个以组件构成的树想象成一个 props 的数据瀑布的话,那么每一个组件的 state 就像是在任意一点上给瀑布增加额外的水源,但是它只能向下流动。

事件处理

  • 事件命名采用小驼峰式

  • JSX里事件需要传入一个函数

    • // HTML
      <button onclick="activateLasers()">
        Activate Lasers
      </button>
      
    • // jsx
      <button onClick={activateLasers}>
        Activate Lasers
      </button>
      
  • 阻止表单的默认提交行为

    • // HTML
      <form onsubmit="console.log('You clicked submit.'); return false">
        <button type="submit">Submit</button>
      </form>
      
    • function Form() {
        function handleSubmit(e) {
          e.preventDefault();
          console.log('You clicked submit.');
        }
      
        return (
          <form onSubmit={handleSubmit}>
            <button type="submit">Submit</button>
          </form>
        );
      }
      
  • class语法记得绑定this

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

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

  handleClick() {
    this.setState(prevState => ({
      isToggleOn: !prevState.isToggleOn
    }));
  }

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

列表&Key

  • key 帮助 React 识别哪些元素改变了,因此应当给数组中的每一个元素赋予一个确定的标识。
  • 一个元素的 key 最好是这个元素在列表中拥有的一个独一无二的字符串
  • 不建议使用索引来用作 key 值
  • key 在其兄弟节点之间应该是独一无二的,不需要全局唯一

组合&继承

1. 包含关系

// 使用children传递组件
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>
  );
}

// 使用参数传递组件
function SplitPane(props) {
  return (
    <div className="SplitPane">
      <div className="SplitPane-left">
        {props.left}
      </div>
      <div className="SplitPane-right">
        {props.right}
      </div>
    </div>
  );
}

function App() {
  return (
    <SplitPane
      left={
        <Contacts />
      }
      right={
        <Chat />
      } />
  );
}

2.特例关系

// WelcomeDialog 可以说是 Dialog 的特殊实例。
function Dialog(props) {
  return (
    <FancyBorder color="blue">
      <h1 className="Dialog-title">
        {props.title}
      </h1>
      <p className="Dialog-message">
        {props.message}
      </p>
    </FancyBorder>
  );
}

function WelcomeDialog() {
  return (
    <Dialog
      title="Welcome"
      message="Thank you for visiting our spacecraft!" />
  );
}

React哲学

  1. 前提:设计稿,接口
  2. 第一步:UI划分组件层级。
    1. 一个组件原则上只能负责一个功能。
    2. 如果你的模型设计得恰当,UI(或者说组件结构)便会与数据模型一一对应
  3. 第二步:写React静态页面
    1. 编写一个应用的静态版本时,往往要编写大量代码,而不需要考虑太多交互细节;添加交互功能时则要考虑大量细节,而不需要编写太多代码。所以,将这两个过程分开进行更为合适。
    2. 需要创建一些会重用其他组件的组件,然后通过 props 传入所需的数据
    3. 完全不应该使用 state 构建静态版本
    4. 对于较为大型的项目来说,自下而上地构建,并同时为低层组件编写测试是更加简单的方式。
  4. 第三步:确定UI state 的最小完整表示
    1. state 用来触发数据模型改变,使UI具备交互功能
    2. 需要找出应用所需的 state 的最小表示,并根据需要计算出其他所有数据。
      1. 该数据是否是由父组件通过 props 传递而来的?如果是,那它应该不是 state。
      2. 该数据是否随时间的推移而保持不变?如果是,那它应该也不是 state。
      3. 你能否根据其他 state 或 props 计算出该数据的值?如果是,那它也不是 state。
  5. 第四步:确定 state 的位置
    1. 找到根据这个 state 进行渲染的所有组件。
    2. 找到他们的共同所有者(common owner)组件(在组件层级上高于所有需要该 state 的组件)。
    3. 该共同所有者组件或者比它层级更高的组件应该拥有该 state。
    4. 如果你找不到一个合适的位置来存放该 state,就可以直接创建一个新的组件来存放该 state,并将这一新组件置于高于共同所有者组件层级的位置。
  6. 第五步:添加反向数据流。显式声明监听函数,并用callback调用setState(),来更新应用。
posted @ 2022-07-24 15:00  沧浪浊兮  阅读(35)  评论(0编辑  收藏  举报