zoukankan      html  css  js  c++  java
  • 深入 JSX

    从本质上讲,JSX 只是为 React.createElement(component, props, ...children) 函数提供的语法糖。JSX代码:

    1
    2
    3
    <MyButton color="blue" shadowSize={2}>
      Click Me
    </MyButton>

    编译后的结果为:

    1
    2
    3
    4
    5
    React.createElement(
      MyButton,
      {color: 'blue', shadowSize: 2},
      'Click Me'
    )

    如果不存在子节点,你可以使用自闭合(self-closing)格式的标签。例如:

    1
    <div className="sidebar" />

    编译为:

    1
    2
    3
    4
    5
    React.createElement(
      'div',  
      {className: 'sidebar'},
      null
    )

    可以发现对于非自定义的html标签‘div’是以字符串的形式传入的。

    在线 Babel 编译器

    指定 React 元素类型

    一个 JSX 标签的开始部分决定了 React 元素的类型。

    首字母大写的标签指示 JSX 标签是一个 React 组件。这些标签会被编译成 命名变量 的直接引用。所以如果你使用 JSX <Foo /> 表达式,那么 Foo 必须在作用域中。

    React 必须在作用域中

    因为 JSX 被编译为 React.createElement 的调用,所以 React 库必须在你 JSX 代码的作用域中。

    例如,所有的 imports 在这段代码中都是必须的,虽然 React 和 CustomButton 并有直接从 JavaScript 中引用:

    1
    2
    3
    4
    5
    6
    7
    import React from 'react';
    import CustomButton from './CustomButton';
     
    function WarningButton() {
      // return React.createElement(CustomButton, {color: 'red'}, null);
      return <CustomButton color="red" />;
    }

    如果你不使用 JavaScript 打包器,而是通过在 <script> 标签加载 React ,它已经作为一个全局 React 存在。

    对 JSX 类型使用点语法

    在 JSX 中,你也可以使用点语法引用一个 React 组件。如果你有一个单一模块(module) ,但却 导出(exports) 多个 React 组件时,这将会很方便。例如,如果 MyComponents.DatePicker是一个组件,你可以直接在 JSX 中使用它:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    import React from 'react';
     
    const MyComponents = {
      DatePicker: function DatePicker(props) {
        return <div>Imagine a {props.color} datepicker here.</div>;
      }
    }
     
    function BlueDatePicker() {
      return <MyComponents.DatePicker color="blue" />;
    }

    通过点语法,可以将具有相同类型的组件封装在一个地方,方便管理。

    用户定义组件必须以大写字母开头

    当一个元素类型以小写字母开头,它表示引用一个类似于 <div> 或者 <span> 的内置组件,会给 React.createElement 方法传递 'div' 或者 'span' 字符串。以大写字母开头的类型,类似于 <Foo />,会被编译成 React.createElement(Foo) ,对应于自定义组件 或者在 JavaScript 文件中导入的组件。

    在运行时选择类型

    不能使用一个普通的表达式作为 React 元素类型。如果你想使用普通表达式来表示元素类型,首先你需要将其赋值给大写的变量。这通常会出现在根据不同的 props 渲染不同的组件时:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    import React from 'react';
    import { PhotoStory, VideoStory } from './stories';
     
    const components = {
      photo: PhotoStory,
      video: VideoStory
    };
     
    function Story(props) {
      // 错误!JSX 类型不能是表达式
      return <components[props.storyType] story={props.story} />;
    }


    为了解决这个问题,首先需要将表达式赋值给一个以大写字母开头的变量。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    import React from 'react';
    import { PhotoStory, VideoStory } from './stories';
     
    const components = {
      photo: PhotoStory,
      video: VideoStory
    };
     
    function Story(props) {
      // 正确!JSX 类型可以是一个以大写字母开头的变量.
      const SpecificStory = components[props.storyType];
      return <SpecificStory story={props.story} />;
    }

    JSX 中的 props(属性)

    有几种不同的方式来指定 JSX 中的 props(属性) 。

    JavaScript 表达式作为 props(属性)

    常用方法:

    1
    <MyComponent foo={1 + 2 + 3 + 4} />

    对于 MyComponent 来讲,props.foo 的值为 10,因为表达式 1 + 2 + 3 + 4 会被计算估值。

    在 JavaScript 中,if 语句和 for 循环不是表达式,因此不能在 JSX 中直接使用。但你可以将他们放在附近的代码块中,例如:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    function NumberDescriber(props) {
      let description;
      if (props.number % 2 == 0) {
        description = <strong>even</strong>;
      else {
        description = <i>odd</i>;
      }
      return <div>{props.number} is an {description} number</div>;
    }

    字符串字面量

    props(属性) 默认为 “true”

    如果你没给 prop(属性) 传值,那么他默认为 true 。下面两个 JSX 表达式是等价的:

    1
    2
    3
    <MyTextBox autocomplete />
     
    <MyTextBox autocomplete={true} />

    通常情况下,不建议使用这种类型,因为这会与ES6中的对象shorthand混淆 。ES6 shorthand 中 {foo} 指的是 {foo: foo} 的简写,而不是 {foo: true} 。这种行为只是为了与 HTML 的行为相匹配。(愚人码头注:举个例子,在 HTML 中,<input type="radio" value="1" disabled /> 与 <input type="radio" value="1" disabled="true" />是等价的。JSX 中的这种行为就是为了匹配 HTML 的行为。)

    属性扩展

    如果你已经有一个 object 类型的 props,并且希望在 JSX 中传入,你可以使用扩展操作符 ... 传入整个 props 对象。这两个组件是等效的:

    1
    2
    3
    4
    5
    6
    7
    8
    function App1() {
      return <Greeting firstName="Ben" lastName="Hector" />;
    }
     
    function App2() {
      const props = {firstName: 'Ben', lastName: 'Hector'};
      return <Greeting {...props} />;
    }


    JSX Children

    通过使用 {} 包裹,你可以将任何的 JavaScript 元素而作为 children(子元素) 传递,下面表达式是等价的:

    1
    2
    3
    <MyComponent>foo</MyComponent>
     
    <MyComponent>{'foo'}</MyComponent>

    Functions(函数) 作为 Children(子元素)

    通常情况下,嵌入到 JSX 中的 JavaScript 表达式会被认为是一个字符串、React元素 或者是这些内容的一个列表。然而, props.children 类似于其他的 props(属性) ,可以被传入任何数据,而不是仅仅只是 React 可以渲染的数据。例如,如果有自定义组件,其 props.children的值可以是回调函数:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    // Calls the children callback numTimes to produce a repeated component
    function Repeat(props) {
      let items = [];
      for (let i = 0; i < props.numTimes; i++) {
        items.push(props.children(i));
      }
      return <div>{items}</div>;
    }
     
    function ListOfTenThings() {
      return (
        <Repeat numTimes={10}>
          {(index) => <div key={index}>This is item {index} in the list</div>}
        </Repeat>
      );
    }

    这个例子中,直接在Repeat组件中传了一个钩子函数进去,并且用一对{}包裹起来,在Repeat中,就可以通过props.children拿到父组件中钩子函数的返回值,并且通过加工包装成React元素。

    传递到自定义组件的 children(子元素) 可以是任何内容,只要在渲染之前组件可以将其转化为 React 能够处理的东西即可。

    Booleans, Null, 和 Undefined 被忽略

    falsenullundefined,和 true 都是有效的的 children(子元素) 。但是并不会被渲染,下面的JSX表达式渲染效果是相同的:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <div />
     
    <div></div>
     
    <div>{false}</div>
     
    <div>{null}</div>
     
    <div>{undefined}</div>
     
    <div>{true}</div>

    在有条件性渲染 React 元素时非常有用。如果 showHeader 为 true 时,<Header />会被渲染:

    1
    2
    3
    4
    <div>
      {showHeader && <Header />}
      <Content />
    </div>

    短路表达式:

    showHeader为true则往下执行,为false则中断,<Header>组件将不会被渲染。

    需要注意的是“falsy”值,例如数值 0 ,仍然会被 React 渲染。例如,这段代码不会按照你预期的发生,因为当 props.messages 是一个空数组时 0 会被打印:

    1
    2
    3
    4
    5
    <div>
      {props.messages.length &&
        <MessageList messages={props.messages} />
      }
    </div>

    要修复这个问题,确保 && 之前的表达式总是布尔值:

    1
    2
    3
    4
    5
    <div>
      {props.messages.length > 0 &&
        <MessageList messages={props.messages} />
      }
    </div>

    反过来,如果在输出中想要渲染 false ,truenull 或者 undefined ,你必须先将其转化为字符串。

  • 相关阅读:
    C#如何不使用递归实现无限层次结构的代码分享[转]
    asp.net mvc2 templates的一篇文章
    asp.net mvc Model验证总结及常用正则表达式
    关于IE的Ajax请求结果缓存的问题
    在ASP.NET MVC中如何让ASCX用户控件具有Action / Controller
    Kubernetes之Pod介绍
    Docker 之Swarm介绍
    Docker之多机网络
    Kubernetes之Pod调度
    Docker之隔离技术
  • 原文地址:https://www.cnblogs.com/cangqinglang/p/9077901.html
Copyright © 2011-2022 走看看