上篇续写
详细内容
1)React 事件处理
React 元素的事件处理和 DOM 元素类似。但是有一点语法上的不同:
1.React 事件绑定属性的命名采用驼峰式写法,而不是小写。
如果采用 JSX 的语法你需要传入一个函数作为事件处理函数,而不是一个字符串(DOM 元素的写法)
HTML 通常写法是:
<button onclick="activateLasers()">
激活按钮
</button>
React 中写法为:
<button onClick={
activateLasers}>
激活按钮
</button>
2.React 中另一个不同是你不能使用返回 false 的方式阻止默认行为, 你必须明确使用 preventDefault。
HTML 通常写法是:
<a href="#" onclick="console.log('点击链接'); return false">
点我
</a>
React 中写法为:
function ActionLink() {
function handleClick(e) {
e.preventDefault();
console.log('链接被点击');
}
return (
<a href="#" onClick={
handleClick}>
点我
</a>
);
}
e 是一个合成事件。
使用 React 的时候通常你不需要使用 addEventListener 为一个已创建的 DOM 元素添加监听器
。你仅仅需要在这个元素初始渲染的时候提供一个监听器
。
import React from 'react';
import ReactDOM from 'react-dom';
import PropTypes from 'prop-types';
class Toggle extends React.Component {
constructor(props) {
super(props);
this.state = {
isToggleOn: true};
// 这边绑定是必要的,这样 `this` 才能在回调函数中使用
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('example')
);
谨慎对待 JSX 回调函数中的 this,类的方法默认是不会绑定 this 的。如果你忘记绑定 this.handleClick 并把它传入 onClick, 当你调用这个函数的时候 this 的值会是 undefined。
向事件处理程序传递参数
通常我们会为事件处理程序传递额外的参数。
参数 e 作为 React 事件对象将会被作为第二个参数进行传递。
通过箭头函数的方式,事件对象必须显式的进行传递,但是通过 bind 的方式,事件对象以及更多的参数将会被隐式的进行传递。
<button onClick={
(e) => this.deleteRow(id, e)}>Delete Row</button>
<button onClick={
this.deleteRow.bind(this, id)}>Delete Row</button>
2)React 条件渲染
在 React 中,你可以创建不同的组件来封装各种你需要的行为。然后还可以根据应用的状态变化只渲染其中的一部分。
React 中的条件渲染和 JavaScript 中的一致,使用 JavaScript 操作符 if 或条件运算符来创建表示当前状态的元素,然后让 React 根据它们来更新 UI。
import React from 'react';
import ReactDOM from 'react-dom';
import PropTypes from 'prop-types';
function User(props){
return <h1> Hello, Welcome</h1>
}
function Guest(props){
return<h1> You need to register</h1>
}
function Judgement(props){
const isLoggedIn = props.isLoggedIn;
if(isLoggedIn){
return <User/>
}
return <Guest />
}
ReactDOM.render(
<Judgement isLoggedIn={
false}/>,
// <Judgement isLoggedIn={true}/>,
document.getElementById('example')
);
元素变量
你可以使用变量来储存元素。它可以帮助你有条件的渲染组件的一部分,而输出的其他部分不会更改。
在下面的例子中,我们将要创建一个名为 LoginControl 的有状态的组件。
它会根据当前的状态来渲染 或 ,它也将渲染前面例子中的 。
import React from 'react';
import ReactDOM from 'react-dom';
class LoginControl extends React.Component {
constructor(props) {
super(props);
this.handleLoginClick = this.handleLoginClick.bind(this);
this.handleLogoutClick = this.handleLogoutClick.bind(this);
this.state = {
isLoggedIn: false};
}
handleLoginClick() {
this.setState({
isLoggedIn: true});
}
handleLogoutClick() {
this.setState({
isLoggedIn: false});
}
render() {
const isLoggedIn = this.state.isLoggedIn;
let button;
if (isLoggedIn) {
button = <LogoutButton onClick={
this.handleLogoutClick} />;
} else {
button = <LoginButton onClick={
this.handleLoginClick} />;
}
return (
<div>
<Greeting isLoggedIn={
isLoggedIn} />
{
button}
</div>
);
}
}
function UserGreeting(props) {
return <h1>欢迎回来!</h1>;
}
function GuestGreeting(props) {
return <h1>请先注册。</h1>;
}
function Greeting(props) {
const isLoggedIn = props.isLoggedIn;
if (isLoggedIn) {
return <UserGreeting />;
}
return <GuestGreeting />;
}
function LoginButton(props) {
return (
<button onClick={
props.onClick}>
登陆
</button>
);
}
function LogoutButton(props) {
return (
<button onClick={
props.onClick}>
退出
</button>
);
}
ReactDOM.render(
<LoginControl />,
document.getElementById('example')
);
与运算符 &&
通过用花括号包裹代码在 JSX 中嵌入任何表达式 ,也包括 JavaScript 的逻辑与 &&,它可以方便地条件渲染一个元素。
import React from 'react';
import ReactDOM from 'react-dom';
function Mailbox(props) {
const unreadMessages = props.unreadMessages;
return (
<div>
<h1>Hello!</h1>
{
unreadMessages.length > 0 &&
<h2>
您有 {
unreadMessages.length} 条未读信息。
</h2>
}
</div>
);
}
const messages = ['React', 'Re: React', 'Re:Re: React'];
ReactDOM.render(
<Mailbox unreadMessages={
messages} />,
document.getElementById('example')
);
三目运算符
condition ? true : false。
阻止组件渲染
在极少数情况下,你可能希望隐藏组件,即使它被其他组件渲染。让 render 方法返回 null 而不是它的渲染结果即可实现。
在下面的例子中, 根据属性 warn 的值条件渲染。如果 warn 的值是 false,则组件不会渲染:
3)React 列表 & Keys
import React from 'react';
import ReactDOM from 'react-dom';
const numbers = [1, 2, 3, 4, 5];
const listItems = numbers.map((numbers) =>
<li>{
numbers}</li>
);
ReactDOM.render(
<ul>{
listItems}</ul>,
document.getElementById('example')
);
import React from 'react';
import ReactDOM from 'react-dom';
function NumberList(props) {
const numbers = props.numbers;
const listItems = numbers.map((number) =>
<li key={
number.toString()}>
{
number}
</li>
);
return (
<ul>{
listItems}</ul>
);
}
const numbers = [1, 2, 3, 4, 5];
ReactDOM.render(
<NumberList numbers={
numbers} />,
document.getElementById('example')
);
Keys
Keys 可以在 DOM 中的某些元素被增加或删除的时候帮助 React 识别哪些元素发生了变化。因此你应当给数组中的每一个元素赋予一个确定的标识。
4)React 组件 API
设置状态:setState
替换状态:replaceState
设置属性:setProps
替换属性:replaceProps
强制更新:forceUpdate
获取DOM节点:findDOMNode
判断组件挂载状态:isMounted
设置状态:setState
setState(object nextState[, function callback])
参数说明
nextState,将要设置的新状态,该状态会和当前的state合并
callback,可选参数,回调函数。该函数会在setState设置成功,且组件重新渲染后调用。
合并nextState和当前state,并重新渲染组件。setState是React事件处理函数中和请求回调函数中触发UI更新的主要方法
setState()并不会立即改变this.state,而是创建一个即将处理的state。setState()并不一定是同步的,为了提升性能React会批量执行state和DOM渲染。
setState()总是会触发一次组件重绘,除非在shouldComponentUpdate()中实现了一些条件渲染逻辑。
import React from 'react';
import ReactDOM from 'react-dom';
class Counter extends React.Component{
constructor(props) {
super(props);
this.state = {
clickCount: 0};
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState(function(state) {
return {
clickCount: state.clickCount + 1};
});
}
render () {
return (<h2 onClick={
this.handleClick}>点我!点击次数为: {
this.state.clickCount}</h2>);
}
}
ReactDOM.render(
<Counter />,
document.getElementById('example')
);
不断点击,次数会增加
替换状态:replaceState
replaceState(object nextState[, function callback])
nextState
,将要设置的新状态,该状态会替换当前的state。
callback
,可选参数,回调函数。该函数会在replaceState设置成功,且组件重新渲染后调用。
replaceState()方法
与setState()
类似,但是方法只会保留nextState中状态,原state不在nextState中的状态都会被删除。
设置属性:setProps
setProps(object nextProps[, function callback])
nextProps
,将要设置的新属性,该状态会和当前的props合并
callback
,可选参数,回调函数
。该函数会在setProps设置成功,且组件重新渲染后调用。
设置组件属性,并重新渲染组件。
props相当于组件的数据流,它总是会从父组件向下传递至所有的子组件中。当和一个外部的JavaScript应用集成时,我们可能会需要向组件传递数据或通知React.render()组件需要重新渲染,可以使用setProps()。
更新组件,我可以在节点上再次调用React.render(),也可以通过setProps()方法改变组件属性,触发组件重新渲染。
替换属性:replaceProps
replaceProps(object nextProps[, function callback])
nextProps
,将要设置的新属性,该属性会替换当前的props。
callback
,可选参数,回调函数。该函数会在replaceProps设置成功,且组件重新渲染后调用。
replaceProps()方法与setProps类似,但它会删除原有 props。
强制更新:forceUpdate
forceUpdate([function callback])
参数说明
callback,可选参数,回调函数。该函数会在组件render()方法调用后调用。
forceUpdate()
方法会使组件调用自身的render()方法重新渲染组件,组件的子组件也会调用自己的render()。但是,组件重新渲染时,依然会读取this.props和this.state,如果状态没有改变,那么React只会更新DOM。
forceUpdate()
方法适用于this.props和this.state之外的组件重绘(如:修改了this.state后),通过该方法通知React需要调用render()
一般来说,应该尽量避免使用forceUpdate(),而仅从this.props和this.state中读取状态并由React触发render()调用。
获取DOM节点:findDOMNode
DOMElement findDOMNode()
返回值:DOM元素DOMElement
如果组件已经挂载到DOM中,该方法返回对应的本地浏览器 DOM 元素。当render返回null 或 false时,this.findDOMNode()也会返回null。从DOM 中读取值的时候,该方法很有用,如:获取表单字段的值和做一些 DOM 操作。
判断组件挂载状态:isMounted
bool isMounted()
返回值:true或false,表示组件是否已挂载到DOM中
isMounted()方法用于判断组件是否已挂载到DOM中。可以使用该方法保证了setState()和forceUpdate()在异步场景下的调用不会出错。