XML基本语法:使用XML语法的好处是标签可以任意嵌套,可以像HTML一样清晰看到DOM树状结构及其属性
const List = () => (
<div>
<Title>This is title</Title>
<ul>
<li>list item</li>
</ul>
</div>
);
· 所有标签都必须闭合,否则无法编译通过;
· 定义标签时,只允许被一个标签包裹;只有一个标签会被转译成对应的React.createElement() 调用,否则无法被转译并调用React.createElement()
const component1 = <span>name</span><a>value</a>; 报错
const component2 = <div><span>name</span><span>value</span></div>; 不报错
元素类型:JSX语法分为两种不同的元素类型
·DOM元素:HTML标签首字母小写对应DOM元素
·组件元素:而组件元素首字母大写对应组件元素
JSX注释:在一个组件的子元素位置使用注释要用 {} 包起来
const App = (
<Nav>
{
// 节点注释
}
<Person
{/* 多行注释 */}
className={style}
/>
</Nav>
);
元素属性:
JSX语法中,不论是DOM元素还是组件元素,它们都有属性。不同的是,DOM元素的属性是标准规范
属性,但是有两个例外————class和for需要转换:
·class 属性改为 className
·for 属性改为 htmlFor
Boolean属性:表单元素中,比如 disabled、require、checked 和 readOnly等,要传false时,必须使用属性表达式
<checked checked={ true } /> || <checked checked={ false } />
展开属性:
const data = { name: 'foo', value: 'bar' };
const component = <Component name={ data.name } value={data.value} />
可以写成:
const component = <Component { ...data } />
自定义 HTML 属性:如果在 JSX 中往DOM元素传入自定义属性,React是不会渲染;如果要使用HTML自定义属性要使用 data- 前缀
<div data-attr="xxx"></div> || <div data-attr={ xxx }></div>
javaScript属性表达式:属性值要使用表达式,用 {} 替换 “” 即可;
const Person = <Person name={ window.isLoggedIn ? window.name : '' }/>;
子组件也可以作为表达式使用
例1
const content = <Container>{ window.isLoggerdIn ? <Nav/> : <Login/>}</Container>;
例2
let component = <Container/>;
<Nav>{ component }</Nav>
HTML转义:React会将所有要显示到DOM的字符串转义,防止XSS攻击。以下5种办法都可以解决
·直接使用UTF-8字符;
·使用对应字符的Uncode编码查询编码;
·使用数组组装 <div>{ [ 'cc', <span>&nbso;</span>, '2018'] }</div>
·直接插入原始的HTML
·<div dangerouslySetInnerHtml={{__html: 'cc 2018'}}></div>
1、深入 JSX
JSX 其实就是 React.createElement( component, props, …children )
<MyButton color="blue" shadowSize={2}>
Click Me
</MyButton>
//编译为
React.createElement(
MyButton,
{color: 'blue', shadowSize: 2},
'Click Me'
)
2、如果没有子级组件,可以使用自闭合标签
<div className="sidebar" />
//编译为:
React.createElement(
'div',
{className: 'sidebar'},
null
);
3、指定 React 元素类型
·JSX 的标签名决定了 React 元素的类型大写开头的 JSX 标签表示一个 React 组件。这些标签将会被编译为同名变量并被引用,所以如果使用 表达式,则必须在作用域中先声明 Foo 变量。
·React 必须声明。由于 JSX 编译后会调用 React.createElement 方法,所以在 JSX 代码中必须首先声明 React 变量。
import React from 'react';
import CustomButton from './CustomButton';
function WarningButton() {
return <CustomButton color="red" />;
// 返回 React.createElement(CustomButton, {color: 'red'}, null);
};
4、点表示法: JSX 中的 “点” 表示法来引用 React 组件。可以从一个模块中导出许多 React 组件
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" />;
}
5、首字母大写
当元素类型以小写字母开头时,它表示一个内置的组件,如 ‘div’ 或 span,并将字符串 ‘div’ 或 ‘span’ 传 递给 React.createElement。
以大写字母开头的类型,如 编译为 React.createElement(Foo),并它正对应于你在 JavaScript 文件中定义或导入的组件。
import React from 'react';
function HelloWorld(props){ // 组件首字母大写
return <div>Hello {props.toWhat}</div>; // HTML标签小写
};
6、在运行时选择类型
不能用 【 表达式 】 来作为 React 元素的标签。如果想通过表达式来确定 React 元素的类型,请先将其赋值给 【 大写 】 开头的变量。
import { PhotoStory, VideoStory } from './stories';
const components = {
photo: PhotoStory,
video: VideoStory
};
function Story(props) {
// 错误!JSX 标签名不能为一个表达式。
return <components[props.storyType] story={props.story} />;
// 正确!JSX 标签名可以为 "大写" 开头的变量。
const SpecificStory = components[props.storyType];
return <SpecificStory story={props.story} />;
};
7、属性: JSX 中有几种不同的方式来指定属性
1)使用 JavaScript 表达式可以传递任何 {} 包裹的 JavaScript 表达式作为一个属性值。
<MyComponent foo={1 + 2 + 3 + 4} />
//对于 MyComponent来说, props.foo 的值为 10,这是 1 + 2 + 3 + 4 表达式计算得出的。
2)if 语句和 for 循环在 JavaScript 中不是表达式,因此它们不能直接在 JSX 中使用,可以将它们放在周围的代码中。
function NumberDescriber(props) {
let description = props.number % 2 == 0 ? <strong>even</strong> : <i>odd</i>;
return <div>{props.number} is an {description} number</div>;
};
3)字符串常量属性值传递
<MyComponent message="hello world" />
// 等价于
<MyComponent message={'hello world'} />
4)如果没有给属性传值,它默认为 true。
<MyTextBox autocomplete />
// 等价于
<MyTextBox autocomplete={true} />
8、扩展属性
如果已经有了 props 对象,并且想在 JSX 中传递它,可以使用 … 作为扩展操作符来传递整个属性对象
function App2() {
// return <Greeting firstName="Ben" lastName="Hector" />;
const props = {firstName: 'Ben', lastName: 'Hector'};
return <Greeting {...props} />;
};
11、子代
在包含开始和结束标签的 JSX 表达式中,标记之间的内容作为特殊的参数传递:props.children。有几种不同的方法来传递子代:
1)字符串常量: 在开始和结束标签之间放入一个字符串,则 props.children 就是那个字符串
<MyComponent>Hello world!</MyComponent>
这是有效的 JSX,并且 MyComponent 的 props.children 值将会直接是 "hello world!"
2)JSX 会移除空行和开始与结尾处的空格。标签邻近的新行也会被移除,字符串常量内部的换行会被压缩成一个空格
<div>Hello World</div>
<div>
Hello World
</div>
3)可以通过子代嵌入更多的 JSX 元素,对于嵌套显示组件非常有用:
<MyContainer>
<MyFirstComponent />
<MySecondComponent />
</MyContainer>
4)JSX可以混合不同类型的子元素,同时用字符串和 JSX 子元素,这是 JSX 类似 HTML 的另一种形式,这在 JSX 和 HTML 中都是有效的:
<div>
Here is a list:
<ul>
<li>Item 1</li>
<li>Item 2</li>
</ul>
</div>
5)React 组件也可以通过数组的形式返回多个元素
render() {
// 不需要使用额外的元素包裹数组中的元素
return [
// 不要忘记 key :)
<li key="A">First item</li>,
<li key="B">Second item</li>,
<li key="C">Third item</li>,
];
}
6)JavaScript 表达式,可以将任何 {} 包裹的 JavaScript 表达式作为子代传递,可以渲染任意长度的 JSX 表达式的列表
// 例1
<MyComponent>foo</MyComponent>
<MyComponent>{'foo'}</MyComponent>
// 例2
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>
);
};
7)JavaScript 表达式可以与其他类型的子代混合使用,通常用于字符串模板
function Hello(props) {
// Hello {props.addressee} 混合使用
return <div>Hello {props.addressee}!</div>;
};
8)函数,通常情况下插入 JSX 中的 JavaScript 表达式将被认作字符串、React 元素或这些内容的列表。然而,props.children 可以像其它属性一样传递任何数据,而不仅仅是 React 元素。
//例如,如果使用自定义组件,则可以将调用 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>
);
};
//传递给自定义组件的子代可以是任何元素,只要该组件在 React 渲染前将其转
换成 React 能够理解的东西
9)布尔值、Null 和 Undefined 被忽略。false、null、undefined 和 true 都是有效的子代,但它们不会直接被渲染,根据条件来确定是否渲染React元素
// 例1
<div />
<div></div>
<div>{false}</div>
<div>{null}</div>
<div>{undefined}</div>
<div>{true}</div>
// 例2
<div>
{showHeader && <Header />}
<Content />
</div>
10)JavaScript 中的一些 “falsy” 值(比如数字0),它们依然会被渲染,要解决这个问题,确保 && 前面的表达式始终为布尔值:
<div>
{
props.messages.length > 0 && <MessageList messages={ props.messages } />
}
</div>
11)如果让类似 false、true、null 或 undefined 出现在输出中,你必须先把它转换成字符串
<div>
My JavaScript variable is { String( myVariable ) }
</div>