爱生活,爱编程,学习使我快乐
JSX语法:render返回元素最外层必须由一个元素包裹。
Fragment 可以作为React的最外层元素占位符。
import React, {Component, Fragment} from 'react';
class TodoList extends Component {
render() {
return (
<Fragment>
<div>
<input/>
<button>提交</button>
</div>
<ul>
<li>1111111</li>
<li>2222222</li>
<li>3333333</li>
</ul>
</Fragment>
)
}
}
export default TodoList;
import React, {Component, Fragment} from 'react';
class TodoList extends Component {
constructor(props) {
super(props);
this.state = {
inputValue: '',
list: []
}
}
render() {
return (
<Fragment>
<div>
<input value={this.state.inputValue} onChange={this.handleChange.bind(this)}/>
<button>提交</button>
</div>
<ul>
<li>1111111</li>
<li>2222222</li>
<li>3333333</li>
</ul>
</Fragment>
)
}
handleChange (e) {
this.setState({
inputValue: e.target.value
})
}
}
export default TodoList;
import React, {Component, Fragment} from 'react';
lass TodoList extends Component {
constructor(props) {
super(props);
this.state = {
inputValue: '',
list: ['学习英语', '学习React']
}
}
render() {
return (
<Fragment>
<div>
<input value={this.state.inputValue} onChange={this.handleChange.bind(this)}/>
<button onClick={this.handleBtnClick.bind(this)}>提交</button>
</div>
<ul>
{this.state.list.map((item, index) => {
return <li key={index} onClick={this.handleItemDelete.bind(this, index)}>{item}</li>
})}
</ul>
</Fragment>
)
}
handleChange (e) {
this.setState({
inputValue: e.target.value
})
}
// 点击提交后,列表中添加一项,input框中内容清空
handleBtnClick () {
this.setState({
list: [...this.state.list, this.state.inputValue],
inputValue: ''
})
}
// 删除
handleItemDelete(index) {
let list = [...this.state.list]; // 拷贝一份原数组,因为是对象,所以不能直接赋值,会有引用问题
list.splice(index, 1);
this.setState({
list: list
})
// 以下方法可以生效,但是不建议使用。
// React中immutable的概念: state 不允许直接操作改变,否则会影响性能优化部分。
// this.state.list.splice(index, 1);
// this.setState({
// list: this.state.list
// })
}
}
export default TodoList;
{/*这里是注释*/}
或者:
{
//这里是注释
}
元素属性class 替换成 className
lable标签中的for 替换成 htmlFor
如果需要在JSX里面解析html的话,可以在标签上加上属性dangerouslySetInnerHTML属性(标签中不需要再输出item):如dangerouslySetInnerHTML={{__html: item}}
...
render() {
return (
<Fragment>
{/* 这是一个注释 */}
{
// class 换成 className
// for 换成 htmlFor
}
<div className="input">
<lable htmlFor={"insertArea"}>请输入内容</lable>
<input id="insertArea" value={this.state.inputValue} onChange={this.handleChange.bind(this)}/>
<button onClick={this.handleBtnClick.bind(this)}>提交</button>
</div>
<ul>
{this.state.list.map((item, index) => {
return (
<li
key={index}
onClick={this.handleItemDelete.bind(this, index)}
dangerouslySetInnerHTML={{__html: item}}
>
</li>
// <li
// key={index}
// onClick={this.handleItemDelete.bind(this, index)}
// >
// {item}
// </li>
)
})}
</ul>
</Fragment>
)
}
...
父组件通过属性向子组件传递数据,子组件通过this.props.属性名 获取父组件传来的数据。
子组件调用父组件的方法来改变父组件的数据。也是父组件通过属性把父组件对应的方法传递给子组件(在父组件向子组件传入方法时,就要绑定this,不然在子组件找不到方法),然后在子组件中通过this.props.方法名(属性名) 调用对应的父组件的方法并传递对应的参数。通过触发父组件方法改变数据,数据改变从而重新渲染页面。
import React, {Component, Fragment} from 'react';
import TodoItem from './todoItem';
class TodoList extends Component {
constructor(props) {
super(props);
this.state = {
inputValue: '',
list: ['学习英语', '学习React']
}
}
render() {
return (
<Fragment>
<div className="input">
<label htmlFor={"insertArea"}>请输入内容</label>
<input id="insertArea" value={this.state.inputValue} onChange={this.handleChange.bind(this)}/>
<button onClick={this.handleBtnClick.bind(this)}>提交</button>
</div>
<ul>
{this.state.list.map((item, index) => {
return (
<TodoItem
key={index}
index={index}
item={item}
deleteItem={this.handleItemDelete.bind(this)}
/>
)
})}
</ul>
</Fragment>
)
}
handleChange (e) {
this.setState({
inputValue: e.target.value
})
}
// 点击提交后,列表中添加一项,input框中内容清空
handleBtnClick () {
this.setState({
list: [...this.state.list, this.state.inputValue],
inputValue: ''
})
}
// 删除
handleItemDelete(index) {
let list = [...this.state.list];
list.splice(index, 1);
this.setState({
list: list
})
}
}
export default TodoList;
import React, { Component } from 'react';
class TodoItem extends Component {
constructor(props) {
super(props);
this.handleDeleteItem = this.handleDeleteItem.bind(this);
}
render() {
return (
<li onClick={this.handleDeleteItem}>
{this.props.item}
</li>
)
}
handleDeleteItem() {
this.props.deleteItem(this.props.index);
}
}
export default TodoItem;
import React, {Component, Fragment} from 'react';
import TodoItem from './todoItem';
class TodoList extends Component {
constructor(props) {
super(props);
this.state = {
inputValue: '',
list: ['学习英语', '学习React']
}
// 统一在constructor中绑定this,提交性能
this.handleChange = this.handleChange.bind(this);
this.handleBtnClick = this.handleBtnClick.bind(this);
this.handleItemDelete = this.handleItemDelete.bind(this);
this.getTodoItem = this.getTodoItem.bind(this);
}
render() {
return (
<Fragment>
<div className="input">
<label htmlFor={"insertArea"}>请输入内容</label>
<input id="insertArea" value={this.state.inputValue} onChange={this.handleChange}/>
<button onClick={this.handleBtnClick}>提交</button>
</div>
<ul>
{this.getTodoItem()}
</ul>
</Fragment>
)
}
handleChange (e) {
// this.setState({
// inputValue: e.target.value
// })
// 因这种写法setState是异步的,有时e.target获取不到,所以先赋值给一个变量再使用。
const value = e.target.value;
// 新版写法,setState不但可以接受一个对象,也可以接受一个方法
// this.setState(() => {
// return {
// inputValue: value
// }
// })
// this.setState(()=>{retuen {}}) 简写成 this.setState(()=>({}))
// 还可以再简写成
this.setState(() => (
{
inputValue: value
}
))
}
// 点击提交后,列表中添加一项,input框中内容清空
handleBtnClick () {
// this.setState({
// list: [...this.state.list, this.state.inputValue],
// inputValue: ''
// })
// 新版写法,可以使用prevState代替修改前的this.state,不但可以提高性能,也能避免不小心修改state导致的bug。
this.setState((prevState) => {
return {
list: [...prevState.list, prevState.inputValue],
inputValue: ''
}
})
}
// 删除
handleItemDelete(index) {
// let list = [...this.state.list];
// list.splice(index, 1);
// this.setState({
// list: list
// })
// 新版写法,可以在return前写js逻辑
this.setState(() => {
let list = [...this.state.list];
list.splice(index, 1);
return {list: list}
})
}
// 把循环提取出来,放在一个方法中
getTodoItem () {
return this.state.list.map((item, index) => {
return (
<TodoItem key={index} index={index} item={item} deleteItem={this.handleItemDelete}/>
)
})
}
}
export default TodoList;
1、声明式开发
可减少大量的dom操作;
对应的是命令式开发,比如jquery,操作DOM。
2、可以与其它框架并存
React可以与jquery、angular、vue等框架并存,在index.html页面,React只渲染指定id的div(如:root),只有这个div跟react有关系。
3、组件化
继承Component,组件名称第一个字母大写。
4、单向数据流
父组件可以向子组件传递数据,但子组件绝对不能改变该数据(应该调用父级传入的方法修改该数据)。
5、视图层框架
在大型项目中,只用react远远不够,一般用它来搭建视图,在作组件传值时要引入一些框架(Fux、Redux等数据层框架);
6、函数式编程
用react做出来的项目更容易作前端的自动化测试。