react 基础知识
react 特点
- 声名式开发
- 可以与其他框架并存
- 组件化
- 单向流数据
- 视图层框架
- 函数式编程
props, state render
state 和 props 中数据改变render函数 执行
父组件的render函数重新执行的时候子组件的render 也会执行
虚拟DOM (js 对象,js 和 js 比较不耗性能, 真实dom 对比比较耗性能 )
1. state数据
2. JSX模版
3. 数据+模版结合,生成真实的DoM,来显示
4. state发生改变
5. 数据+模版结合,生成真实的DOM,替换原始的DOM
缺陷:
数据改变完整替换DOM,非常好性能
解决方案1:
5. 数据+模版结合,生成真实的DOM,并不直接替换原始的DOM
6. 新的DOM (DoucumentFragment) 和原始的DOM做比对,找差异
7. 找出input框发生了变化
8. 只用新的DOM中的input元素,替换掉老的DOM中的input元素
解决方案2:(推荐)
1. state数据
2. JSX模版
3· 生成虚拟DOM (虚拟DOM就是一个JS对象,用它来描述真实DOM)
['div', (id: 'abc'}, ['span', t), 'hello world']]
4. 用虚拟DOM生成真实的DOM,来显示
<div id='abc'><span>hello world</span></div>
5. state发生变化
6. 数据+模版 结合,生成新的虚拟DOM
['div', (id: 'abc'}, ['span', t), 'bye bye']]
7. 比较原始虚拟DOM和新的虚拟DOM的区别,找到区别的内容(提升性能)diff 算法
8. 直接操作DOM,改变span中的内容
render() {
const { content, test }= this.props;
// JSx-> createELemnt-> 虚拟DOM (JS对象) ->真实的DOM
return (<div><span>item</span></div>
return React.createELement('div", {}, React.createELement('span', {}, 'dddd')
}
优点:
1. 性能提升
2. 它能跨端应用得以实现
虚拟DOM diff (原始虚拟DOM和新的虚拟DOM的区别比对)
1. 同层比对
2. 不能用 key={index}作为key 值 (item,用它本身做key值)
3. setdata 可以吧多次比对合并成一次比对
监听获取输入同步 react ref (获取dom) (onChange)
<input className="search-input fl" type="search" onChange={this.handlechange.bind(this)} onKeyUp={this.onKeyup.bind(this)}/>
handlechange(event) {
let val = event.target.value.replace(/^\s+|\s+$/g,"");
this.setState(() => ({ keyword: val }));
};
onKeyup(e) {
if(e.keyCode === 13) {
if (this.state.keyword.length > 1) {
this.setState(() => ({page: 1 }));
this.getData()
}
}
}
<form className="form-menu" ref="form">
<label><i>*</i>作品名称:</label>
<input className="input-border" defaultValue={title} ref="title"/>
<button type="button" className="submit" onClick={this.submitFun.bind(this)}>{this.state.modalTitle}</button>
</form>
// 表单提交
submitFun() {
const {formData} = this.state;
const { title } = this.refs;
const inputData = {};
if (title.value.length < 2) {
this.setState(() => ({hint: '作品名称不能少于2个字符' }));
} else {
inputData.title = title.value;
if(formData.id) {
inputData.id = formData.id;
this.edit(BACKEND_UPDATA_URL, inputData);
return
}
this.setState(() => ({formData: inputData }));
this.add(BACKEND_CREATE_URL, inputData)
}
};
父组件调用子组件中的方法
子组件
import React from 'react';
export default class Message extends React.Component {
constructor(props) {
super(props);
this.state = {
message: ''
}
};
componentDidMount() {
this.props.onRef(this)
}
reminding(ms) {
this.setState(() => ({ message: ms}));
setTimeout(() => {
this.setState(() => ({ message: '' }))
},3000 )
}
render() {
return (
<p className={this.state.message.length > 0 ? "message-hint-active" : 'message-hint' }>{this.state.message}</p>
)
}
}
父组件:
<Message onRef={this.onRef} />
onRef = (ref) => {
this.Message = ref
}
that.Message.reminding(res.data.message)
setSate 函数的方法(异步方法)
this.setSate((prevState) => ({
list: [...prevState.list, inputValue],
inputValue: ' '
}), () => {
// 回调方法执行完数据存储后执行可以获取刚才同步的数据
})
生命周期函数(组件自动调用的函数)
1. constructor()
es6 语法自带构造函数
组件挂载
1、componentWillMount()
页面挂载之前调用,以后组件更新不调用,只调用一次,此时可以修改state。
2、 render()
react最重要的步骤,创建虚拟dom,进行diff算法,更新dom树都在此进行。此时就不能更改state了。
3、componentDidMount()
组件挂载之后调用,组件渲染之后调用,只调用一次。
组件更新
componentWillReceiveProps(nextProps)
组件接受新的props时调用。
组件从父组件接收参数(第一次不会执行)
父组件render 重新执行了才被执行
props 更新 state 更新
1. componentWillUpdata(nextProps, nextState) // 需要返回一个bloo (true, false)
组件更新之前时才调用,此时可以修改state
2. shouldComponentUpdate(nextProps, nextState)
组件更新之前时才调用,(componentWillUpdata 之后执行)
react性能优化非常重要的一环。组件接受新的state或者props时调用,我们可以设置在此对比前后两个props和state是否相同,如果相同则返回false阻止更新,因为相同的属性状态一定会生成相同的dom树,这样就不需要创造新的dom树和旧的dom树进行diff算法对比,节省大量性能,尤其是在dom结构复杂的时候
3. render()
组件渲染
4. componentDidUpdate()
组件更新完成后调用,此时可以获取dom节点。
组件卸载:
componentWillUnmount()
组件将要卸载时调用,一些事件监听和定时器需要在此时清除。
默认设置:
1、getDefaultProps()
设置默认的props,也可以用dufaultProps设置组件的默认属性.
2、getInitialState()
在使用es6的class语法时是没有这个钩子函数的,可以直接在constructor中定义this.state。此时可以访问this.props
React css 动画效果
<p className={this.state.message.length > 0 ? "show" : 'hind' }>{this.state.message}</p>
显示隐藏
.show {transition: all 1s ease-in;opacity: 0;}
.hind {transition: all 1s ease-in; opacity: 1;}
显示隐藏变色
.show {opacity: 1;transition: all 1s ease-in;}
.hide {animation: hide-item 2s ease-in forwards;}
@keyframes hide-item {
0% {
opacity: 1;color: red;
}
50% {
opacity: 0.5;color: green;
}
100% {
opacity: 0;color: blue;
}
第三方动画模块 react-transition-group
地址: https://reactcommunity.org/react-transition-group/
redux
基本原则:
1. store 是唯一的
2. 只有store能够改变自己的内容
2. reducer: 必须是纯函数 (给定固定的函数,就会有固定的输出,不会有任何副作用(不能对参数进行修改,)
核心API
createStore 创建store
store.dispath 更新上传
store.getState 获取
store.subscribe 改变时触发
组件:
子组件直接调用父组件方法
<div onClick={(index) => {this.props.handlechange(index)}}></div>
- 普通组件 (逻辑和渲染都在一个组件)
- ul组件 (少量的逻辑 + 无状态组件)
- 容器组件(逻辑)
- 无状态组件 (渲染不加逻辑处理)
// 无状态组件
import React, { Component } from 'react';
const TodoListUI = (props)=> {
return (
<div>
<div><Inputvalue {props. inputValue)
onChange {props.handLeInputChange}/>
<Button onclick={props.handleBtnclick) /div>
</div)
中间件
redux-thunk
1. store -> action 可以是函数和对象
2. store -> dispath 方法的升级
redux-sage
tiryLi

浙公网安备 33010602011771号