一. React深入 JSX

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

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

编译为:

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

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

<div className="sidebar" />

可以编译为:

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

一. 指定React元素类型

一个JSX标签的开始决定了React元素的类型,首字母大写的标签指示JSX标签是一个React组件,这些标签会被编译成命名变量的直接引用。

1.1 React必须在作用域中

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

1.2 对JSX类型使用点语法

在 JSX 中,你也可以使用点语法引用一个 React 组件。如果你有一个单一模块(module) ,但却导出 (exports) 多个 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" />;
}
1.3 用户定义组件必须以大写字母开头

当一个元素类型以小写字母开头,他会认为这个锇元素是一个HTML标签,类似<div>或者<span>。所以一个组件必须以大写字母开头的方式命名。如果已经有一小写字母开头的组件,需要在使用时修改成大写字母开头。

1.4 在运行时选择类型

不能使用一个普通的表达式作为 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} />;
}

二. JSX 中的 props(属性)

2.1 JavaScript 表达式作为props(属性)

可以传递任何一个用 {} 包裹的 JavaScript 表达式作为 props(属性)。
在JavaScript中,iffor不是表达式,因此不能直接在JSX中使用,但是可以放在附近的代码块中。

字符串字面量

可以传入一个字符串作为一个props(属性),当你传递一个字符串面量时,如果其值是为转移的HTML,那么一下两个JSX表达式是等效的:

<MyComponent message="&lt;3" />
<MyComponent message={'<3'} />
2.2 props(属性)默认为“true”

如果没给prop(属性)传值,那么默认的就为true。如下所示:

<MyTextBox autocomplete />
<MyTextBox autocomplete={true} />
属性扩展

如果已经有一个object类型的props,并且希望在JSX中传入,那么可以使用扩展操作符...传入整个props对象。

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

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

注意:当在创建一个一般容器时,这样的方法非常有用。然而这可能会传递一些不相关的props(属性)给组件,而这些组件并不需要这些props。因此应当谨慎使用该语法。

三. JSX中的children

传递children时,JSX会删除每行开头和结尾的空格,并且也会删除空行。邻接标签的空行也会被移除,字符串之间的空格会被压缩成一个空格,因此下面四种传递字符串的渲染效果都是相同的:

<div>Hello World</div>

<div>
  Hello World
</div>

<div>
  Hello
  World
</div>

<div>

  Hello World
</div>
3.1 JSX Children

可以提供多个JSX元素作为children。这对显示嵌套组件非常有用。

<MyContainer>
  <MyFirstComponent />
  <MySecondComponent />
</MyContainer>

注:React组件不能返回多个React元素,但是单个JSX表达式可以有多个子元素。

3.2 JavaScript 表达式作为 Children(子元素)

通过使用 {} 包裹,你可以将任何的 JavaScript 元素而作为 children(子元素) 传递。
对于渲染长度不定的JSX表达式非常有效,例如:

function Item(props) {
  return <li>{props.message}</li>;
}

function TodoList() {
  const todos = ['finish doc', 'submit pr', 'nag dan to review'];
  return (
    <ul>
      {todos.map((message)=><Item key={message} message={message}>)}
    </ul>
  );
}
3.3 Functions(函数) 作为 Children(子元素)

如果有自定义组件,props.children的值可以是回调函数:

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>
  );
}
3.3 Booleans,Null和Undefined被忽略

falsenullundefined,和 true 都是有效的的 children(子元素) 。但是并不会被渲染,在有条件性渲染React元素时非常有用,如下所示:

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

注意:需要注意的是"falsy"值,例如数值0,仍然会被React渲染,要修复这个问题,要确保&&之前的表达式总是布尔值。

反过来,如果想在输出中渲染falsenullundefined,和 true,必须现将其转化为字符串

<div>
  My JavaScript variable is {String(myVariable)}.
</div>
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,539评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,911评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,337评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,723评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,795评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,762评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,742评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,508评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,954评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,247评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,404评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,104评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,736评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,352评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,557评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,371评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,292评论 2 352

推荐阅读更多精彩内容

  • 3. JSX JSX是对JavaScript语言的一个扩展语法, 用于生产React“元素”,建议在描述UI的时候...
    pixels阅读 2,818评论 0 24
  • 以下内容是我在学习和研究React时,对React的特性、重点和注意事项的提取、精练和总结,可以做为React特性...
    科研者阅读 8,229评论 2 21
  • HTML模版 之后出现的React代码嵌套入模版中。 1. Hello world 这段代码将一个一级标题插入到指...
    ryanho84阅读 6,229评论 0 9
  • 深入JSX date:20170412笔记原文其实JSX是React.createElement(componen...
    gaoer1938阅读 8,057评论 2 35
  • React Native是基于React的,在开发React Native过程中少不了的需要用到React方面的知...
    亓凡阅读 1,466评论 1 4