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 ...other
object 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只会在showHeader
为true
时渲染<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
上面。
react基础篇五的更多相关文章
- docker+k8s基础篇五
Docker+K8s基础篇(五) service资源介绍 A:service资源的工作特性 service的使用 A:service字段介绍 B:ClusterIP的简单使用 C:NodePort的简 ...
- react 基础篇 #2 create-react-app
1. 介绍 在开发react应用时,应该没有人用传统的方法引入react的源文件(js),然后在html编辑吧. 大家都是用webpack + es6来结合react开发前端应用. 这个时候,我们可以 ...
- [react 基础篇]——React.createClass()方法同时创建多个组件类
react 组件 React 允许将代码封装成组件(component),然后像插入普通 HTML 标签一样,在网页中插入这个组件.React.createClass 方法就用于生成一个组件类 一个组 ...
- React基础篇 (1)-- render&components
render 基础用法 //1.创建虚拟DOM元素对象 var vDom=<h1>hello wold!</h1> //2.渲染 ReactDOM.render(vDom,do ...
- react基础篇入门组件
讲述一下React: 1.声明式设计-React采用声明范式,可以轻松描述应用 2.高效-React通过DOM模型,最大限度的减少dom的交互 3.灵活-React可以与已知的库或框架很好的配合 4. ...
- React基础篇 - 02.JSX 简介
JSX 简介 请观察下面的变量声明: const element = <h1>Hello, world!</h1>; 这种看起来可能有些奇怪的标签语法既不是字符串也不是HTML ...
- C#基础篇五值类型和引用类型
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace P01M ...
- Hybrid APP基础篇(五)->JSBridge实现示例
说明 JSBridge实现示例 目录 前言 参考来源 楔子 JS实现部分 说明 实现 Android实现部分 说明 JSBridge类 实现 Callback类 实现 Webview容器关键代码 实现 ...
- React基础篇 (3)-- 生命周期
生命周期是react中的重要部分,理解它有助于我们更合理的书写逻辑. 组件的生命周期可分成三个状态: Mounting:已插入真实 DOM Updating:正在被重新渲染 Unmounting:已移 ...
随机推荐
- ActiveMQ学习总结(10)——ActiveMQ采用Spring注解方式发送和监听
对于ActiveMQ消息的发送,原声的api操作繁琐,而且如果不进行二次封装,打开关闭会话以及各种创建操作也是够够的了.那么,Spring提供了一个很方便的去收发消息的框架,spring jms.整合 ...
- nyoj_915_+-字符串_201402261520
+-字符串 时间限制:1000 ms | 内存限制:65535 KB 难度:1 描述 Shiva得到了两个只有加号和减号的字符串,字串长度相同.Shiva一次可以把一个加号和 ...
- [bzoj4530][Bjoi2014]大融合_LCT
大融合 bzoj-4530 Bjoi-2014 题目大意:n个点,m个操作,支持:两点连边:查询两点负载:负载.边(x,y)的负载就是将(x,y)这条边断掉后能和x联通的点的数量乘以能和y联通的点的数 ...
- 阿伦 凯 Alan Kay 面向对象编程思想创始人
The best way to predict the future is to invent it. 预测未来最好的办法就是创造它.
- VB.NET机房收费 & 抽象工厂模式
学习设计模式的时候,提到了一个专门訪问数据库的模式-抽象工厂模式,记得当时举样例理解的时候并未设计到数据库,仅仅是大概了了解了一下,如今对于机房收费系统涉及到了数据库的管理,借此机会好好学习一下.用常 ...
- 全栈JavaScript之路(十)学习 DocumentFragment 类型 节点
DocumentFragment 类型节点,代表一个文档片段,是一种轻量级的'文档' 对象.能够包括其他类型节点,并有能力訪问.操作当中的节点,可是在文档中没有文档标记,相当于是一个页面不可见的容器. ...
- Navicat 提示Cannot create oci environment 解决方式
一直在使用Navicat,这是一个数据库client软件.能连接多种不同类型的数据库,给我们的日常的工作带来了不少的便捷.近期.我在电脑上安装了orcale,然后,Navicat就莫名其妙的不能连接o ...
- Java怎样获取Content-Type的文件类型Mime Type
在Http请求中.有时须要知道Content-Type类型,尤其是上传文件时.更为重要.尽管有些办法可以解决,但都不太准确或者繁琐,索性我发现一个开源的类库可以解决相对完美的解决问题,它就是jMime ...
- 多级联动系列——ajax调用XML实现三级联动
ajax 使用起来特别的方便,再也不操心浏览器兼容问题了.用ajax调用XML页面中的内容,来生成三级联动,OK废话不多说,跟着我一步步写吧. 首先写一个XML文件.data.xml <?xml ...
- HDU1010-奇偶剪枝(DFS)
题目链接:Tempter of the Bone 第一次做剪枝的题目,剪枝,说实话研究的时间不短.好像没什么实质性的进展,遇到题目.绝对有会无从下手的感觉,剪枝越来越神奇了. .. . HDU1010 ...