Fullstack Rect 笔记-JSX
2018-08-10 小文字JSX书写Tips
JSX =》JavaScript Syntax Extension
=》JS语法糖扩展
使用JSX可以大幅提高代码书写的简洁性,特别是在多层级的组件嵌套书写是产生的层级问题。
- JSX中写注释
{/*
注释内容
*/}
- JSX Boolean属性
bool属性需要用{}
包括,类似的,变量值也需要用{}
包裹
<input name='Name' disabled={true} />
- JSX 条件表达式
通过&&
可选的输出内容,而不需要?:
const renderAdminMenu = function() {
return (<MenuLink to="/users">User accounts</MenuLink>)
}
const userLevel = this.props.userLevel; return (
<ul>
<li>Menu</li>
{userLevel === 'admin' && renderAdminMenu()}
</ul>
)
- JSX透传属性语法
JSX可以透传属性,已更简单书写来赋值属性{...props}
{/* 常规写法,将msg和recipent赋值给Component组件的属性 */}
const props = {msg: "Hello", recipient: "World"}
<Component msg={"Hello"} recipient={"World"} />
<Component {...props} />
<!-- essentially the same as this: -->
<Component msg={"Hello"} recipient={"World"} />
- class & className区分
JSX中使用className来指定class
<!-- Same as <div class='box'></div> -->
<div className='box'></div>
var cssNames = ['box', 'alert']
// and use the array of cssNames in JSX
(<div className={cssNames.join(' ')}></div>)
- classnames模块
支持class的动态控制,为true的class生效
class App extends React.Component {
render() {
const klass = classnames({
box: true, // always apply the box class
alert: this.props.isAlert, // if a prop is set
severity: this.state.onHighAlert, // with a state
timed: false // never apply this class
});
return (<div className={klass} />)
}
}
- 自定义属性
data-anything
为html标准标签添加自定义的属性需要以data-
开头,自定义组件则不受这个约束
<div className='box' data-dismissible={true} />
<span data-highlight={true} />
<Message dismissible={true} />
<Note highlight={true} />
高阶组件配置
- PropTypes属性类型
通过prop-types
包可以对属性类型做限制,同时提供一个优良的说明
class Map extends React.Component {
static propTypes = {
lat: PropTypes.number,
lng: PropTypes.number,
zoom: PropTypes.number,
place: PropTypes.object,
markers: PropTypes.array,
};
const Map = React.createClass({
propTypes: {
lat: PropTypes.number,
lng: PropTypes.number // ...
},
})
- props默认值
class Counter extends React.Component { static defaultProps = {
initialValue: 1
};
// ...
};
<!-- 等价 -->
<Counter />
<Counter initialValue={1} />
- 全局上下文共享属性
通过全局的context可以实现属性数据共享,避免将数据从顶层组件一层层传递赋值,但是要尽量避免滥用context
;
第一步:在父组件定义childContextTypes和getChildContext;
第二步:在子组件定义;
第三步:在子组件中通过this.context.xxx可以获取共享的数据;
// 父组件
class Messages extends React.Component { // ...
static childContextTypes = {
users: PropTypes.array,
userMap: PropTypes.object,
};
// ...
getChildContext() {
return {
users: this.getUsers(),
userMap: this.getUserMap(),
};
}
// ...
}
// 子组件
class ThreadList extends React.Component {
// ...
static contextTypes = {
users: PropTypes.array,
};
// ...
}
class ChatWindow extends React.Component { // ...
static contextTypes = {
userMap: PropTypes.object,
};
// ...
}
- 自定义嵌套组件
自定义的组件也可以是类似div这种支持内部嵌套组件;要实现这种效果,需要使用this.props.chidren
const Newspaper = props => {
return (
<Container>
<Article headline="An interesting Article">
Content Here
</Article>
</Container>
);
}
class Container extends React.Component {
//...
render() {
return (
<div className='container'>
{this.props.children}
</div>
);
}
}
- 子组件与map/forEach
将一个数组数据按照一定规则生成ReactElement经常用到map方法,类似的子组件也有map方法:React.Children.map()
/React.Children.forEach()
class Container extends React.Component {
static propTypes = {
component: PropTypes.element.isRequired,
children: PropTypes.element.isRequired
//...
renderChild = (childData, index) => {
return React.createElement(
this.props.component,
{}, // <~ child props
childData // <~ child's children
)
}
// ...
render() {
return (
<div className='container'>
{React.Children.map(
this.props.children,
this.renderChild )
}
</div> )
}
}