目录
- 事件处理
- 示例1
- 示例2
- 示例3(this 绑定问题)
- 示例4(传递参数)
- Class 和 Style
- 表单处理
- 组件
- 组件规则注意事项
- 函数式组件(无状态)
- 类方式组件(有状态)
- 组件传值 Props
- `this.props.children`
- 组件状态 State
- 组件生命周期
- PropTypes 类型校验
- Default Prop Values
- 和服务端交互
- 获取真实 DOM 节点
- TodoMVC
- 开始
- React 其它
- React DevTools
- create-react-app
事件处理
参考文档:https://reactjs.org/docs/handling-events.html
示例1
<button οnclick="activateLasers()">
Activate Lasers
</button>
<button onClick={activateLasers}>
Activate Lasers
</button>
示例2
<a href="#" onclick="console.log('The link was clicked.'); return false">
Click me
</a>
function ActionLink() {
function handleClick(e) {
e.preventDefault();
console.log('The link was clicked.');
}
return (
<a href="#" onClick={handleClick}>
Click me
</a>
);
}
示例3(this 绑定问题)
class Toggle extends React.Component {
constructor(props) {
super(props);
this.state = {isToggleOn: true};
// This binding is necessary to make `this` work in the callback
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState(prevState => ({
isToggleOn: !prevState.isToggleOn
}));
}
render() {
return (
<button onClick={this.handleClick}>
{this.state.isToggleOn ? 'ON' : 'OFF'}
</button>
);
}
}
ReactDOM.render(
<Toggle />,
document.getElementById('root')
);
箭头函数:
class LoggingButton extends React.Component {
// This syntax ensures `this` is bound within handleClick.
// Warning: this is *experimental* syntax.
handleClick = () => {
console.log('this is:', this);
}
render() {
return (
<button onClick={this.handleClick}>
Click me
</button>
);
}
}
更简单的方式:
class LoggingButton extends React.Component {
handleClick() {
console.log('this is:', this);
}
render() {
// This syntax ensures `this` is bound within handleClick
return (
<button onClick={(e) => this.handleClick(e)}>
Click me
</button>
);
}
}
示例4(传递参数)
<button onClick={(e) => this.deleteRow(id, e)}>Delete Row</button>
<button onClick={this.deleteRow.bind(this, id)}>Delete Row</button>
Class 和 Style
class:
<div className="before" title="stuff" />
classNames:
style:
<div style={{color: 'red', fontWeight: 'bold'}} />
表单处理
参考文档:https://reactjs.org/docs/forms.html
组件
React 允许将代码封装成组件(component),然后像插入普通 HTML 标签一样,在网页中插入这个组件。
组件规则注意事项
- 组件类的第一个首字母必须大写
- 组件类必须有
render
方法 - 组件类必须有且只有一个根节点
- 组件属性可以在组件的
props
获取- 函数需要声明参数:
props
- 类直接通过
this.props
- 函数需要声明参数:
函数式组件(无状态)
- 名字不能用小写
- React 在解析的时候,是以标签的首字母来区分的
- 如果首字母是小写则当作 HTML 来解析
- 如果首字母是大小则当作组件来解析
- 结论:组件首字母必须大写
类方式组件(有状态)
class ShoppingList extends React.Component {
render() {
return (
<div className="shopping-list">
<h1>Shopping List for {this.props.name}</h1>
<ul>
<li>Instagram</li>
<li>WhatsApp</li>
<li>Oculus</li>
</ul>
</div>
);
}
}
// Example usage: <ShoppingList name="Mark" />
本质:
return React.createElement('div', {className: 'shopping-list'},
React.createElement('h1', /* ... h1 children ... */),
React.createElement('ul', /* ... ul children ... */)
);
组件传值 Props
EcmaScript 5 构造函数:
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
EcmaScript 6 Class:
class Welcome extends React.Component {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}
this.props.children
参考文档:https://reactjs.org/docs/react-api.html#reactchildren
this.props
对象的属性与组件的属性一一对应,但是有一个例外,就是 this.props.children
属性。
它表示组件的所有子节点。
this.props.children
的值有三种可能:如果当前组件没有子节点,它就是 undefined
;如果有一个子节点,数据类型是 object
;如果有多个子节点,数据类型就是 array
。所以,处理 this.props.children
的时候要小心。
React 提供一个工具方法 React.Children
来处理 this.props.children
。我们可以用 React.Children.map
来遍历子节点,而不用担心 this.props.children
的数据类型是 undefined
还是 object
。
组件状态 State
参考文档:https://reactjs.org/docs/state-and-lifecycle.html
组件生命周期
参考文档:https://reactjs.org/docs/state-and-lifecycle.html
完整生命周期 API:https://reactjs.org/docs/react-component.html#the-component-lifecycle
PropTypes 类型校验
参考文档:https://reactjs.org/docs/typechecking-with-proptypes.html
组件的属性可以接受任意值,字符串、对象、函数等等都可以。有时,我们需要一种机制,验证别人使用组件时,提供的参数是否符合要求。
示例:
import PropTypes from 'prop-types';
class Greeting extends React.Component {
render() {
return (
<h1>Hello, {this.props.name}</h1>
);
}
}
Greeting.propTypes = {
name: PropTypes.string
};
Default Prop Values
参考文档:https://reactjs.org/docs/typechecking-with-proptypes.html#default-prop-values
示例:
class Greeting extends React.Component {
render() {
return (
<h1>Hello, {this.props.name}</h1>
);
}
}
// Specifies the default values for props:
Greeting.defaultProps = {
name: 'Stranger'
};
// Renders "Hello, Stranger":
ReactDOM.render(
<Greeting />,
document.getElementById('example')
);
或者:
class Greeting extends React.Component {
static defaultProps = {
name: 'stranger'
}
render() {
return (
<div>Hello, {this.props.name}</div>
)
}
}
和服务端交互
组件的数据来源,通常是通过 Ajax 请求从服务器获取,可以使用 componentDidMount
方法设置 Ajax 请求,等到请求成功,再用 this.setState
方法重新渲染 UI 。
获取真实 DOM 节点
参考文档:https://reactjs.org/docs/refs-and-the-dom.html
组件并不是真实的 DOM 节点,而是存在于内存之中的一种数据结构,叫做虚拟 DOM (virtual DOM)。只有当它插入文档以后,才会变成真实的 DOM 。根据 React 的设计,所有的 DOM 变动,都先在虚拟 DOM 上发生,然后再将实际发生变动的部分,反映在真实 DOM上,这种算法叫做 DOM diff ,它可以极大提高网页的性能表现。
但是,有时需要从组件获取真实 DOM 的节点,这时就要用到 ref
属性。
示例:
class CustomTextInput extends React.Component {
constructor(props) {
super(props);
this.focusTextInput = this.focusTextInput.bind(this);
}
focusTextInput() {
// Explicitly focus the text input using the raw DOM API
this.textInput.focus();
}
render() {
// Use the `ref` callback to store a reference to the text input DOM
// element in an instance field (for example, this.textInput).
return (
<div>
<input
type="text"
ref={(input) => { this.textInput = input; }} />
<input
type="button"
value="Focus the text input"
onClick={this.focusTextInput}
/>
</div>
);
}
}
TodoMVC
- classnames
开始
下载模板:
git clong https://github.com/tastejs/todomvc-app-template.git --depth=1 todomvc-react
安装依赖:
cd todomvc-react
npm install
安装 react
开发环境依赖:
npm install --save babel-standalone react react-dom
React 其它
React DevTools
https://github.com/facebook/react-devtools