我爱编程

react 深入JSX

2018-05-26  本文已影响0人  叶绿素yls

本质上来说JSX是React.createElement(component, props, ...children)方法的语法糖。

所以我们如果使用了JSX,我们其实就是在使用React,所以我们就需要引入React

import React from 'react';

然后我们写组件的时候,自定义组件的首字母是大写的,否则表示它是一个内置组件

运行时确定类型时,遇到了一个问题,准确来说跟这个小节的内容不是特别有关,就是让我想起了一个内容,就是我们的react组件一般命名都是大写字母开头的,然后我试了一下这样的操作:

    function Hello() {
        return (
            <h1>Hello</h1>
        )
    }

    function World() {
        return (
            <h1>World</h1>
        )
    }

    const components = {
        hello:Hello,
        world:World
    };

    ReactDOM.render(<components.hello/>,document.getElementById('root'));

这样是可以正确渲染出来的,并不会报错,我觉得很奇怪,因为我们写的是<components.hello/>这样的小写的组件,它为什么不判断为是内置组件呢?我想了一下,也许是因为有.操作符存在,所以React知道它是一个自定义的组件。如果我们换一种写法:

    function Hello() {
        return (
            <h1>Hello</h1>
        )
    }

    function World() {
        return (
            <h1>World</h1>
        )
    }

    const components = {
        hello:Hello,
        world:World
    };
    const hello = components['hello'];

    ReactDOM.render(<hello/>,document.getElementById('root'));

这样写,虽然hello和上面那个例子的components.hello完全是等价的,但是React把它识别为一个普通的组件,导致报错。

不得不说React是非常聪明的。

然后回到这一小节(运行时确定类型),就是说我们不能在元素标签的类型中使用表达式,比如:<components.[this.props.type]>,这么写就是错的,如果我们要实现这种根据参数来改变组件的话,我们需要提前把它赋值给一个大写字母开头的变量,为什么要大写?我们刚说过,如果是小写,那么React就会识别为一个内置组件。最后就是这样:

const SpecificType = components[this.props.type];
return <SpecificType/>

属性的默认值如果我们没有属性赋值,只是写了出来,那么它的默认值是true

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

这里的{true}不要以为是{true: true}哈,这个{}是在JSX中使用JS的标志。

传递属性
如果我们想要把属性对象(不一定真的是传递进来的,也可以是我们加工之后的)传递其他组件,那我们可以这么写。

function App1() {
  return <Greeting firstName="Ben" lastName="Hector" />;
}

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

这样确实是非常方便的,省的我们写那些属性名啦,但是这可能让我们把过多的参数传递给某个组件,所以用的时候最好确保所有参数都是有意义的,不然有可能是代码变得混乱,谨慎使用。

子代
这个就是我们之前用到的,但是没有详细解释的一个地方。在开始标签和结束标签之间就是我们的props.children属性。

如果子代的字符串的话,props.children是移除两端的空格,中间的换行符是一个空格,内部的多个空格也是一个空格(和HTML一样)。

子代当然也可以是组件啦,我们之前就这么用过,当然,也可以是组件和字符串的结合啦,所以基本上子代可以是任何东西。props.children是一个数组按顺序包含所有的子代组件。

突然看到

render() {
  // 不需要使用额外的元素包裹数组中的元素
  return [
    // 不要忘记 key :)
    <li key="A">First item</li>,
    <li key="B">Second item</li>,
    <li key="C">Third item</li>,
  ];
}

包含在数组中的元素渲染出来可以不用元素包裹起来,这个厉害的嘛?我之前一直不知道,不过仔细想想我们之前其实已经用过了,当我们用map把一个数组转换为组件的时候,返回值就是一个数组嘛,我们也没有把它包在一个组件当中,观察还是不仔细呀。

组件还可以是一个函数哦,我们可以把一些组件的"构造函数"传递进去:),当然用法我目前还了解的不多。

在子代中,有几个情况是不渲染的,我们需要了解一下:

<div />

<div></div>

<div>{false}</div>

<div>{null}</div>

<div>{undefined}</div>

<div>{true}</div>

这个规则也是我们能够使用条件渲染的前提,但也有一些特例,我们需要注意一下,就是数字00是一个falsy值,但是有时候我们随意使用的话会出现意料之外的事情,比如

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

我们本来是想当messages数组中没有内容的时候我们就不渲染啦,但是这个表达式props.messages.length && ....的值是0,React肯定不知道我们是输出0呢,还是表示false呢,所以它肯定不能因为0表示false,而不去渲染0,那么我们很多地方其实又需要渲染出0。所以我们尽量保证我们的逻辑表达式的返回值是布尔类型的返回值。
如果我们需要输出false, null,undefined,true,我们需要先把它们转换为字符串类型。

<div>
  My JavaScript variable is {String(myVariable)}.
</div>
上一篇下一篇

猜你喜欢

热点阅读