zoukankan      html  css  js  c++  java
  • react基础篇五

    再看JSX

    本质上来讲,JSX 只是为 React.createElement(component, props, ...children) 方法提供的语法糖。比如下面的代码:

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

    编译为:

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

    如果没有子代,你还可以使用自闭合标签,比如:

    <div className="sidebar" />

    编译为:

    React.createElement(
      'div',
      {className: 'sidebar'},
      null
    )

    如果你想彻底验证 JSX 是如何转换为 JavaScript 的,你可以尝试 在线 Babel 编译器.

    React 必须在作用域中

    由于 JSX 编译成React.createElement方法的调用,所以在你的 JSX 代码中,React库必须也始终在作用域中。

    比如,下面两个导入都是必须的尽管 React 和 CustomButton 都没有在代码中被直接调用。

    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 组件。你可以方便地从一个模块中导出许多 React 组件。例如,有一个名为 MyComponents.DatePicker 的组件,你可以直接在 JSX 中使用它:

    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>,将导致字符串 'div' 或 'span' 传递给 React.createElement。 以大写字母开头的类型,如 <Foo /> 编译为 React.createElement(Foo),并且它正对应于你在 JavaScript 文件中定义或导入的组件。

    在运行时选择类型

    你不能使用一个通用的表达式来作为 React 元素的标签。如果你的确想使用一个通用的表达式来确定 React 元素的类型,请先将其赋值给大写开头的变量。这种情况一般发生于当你想基于属性值渲染不同的组件时:

    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} />;
    }

    要解决这个问题,我们需要先将类型赋值给大写开头的变量。(组件一定是大写开头)

    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} />;
    }

    props

    属性默认为“True”

    如果你没有给属性传值,它默认为 true。因此下面两个 JSX 是等价的:

    <MyTextBox autocomplete />
    
    <MyTextBox autocomplete={true} />

    一般情况下,我们不建议这样使用,因为它会与 ES6 对象简洁表示法 混淆。比如 {foo} 是 {foo: foo} 的简写,而不是 {foo: true}。这里能这样用,是因为它符合 HTML 的做法。

    展开属性(传参)

    如果你已经有了个 props 对象,并且想在 JSX 中传递它,你可以使用 ... 作为“展开(spread)”操作符来传递整个属性对象。下面两个组件是等效的:

    function App1() {
      return <Greeting firstName="Ben" lastName="Hector" />;
    }
    
    function App2() {
      const props = {firstName: 'Ben', lastName: 'Hector'};
      return <Greeting {...props} />;
    }

    You can also pick specific props that your component will consume while passing all other props using the spread operator.

    const Button = props => {
      const { kind, ...other } = props;
      const className = kind === "primary" ? "PrimaryButton" : "SecondaryButton";
      return <button className={className} {...other} />;
    };
    
    const App = () => {
      return (
        <div>
          <Button kind="primary" onClick={() => console.log("clicked!")}>
            Hello World!
          </Button>
        </div>
      );
    };

    In the example above, the kind prop is safely consumed and is not passed on to the <button> element in the DOM. All other props are passed via the ...otherobject making this component really flexible. You can see that it passes an onClick and children props.

    展开属性非常有用。但是他们也容易传递不必要的属性给组件,而组件并不需要这些多余属性。或者传递无效的HTML熟悉给DOM。我们建议你谨慎使用此语法。

    函数作为子代

    通常情况下,插入 JSX 中的 JavaScript 表达式将被认作字符串、React 元素或这些的一个列表。然而props.children 可以像其它属性一样传递任何种类的数据,而不仅仅是 React 知道如何去渲染的数据种类。例如,如果你有一个自定义组件,你能使其取一个回调作为props.children:(children就是一个参数而已可以将dom对象传入)

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

    传递给自定义组件的子代可以是任何东西,只要该组件在 React 渲染前将其转换成 React 能够理解的东西。这个用法并不常见,但当你想扩展 JSX 时可以使用。

    布尔值、Null 和 Undefined 被忽略

    这在根据条件来确定是否渲染React元素时非常有用。以下的JSX只会在showHeadertrue时渲染<Header />组件。

    <div>
      {showHeader && <Header />}
      <Content />
    </div>

    一个告诫是JavaScript中的一些 “falsy” 值(比如数字0),它们依然会被React渲染。例如,下面的代码不会像你预期的那样运行,因为当 props.message 为空数组时,它会打印0:

    <div>
      {props.messages.length &&
        <MessageList messages={props.messages} />
      }
    </div>

    要解决这个问题,请确保 && 前面的表达式始终为布尔值:

    <div>
      {props.messages.length > 0 &&
        <MessageList messages={props.messages} />
      }
    </div>

    限制单个子代

    使用 PropTypes.element 你可以指定只传递一个子代

    import PropTypes from 'prop-types';
    
    class MyComponent extends React.Component {
      render() {
        // This must be exactly one element or it will warn.
        const children = this.props.children;
        return (
          <div>
            {children}
          </div>
        );
      }
    }
    
    MyComponent.propTypes = {
      children: PropTypes.element.isRequired
    };

    属性默认值

    你可以通过配置 defaultProps 为 props定义默认值:

    class Greeting extends React.Component {
      render() {
        return (
          <h1>Hello, {this.props.name}</h1>
        );
      }
    }
    
    // 为属性指定默认值:
    Greeting.defaultProps = {
      name: 'Stranger'
    };
    
    // 渲染 "Hello, Stranger":
    ReactDOM.render(
      <Greeting />,
      document.getElementById('example')
    );

    如果你在使用像 transform-class-properties 的 Babel 转换器,你也可以在React 组件类中声明 defaultProps 作为静态属性。这个语法还没有最终通过,在浏览器中需要一步编译工作。更多信息,查看类字段提议

    class Greeting extends React.Component {
      static defaultProps = {
        name: 'stranger'
      }
    
      render() {
        return (
          <div>Hello, {this.props.name}</div>
        )
      }
    }

    defaultProps 用来确保 this.props.name 在父组件没有特别指定的情况下,有一个初始值。类型检查发生在 defaultProps 赋值之后,所以类型检查也会应用在 defaultProps 上面。

  • 相关阅读:
    request 请求 转 json
    图片缩略图 简单应用
    文件压缩下载 和 解压缩并解析
    简单 map 与 xml 互转
    SVN+vs2017
    cordova生成签名的APK
    海关 实时数据 企业联调接口 总结
    vs2017远程调试
    X509证书 指定了无效的提供程序类型 System.Security.Cryptography.CryptographicException 错误解决方法
    微信公众号开发 ,redirect_uri域名还是与后台配置不一致
  • 原文地址:https://www.cnblogs.com/airfand/p/10679409.html
Copyright © 2011-2022 走看看