React facebook团队开发
1.用来构建UI的 JavaScript库
2.React 不是一个 MVC 框架,仅仅是视图(V)层的库
特点
1 使用 JSX语法 创建组件,实现组件化开发,为函数式的 UI 编程方式打开了大门
2 性能高的让人称赞:通过 diff算法 和 虚拟DOM 实现视图的高效更新
React中的核心概念
1 虚拟DOM(Virtual DOM)
2 Diff算法(虚拟DOM的加速器,提升React性能的法宝)
JSX 的基本使用
JSX= js+html react 是js库
JSX 是 JavaScript 语法扩展,可以让你在 JavaScript 文件中书写类似 HTML 的标签
- JSX - 使用react构造组件,babel(语法降级)编译——>转化js对象
- ReactDOM.render()方法将dom,插入到root
3.JSX语法,最终会被编译为 createElement() 方法
JSX的注意点
只有一个根标签(虚拟dom对象需要一个根对象)
注意 1: 如果在 JSX 中给元素添加类, 需要使用 className 代替 class
类似:label 的 for属性,使用htmlFor代替
注意 2:在 JSX 中可以直接使用 JS代码,直接在 JSX 中通过 {} 中间写 JS代码即可
注意 3:在 JSX 中只能使用表达式,但是不能出现 语句!!!
注意 4:在 JSX 中注释语法:{/* 中间是注释的内容 */}
注意:JSX的语法需要通过 babel-preset-react 编译后,才能被解析执行
React组件
1.通过 JS函数 创建(无状态组件)
function WelcomeUI(props){
// props ---> { username: 'zs', age: 20 }
return (
<div>
<div>Welcome React</div>
<h3>姓名:{props.username}----年龄是:{props.age}</h3>
</div>
)
}
// 给 WelcomeUI组件 传递 props:username 和 age
ReactDOM.reander(<WelcomeUI username="zs" age={20}></WelcomeUI>, ......)
JavaScript函数创建注意:
注意:1 函数名称必须为大写字母开头,React通过这个特点来判断是不是一个组件
注意:2 函数必须有返回值,返回值可以是:JSX对象或null
注意:3 返回的JSX,必须有一个根元素
注意:4 组件的返回值使用()包裹,避免换行问题 return ()
2.通过 class 创建(有状态组件)
1 如果一个组件仅仅是为了展示数据,那么此时就可以使用 函数组件
2 如果一个组件中有一定业务逻辑,需要操作数据,那么就需要使用 class 创建组件,因为,此时需要使用 state
import React, {Component} from 'react';
class StateDemo extends Component {
state = {
name: 'react',
now: new Date()
};
/* 两种方式都可以
constructor(props) {
super(props);
this.state = {
name: 'react',
now: new Date()
};
}
*/
render() {
return (
<div>
<h1>hello {this.state.name}</h1>
<div>当前时间是: {this.state.now.toLocaleString()}</div>
<button onClick={()=>{this.setState({now: new Date()})}} >刷新时间</button>
</div>
);
}
}
props和state区别
1. props
给组件传递数据 - 父子组件传递数据
组件中有一个只读的对象 叫做 props,无法给props添加属性
获取方式:函数参数WelcomeUI(props)或者 类自带属性props
作用:将传递给组件的属性转化为 props 对象中的属性
### 2.state
状态即数据`
作用:用来给组件提供组件内部使用的数据
注意:只有通过class创建的组件才具有状态
注意:状态是私有的,完全由组件来控制
注意:不要在 state 中添加 render() 方法中不需要的数据,会影响渲染性能!
可以将组件内部使用但是不渲染在视图中的内容,直接添加给 this
注意:不要在 render() 方法中调用 setState() 方法来修改state的值
但是可以通过 this.state.name = 'rose' 方式设置state,但是不会更新render()(不推荐!!!!)
修改 state 的值,render()会更新
// 方式一:
this.setState({
count: this.state.count + 1
})
this.setState({
count: this.state.count + 1
}, function(){
// 由于 setState() 是异步操作,所以,如果想立即获取修改后的state
// 需要在回调函数中获取
// https://doc.react-china.org/docs/react-component.html#setstate
});
设置 state 只会为下一次渲染变更 state 的值
一个 state 变量的值永远不会在一次渲染的内部发生变化
更新state:
1.设置 state 不会更改现有渲染中的变量,但会请求一次新的渲染。
2.React 会在事件处理函数执行完成之后处理 state 更新。这被称为批处理。
3.要在一个事件中多次更新某些 state,你可以使用 setNumber(n => n + 1) 更新函数。
二. 组件的生命周期
函数的生命周期 主要分为三个阶段 :挂载
(已插入真实 DOM)、更新
(正在被重新渲染)、卸载
(已移出真实DOM) .
class LDemo extends Component {
constructor() {
super();
console.log('======执行了构造方法');
// 构造方法中直接给state赋初始值 不能执行setState
this.state = {name:'react'}
}
componentWillMount() {
'注意:无法获取页面中的DOM对象,还没被挂载'
'注意:可以调用 setState() 方法来改变状态值,用途:请求获取数据'
console.log('=======组件将要挂载,执行了componentWillMount')
}
componentDidMount() {
console.log('======组件挂载到dom节点完成,执行了componentDidMount方法');
`1 组件已经挂载到页面中
2 可以进行DOM操作,比如:获取到组件内部的DOM对象
3 可以发送请求获取数据
4 可以通过 setState() 修改状态的值
注意:在这里修改状态会重新渲染render()
`
}
shouldComponentUpdate(nextProps, nextState, nextContext) {
console.log('=====执行了shouldComponentUpdate 组件在受到props或者state更新要判断是否执行render方法刷新视图, 返回false则不执行render');
// 当state中name变为vue时,视图不更新
if (nextState.name === 'vue') {
return false;
}
return true;
}
componentDidUpdate(prevProps, prevState, snapshot) {
console.log('=====组件更新完成之后,执行了componentDidUpdate')
}
componentWillUnmount() {
// 一般用于处理消除定时器、订阅
console.log('======组件将要移除时,执行componentWillUnmount')
}
render() {
`不要在render方法中调用 setState() 方法,否则会递归渲染
原因说明:状态改变会重新调用render(),render()又重新改变状态`
console.log('======执行了render方法');
mytext = React.createRef() //关联dom
render() {
return (
<div>
<input type="text" ref={this.mytext} defaultValue="asdad" />
<button onClick={
() => { console.log(this.mytext.current.value); }
}>获取Value</button>
<button onClick={() => {
this.mytext.current.value = ""
}}>重置</button>
</div >
)
}
}
事件绑定中的this
1 通过 bind 绑定
2 通过 箭头函数 绑定
// 自定义方法:
handleBtnClick(arg1, arg2) {
this.setState({
msg: '点击事件修改state的值' + arg1 + arg2
})
}
render() {
return (
<div>
原理:bind能够调用函数,改变函数内部this的指向,并返回一个新函数
说明:bind第一个参数为返回函数中this的指向,后面的参数为传给返回函数的参数
<button onClick={
// 无参数
// this.handleBtnClick.bind(this)
// 有参数
this.handleBtnClick.bind(this, 'abc', [1, 2])
}>事件中this的处理</button>
##箭头函数中的this由所处的环境决定,自身不绑定this
<input type="button" value="在构造函数中绑定this并传参"
onClick={() => { this.handleBtnClick('参数1', '参数2')}
} />
</div>
)
}
传递给事件处理函数的函数应直接传递函数名handleClick,而非调用 handleClick()
<button onClick={handleClick}>
正确 |
handleClick
函数作为 onClick
事件处理函数传递。这会让 React 记住它,并且只在用户点击按钮时调用你的函数。
<button onClick={handleClick()}>
错误 |
handleClick()
中最后的 ()
会在 [渲染] 过程中 立即 触发函数,即使没有任何点击。这是因为在 [JSX {
和 }
]之间的 JavaScript 会立即执行。
组件通讯
父 -> 子:props
子 -> 父:父组件通过props传递回调函数
给子组件,子组件调用函数将数据
作为参数传递给父组件
兄弟组件:因为React是单向数据流,因此需要借助父组件进行传递,通过父组件回调函数改变兄弟组件的props
state
1.React 会等到事件处理函数中的 所有 代码都运行完毕再处理你的 state 更新。