React文档(十四)深入JSX
根本上,JSX只是为React.createElement(component, props, ...children)函数提供语法糖。JSX代码是这样的:
<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是怎样转换成js的,你可以试一试在线Babel编译器。
指定react元素类型
JSX标签名决定了React元素的类型。
首字母大写的类型表明JSX标签涉及到一个React组件。这些标签被编译成同名变量并被引用,因此如果你使用JSX <Foo />表达式,必须在作用域之内声明Foo变量。
React必须声明
import React from 'react';
import CustomButton from './CustomButton'; function WarningButton() {
// return React.createElement(CustomButton, {color: 'red'}, null);
return <CustomButton color="red" />;
}
如果你不使用一个js打包器而是把React以一个script标签添加,那么React就已经在作用域内,作为一个全局对象。
点表示法
你也可以在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" />;
}
用户定义组件必须首字母大写
import React from 'react'; // 错误!组件名应该首字母大写:
function hello(props) {
//正确,div是有效的html标签:
return <div>Hello {props.toWhat}</div>;
} function HelloWorld() {
// 错误!React 会将小写开头的标签名认为是 HTML 原生标签:
return <hello toWhat="World" />;
}
为了解决这个问题,我们会重命名hello为Hello并且在渲染的时候使用<Hello />。
import React from 'react'; // 正确!组件名应该首字母大写:
function Hello(props) {
// 正确,div是有效的html标签:
return <div>Hello {props.toWhat}</div>;
} function HelloWorld() {
// 正确!React 能够将大写开头的标签名认为是 React 组件.
return <Hello toWhat="World" />;
}
运行时选择类型
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
有许多不同的方法在JSX里指定props。
js表达式
你可以将任意js表达式作为一个prop来传递,通过用{}包裹表达式。举个例子,在这段JSX里:
<MyComponent foo={1 + 2 + 3 + 4} />
对于MyComponent,props.foo的值会是10因为表达式1+2+3+4被求值了。
if语句和for循环在js里不算表达式,所以他们在JSX里不能直接使用。另外,你可以把它们放在周围的代码里。举个例子:
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>;
}
字符串常量
你可以将一个字符串作为一个prop来传递。下面两个JSX表达式是相等的:
<MyComponent message="hello world" />
<MyComponent message={'hello world'} />
当你传递了一个字符串字面值,该值会被解析为HTML非转义字符串。所以下面两个JSX表达式是相等的:
<MyComponent message="<3" />
<MyComponent message={'<3'} />
这个行为通常不是有重大意义的,这里提及只是因为完整性。
props默认是true
如果你不给prop传递任何值,那么它默认就是true。下面两个JSX表达式是相等的:
<MyTextBox autocomplete />
<MyTextBox autocomplete={true} />
通常情况下,我们不建议使用这个因为ES6对象简洁表示法会造成困惑。{foo}是{foo: foo}的简写形式而不是{foo: true}。这里这样用是因为这个行为和HTML的行为匹配。
扩展属性
如果你已经有了一个对象props,并且你想要把它传递给JSX,你可以使用...扩展运算符来传递整个props对象。下面两个组件是等同的:
function App1() {
return <Greeting firstName="Ben" lastName="Hector" />;
}
function App2() {
const props = {firstName: 'Ben', lastName: 'Hector'};
return <Greeting {...props} />;
}
扩展属性当你在创建通用容器的时候会很有用。然而,他们也会把你的代码弄乱,因为它们很容易传递很多不相关的props给根本不关心它们的组件。我们建议你保守地使用此语法。
JSX里的children
在同时包含起始标签和结束标签的JSX表达式里,这些标签之间的内容被作为特殊的prop来传递:props.children。传递children有几种不同的方式:
字符串常量
你可以在起始标签和结束标签之间放一个字符串props.children。这对于许多内建HTML元素来说很有用。举个例子:
<MyComponent>Hello world!</MyComponent>
这是有效的JSX,而且MyComponent组件的props.children就是那个字符串“Hello world!”。HTML未转义,所以你可以像写HTML一样来写JSX:
<div>This is valid HTML & JSX at the same time.</div>
JSX会移除一行开头的空格和结尾的空格。它也会移除空行。临近标签的新行被移除;字符串字面量中间出现的新行会被压缩成一个空格。所以下面的都会被渲染成一样的:
<div>Hello World</div> <div>
Hello World
</div> <div>
Hello
World
</div> <div> Hello World
</div>
JSX children
你可以提供更多的JSX元素来作为子元素。这样在显示嵌套的组件时会很有用:
<MyContainer>
<MyFirstComponent />
<MySecondComponent />
</MyContainer>
你也可以混合不同类型的子元素,所以你可以将JSX子组件和字符串字面量一起使用。这样使JSX像HTML的语法,就可以同时使JSX和HTML都有效:
<div>
Here is a list:
<ul>
<li>Item 1</li>
<li>Item 2</li>
</ul>
</div>
React 组件也可以通过数组的形式返回多个元素:
render() {
// 不需要使用额外的元素包裹数组中的元素
return [
// 不要忘记 key :)
<li key="A">First item</li>,
<li key="B">Second item</li>,
<li key="C">Third item</li>,
];
}
js表达式
你可以传递任意js表达式作为子元素,通过使用{}来包裹表达式。举个例子,以下表达式是等同的:
<MyComponent>foo</MyComponent>
<MyComponent>{'foo'}</MyComponent>
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>
);
}
js表达式可以与其他类型子元素混合。这样在字符串模板的场景里比较常用:
function Hello(props) {
return <div>Hello {props.addressee}!</div>;
}
函数作为子元素
// 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>
);
}
给自定义组件传递的children可以是任何东西,只要组件在渲染之前将它们转变成React可以理解的即可。这个children的用法不常见,但是它是可以运行的只要你想要扩展JSX的能力。
布尔值,null值还有undefined是被忽略的
<div />
<div></div>
<div>{false}</div>
<div>{null}</div>
<div>{undefined}</div>
<div>{true}</div>
这样根据条件是否渲染React元素就可以很有用。下面JSX渲染一个<Header />如果showHeader的值是true:
<div>
{showHeader && <Header />}
<Content />
</div>
值得注意的就是一些会被转换成false的值,类似于数字0,依然会被React渲染。举个例子,下面的代码也许不会像你期待的那样运行因为当props.messages是一个空数组的时候0将会被打印:
<div>
{props.messages.length &&
<MessageList messages={props.messages} />
}
</div>
<div>
{props.messages.length > 0 &&
<MessageList messages={props.messages} />
}
</div>
相反的,如果你想要让一个值像false,true,null或者undefined出现在输出中,你必须首先将它转换成字符串:
<div>
My JavaScript variable is {String(myVariable)}.
</div>
React文档(十四)深入JSX的更多相关文章
- React文档(四)渲染元素
元素是React应用的最小单位. 一个React元素描述了你在屏幕上所看到的东西: const element = <h1>Hello, world</h1>; 和浏览器页面中 ...
- React文档(十三)思考React
在我们的看来,React是使用js创建大型快速网站应用的首要方法.它在Facebook和Instagram的使用已经为我们展现了它自己. React的一个很好的地方就在于当你创建应用的时候它使你思考如 ...
- React文档(二十四)高阶组件
高阶组件(HOC)是React里的高级技术为了应对重用组件的逻辑.HOCs本质上不是React API的一部分.它是从React的组合性质中显露出来的模式. 具体来说,一个高阶组件就是一个获取一个组件 ...
- React文档(一)安装
React是一个灵活的可以用于各种不同项目的框架,你可以用它来写新应用,你也可以逐步将它引进已有的代码库而不用重写整个项目. 试用React 如果你想玩一玩React,那么就去CodePen上试一试. ...
- 浅谈用java解析xml文档(四)
继续接上一文,这一阵子因为公司项目加紧,导致最后一个解析xml文档的方式,还没有总结,下面总结使用dom4J解析xml. DOM4J(Document Object Model for Java) 使 ...
- [译]Selenium Python文档:四、元素定位
要定位一个页面中的元素有多中策略和方法.你可以根据实际情况选择其中最为合适的.Selenium为定位页面元素提供了下面的这些方法: find_element_by_id(使用id) find_elem ...
- react文档demo实现输入展示搜索结果列表
文档页面地址:https://doc.react-china.org/docs/thinking-in-react.html 该文档只给了具体实现思路,下面是我实现的代码. 初学react,如果有写的 ...
- Javadoc转换chm帮助文档的四种方法总结
1) 将现有的 html 文件集(比如 api) 制作成chm 文档 http://www.blogjava.net/lishunli/archive/2010/01/07/308618.html 我 ...
- React文档(二十)不使用JSX
JSX并不是使用React的一个强制需求.当你不需要在你的构造环境里设置编译那么不使用JSX会很方便. 每一个JSX元素只是调用React.createElement(componnet, props ...
随机推荐
- Unable to convert MySQL date/time value to System.DateTime问题解决方案
原因:可能是该字段(date/datetime)的值默认缺省值为:0000-00-00/0000-00-00 00:00:00,这样的数据读出来转换成System.DateTime时就会有问题: 解决 ...
- https SSL主流数字证书都有哪些格式(转载)
主流数字证书都有哪些格式? 一般来说,主流的Web服务软件,通常都基于两种基础密码库:OpenSSL和Java. Tomcat.Weblogic.JBoss等,使用Java提供的密码库.通过Java的 ...
- C++的默认构造函数
待看文章:C++ 合成默认构造函数的真相 默认构造函数指不带参数或者所有参数都有缺省值的构造函数!!! 类的默认构造函数可以使得在实例化该类的对象时不用提供参数,但是类也可以不含默认构造函数,这样在实 ...
- python进阶之 线程编程
1.进程回顾 之前已经了解了操作系统中进程的概念,程序并不能单独运行,只有将程序装载到内存中,系统为它分配资源才能运行,而这种执行的程序就称之为进程.程序和进程的区别就在于:程序是指令的集合,它是进程 ...
- 【LeetCode每天一题】Length of Last Word(字符串中最后一个单词的长度)
Given a string s consists of upper/lower-case alphabets and empty space characters ' ', return the l ...
- python_函数式编程
函数式编程是一种编程范式 (而面向过程编程和面向对象编程也都是编程范式).在面向过程编程中,我们见到过函数(function):在面向对象编程中,我们见过对象(object).函数和对象的根本目的是以 ...
- [openjudge-搜索]单词接龙
题目描述 描述 单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母,要求出以这个字母开头的最长的"龙"(每个单词都最多在"龙&q ...
- 给datagrid的日期格式化成年月日
$('#infos').datagrid({ title:'系统版本列表', iconCls:'icon-view', method:'POST', singleSelect:false, fit : ...
- nodejs cannot find module 'mysql' 问题分析
在windows平台下,测试nodejs连接mysql数据库. 首先 在控制台中安装mysql依赖包 npm install mysql 安装成功后,mysql依赖包可以在User目录中的node_m ...
- 1.1:Get Started with Unity Shaders
文章著作权归作者所有.转载请联系作者,并在文中注明出处,给出原文链接. 本系列原更新于作者的github博客,这里给出链接. 第1章开始正式进入Unity Shader的学习. 什么是Shader 本 ...