1、Fragment可以作为React组件的占位符,使它在Dom中不显示最外层的div
import React,{Component,Fragment} from 'react';
class TodoList extends Component{
render(){
return (
<Fragment>
<div>
<input />
<button>提交</button>
</div>
<ul>
<li>my list 1</li>
<li>my list 2</li>
</ul>
</Fragment>
);
}
}
export default TodoList;
2、数据驱动响应
- this.state 负责存储数据
- jsx中js表达式用{}包裹
- 事件绑定需要通过bind(this)对函数的作用域进行变更
- 如果修改state中的内容,不能直接改,需要通过setState向里面传入对象的形式进行修改
import React,{Component,Fragment} from 'react';
class TodoList extends Component{
constructor(props) {
super(props);
this.state = {
inputValue: '123',
list: [],
}
}
render(){
return (
<Fragment>
<div>
<input value={this.state.inputValue} onChange={this.handleChange.bind(this)} />
<button>提交</button>
</div>
<ul>
<li>my list 1</li>
<li>my list 2</li>
</ul>
</Fragment>
);
}
handleChange(e){
// console.log(this);
this.setState({
inputValue:e.target.value,
});
// Uncaught TypeError: Cannot read property 'state' of undefined
this.state.inputValue = e.target.value;
}
}
export default TodoList;
3、TodoList列表动态新增,删除
- react中的immutable概念要求我们不要修改state,而是修改副本,好处是可以用来性能优化
- function.bind(this, 函数接收参数)
import React,{Component,Fragment} from 'react';
class TodoList extends Component{
constructor(props) {
super(props);
this.state = {
inputValue: '123',
list: [],
}
}
render(){
return (
<Fragment>
<div>
<input value={this.state.inputValue} onChange={this.handleChange.bind(this)} />
<button onClick={this.handBtnClick.bind(this)}>提交</button>
</div>
<ul>
{
this.state.list.map((item,index) => {
// return (<li>{item}</li>) Each child in a list should have a unique "key" prop.
return (
<li key={index} onClick={this.handItemDelete.bind(this,index)}>
{item}
</li>
)
})
}
</ul>
</Fragment>
);
}
handleChange(e) {
// console.log(this);
this.setState({
inputValue:e.target.value,
});
// Uncaught TypeError: Cannot read property 'state' of undefined
// this.state.inputValue = e.target.value;
}
handBtnClick() {
this.setState(
{
list: [...this.state.list,this.state.inputValue],
inputValue: '',
}
);
}
handItemDelete(index) {
// console.log(index);
// 拷贝一个副本,react不建议直接对状态数据直接操作
const list = this.state.list;
list.splice(index,1); // 根据下标删除
this.setState(
{
list: list,
}
);
}
}
export default TodoList;
4、Jsx语法细节
-
react 标签内的属性 不能和js中自带的属性和方法名冲突 替换成其他的名字(驼峰)代替原有属性名 例:class 替换成 className
-
在jsx语法内部添加注释:
{/这里是注释/}
或者:
{
//这里是注释
} -
如果需要在jsx里面解析html的话,可以在标签上加上属性dangerouslySetInnerHTML属性:如dangerouslySetInnerHTML={{__html: item}}
5、组件间的传值
父子组件之间通讯:
-
父=>子
父组件通过属性向子组件传递数据,子组件通过this.props.属性名 就可以获取父组件传来的数据。 -
子=>父
子组件调用父组件的方法来改变父组件的数据,也是父组件通过属性把 父组件对应的方法传递给子组件(要绑定this ,bind(this),不然在子组件找不到方法),然后子组件在对应的方法中通过this.props.方法名(属性名) 调用对应的父组件的方法并传递对应的参数,通过触发父组件方法改变数据,数据改变从而重新渲染页面。 -
组件间传指通过对象的属性进行,传递的内容可以是变量也可以是方法,接受方通过this.props.对应的名称进行接收。传递时需要通过bind(this)来传递自己给对方。在事件绑定自身对象时建议通过contructor构造函数中来实现,如this.handeClick = this.handleClick.bind(this);这样可以提高效率。
<TodoItem
content={item}
index={index}
key ={index}
itemDelete={this.handItemDelete.bind(this)}
/>
import React,{Component} from 'react';
class TodoItem extends Component {
constructor(props) {
super(props);
this.handClick = this.handClick.bind(this);
}
render(){
return (
<li onClick={this.handClick}> }>
{this.props.content }
</li>
)
}
handClick(){
this.props.itemDelete(this.props.index);
// alert(this.props.index);
}
}
export default TodoItem;
6、TodoList优化代码
import React,{Component,Fragment} from 'react';
import TodoItem from './TodoItem';
import './style.css';
class TodoList extends Component{
constructor(props) {
super(props);
this.state = {
inputValue: '123',
list: [],
}
this.handleChange = this.handleChange.bind(this);
this.handBtnClick = this.handBtnClick.bind(this);
this.handItemDelete = this.handItemDelete.bind(this);
}
render(){
return (
<Fragment>
<div>
<label htmlFor="inputAra">输入内容</label>
<input className="input" id ="inputAra"
value={this.state.inputValue} onChange={this.handleChange} />
<button onClick={this.handBtnClick}>提交</button>
</div>
<ul>
{this.getTodoItem()}
</ul>
</Fragment>
);
}
getTodoItem(){
return this.state.list.map((item,index) => {
return (
<TodoItem
content={item}
index={index}
key ={index}
itemDelete={this.handItemDelete}
/>
)
})
}
handleChange(e) {
// 函数,异步,性能提升
const value = e.target.value;
this.setState(() => ({
inputValue:value,
}));
// this.setState({
// inputValue:e.target.value,
// });
}
handBtnClick() {
this.setState((prevState) => ({
list: [...prevState.list,prevState.inputValue],
inputValue: '',
}));
}
handItemDelete(index) {
this.setState((prevState) => {
const list = [...prevState.list];
list.splice(index,1); // 根据下标删除
return {list}
});
}
}
export default TodoList;
import React,{Component} from 'react';
class TodoItem extends Component {
constructor(props) {
super(props);
this.handClick = this.handClick.bind(this);
}
render(){
const {content} = this.props;
return (<li onClick={this.handClick}>{content }</li>)
}
handClick(){
const {itemDelete,index} = this.props;
itemDelete(index);
}
}
export default TodoItem;