**1. 组件 **
<body>
<div id="app"></div>
<script src="../build/react.min.js"></script>
<script src = "../build/JSXTransformer.js"></script>
<script type = "text/jsx">
var InputState = React.createClass({
//getInitialState 方法中 return 的对象,就是 state 对象,里面自建属性
getInitialState : function(){
return {enable:false};
},
//state 的属性通过 this.state.prop 得到
handleClick : function(event){
this.setState({enable:!this.state.enable});
},
//注意内联样式的写法
render : function(){
return (
<p>
<input type="text" disabled = {this.state.enable} style={{color:this.state.enable?'green':'red'}}/>
<button onClick={this.handleClick}>ChangeState</button>
</p>
)
}
});
React.render(<InputState/>,document.getElementById('app'));
</script>
</body>
**2. state **
- state 不能直接赋值,比如以下的代码 :
//wrong
this.state.comment = 'Hello';
// Correct
this.setState({comment: 'Hello'});
- state是异步的,因此你不能用某个state计算得到下个state:
// Wrong
this.setState({ counter: this.state.counter + this.props.increment,});
// Correct
this.setState((prevState, props) => ({ counter: prevState.counter + props.increment}));
注意上面setState方法,它不仅仅可以接收一个对象,还可接收一个方法,这个方法的参数分别是上一个state,和当前的props。
**3. 事件 **
- 阻止事件冒泡,必须显式指定
//js
<a href="#" onclick="console.log('The link was clicked.'); return false"> Click me</a>
//react
function ActionLink() {
function handleClick(e) {
e.preventDefault();
console.log('The link was clicked.');
}
return ( <a href="#" onClick={handleClick}> Click me </a> );
}
- react事件作用域问题:
import React, {Component} from 'react'
export default class Toggle extends Component{
constructor(props){
super(props);
this.state={isToggleOn : true};
// 必须bind(this),否则报错(this值window对象)
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState(prevState=>({
isToggleOn : !prevState.isToggleOn
}));
}
render(){
return (
<button onClick={this.handleClick} style={{background: this.state.isToggleOn?'green':'red'}}>
{this.state.isToggleOn?'ON':'OFF'}
</button>
)
}
}
<u><i>如果把上面的 this.handleClick = this.handleClick.bind(this);这句去掉,就会报错,解决办法3种:</i></u>
You have to be careful about the meaning of this in JSX callbacks. In JavaScript, class methods are not bound by default. If you forget to bind this.toggle and pass it to onClick, this will be undefined when the function is actually called.
This is not React-specific behavior; it is a part of how functions work in JavaScript. Generally, if you refer to a method without () after it, such as onClick={this.handleClick}, you should bind that method.
If calling bind annoys you, there are two ways you can get around this. If you are using the experimental property initializer syntax, you can use property initializers to correctly bind callbacks:
- 用Lambda表达式定义函数
handleClick=()=> {
this.setState(prevState=>({
isToggleOn : !prevState.isToggleOn
}));
}
- jsx调用时bind:
render(){
return (
<button onClick={this.handleClick.bind(this)} style={{background: this.state.isToggleOn?'green':'red'}}>
{this.state.isToggleOn?'ON':'OFF'}
</button>
)
}
- jsx用Lambda调用
render(){
return (
<button onClick={(e)=>this.handleClick(e)} style={{background: this.state.isToggleOn?'green':'red'}}>
{this.state.isToggleOn?'ON':'OFF'}
</button>
)
}
**4. 条件渲染 **
function Mailbox(props) {
const unreadMessages = props.unreadMessages;
return (
<div>
<h1>Hello!</h1>
//此处若length>0 则会渲染h2
{unreadMessages.length > 0 &&
<h2>
You have {unreadMessages.length} unread messages.
</h2>
}
</div>
);
}
const messages = ['React', 'Re: React', 'Re:Re: React'];
ReactDOM.render(
<Mailbox unreadMessages={messages} />,
document.getElementById('root')
);
5. List
- 列表循环必须要提供key:
import React, {Component} from 'react'
export default class List extends Component{
render(){
const stus = this.props.stus;
const stuListElements = stus.map((stu)=><li>{stu}</li>);
return (
<ul>
{stuListElements}
</ul>
);
}
}
//报错:warning.js:36 Warning: Each child in an array or iterator should have a unique "key" prop.
// Check the render method of `List`. See https://fb.me/react-warning-keys for more information.
Keys help React identify which items have changed, are added, or are removed. Keys should be given to the elements inside the array to give the elements a stable identity:
The best way to pick a key is to use a string that uniquely identifies a list item among its siblings. Most often you would use IDs from your data as keys:
解决办法是给每个列表项提供一个唯一key,一般可以是id
let testStu = [
{id:1,name:'aaa'},
{id:2,name:'bbb'},
{id:3,name:'ccc'}
];
...
const stuListElements = stus.map((stu)=><li key={stu.id}>{stu.name}</li>);
...
要是列表项没有key怎么办?官方给出的答案是使用数组下标,万不得已采用,因为这个会减慢渲染速度:
// Only do this if items have no stable IDs
const todoItems = todos.map((todo, index) =>
<li key={index}> {todo.text} </li>);
- key 始终应该在Array内部定义!
function Number(props) {
// Correct! There is no need to specify the key here:
return <li>{props.value}</li>;
}
function NumberList(props) {
const numbers = props.numbers;
const listItems = numbers.map((number) =>
// Correct! Key should be specified inside the array.
<Number key={number.toString()}
value={number} />
);
return (
<ul>
{listItems}
</ul>
);
}
const numbers = [1, 2, 3, 4, 5];
ReactDOM.render(
<NumberList numbers={numbers} />,
document.getElementById('root')
);
** 6. Form **
- Two types of form components:
Controlled Components (有value属性的)
Uncontrolled Components(没有value属性的)
import React, {Component} from 'react'
export default class Form extends Component{
constructor (props){
super(props);
this.state = {formValue: "hello react"};
}
handleInput=(event)=>{
//target.formValue取到input的值
//这样限制用户输入的长度
this.setState({formValue: event.target.value.substr(0,10)})
}
render(){
return (
<div>
<h3> {this.state.formValue} </h3>
这是一个Controlled Components <br />
<p><input type="text" onChange={this.handleInput} value={this.state.formValue}/></p>
这是一个UnControlled Components <br />
<p><input type="text" onChange={this.handleInput} /></p>
</div>
);
}
}
Paste_Image.png
可以看到Controlled Component的value是受控制的
- 使用Checkboxes 和 Radio Buttons时注意:preventDefault
Be aware that, in an attempt to normalize change handling for checkbox and radio inputs, React uses a click event in place of a change event. For the most part this behaves as expected, except when calling preventDefault
in a change handler. preventDefault stops the browser from visually updating the input, even if checked gets toggled. This can be worked around either by removing the call to preventDefault , or putting the toggle ofchecked in a setTimeout
- 非空初始值用default value:
render() { return <input type="text" defaultValue="Hello!" />; }
网友评论