react

145 阅读3分钟

props校验,默认值

Consumer, Provider
// 父组件:
    const p = {
        name="zhangsan",
        age="18"
    }
    // <Provider {...p} >
    <Provider name="zhangsan" age="18">
        <App />
    <Provider />
    
// 子组件
    <Consumer>
        {(info) => (
          // 通过Consumer直接获取父组件的值
          <div>
            <p>父组件的值:{info}</p>
            <GrandSon />
          </div>
        )}
    </Consumer>
// 默认值
组件名.defaultProps = {
    age: 1,
    str: 'zhangsan'
}
// 传值校验:
// 插件:prop-types
import PropTypes from 'prop-types';
组件名.propTypes = {
    optionalArray: PropTypes.array,//检测数组类型
    optionalBool: PropTypes.bool,//检测布尔类型
    optionalFunc: PropTypes.func,//检测函数(Function类型)
    optionalNumber: PropTypes.number,//检测数字.isRequired(必传项)
    optionalObject: PropTypes.object,//检测对象
    optionalString: PropTypes.string,//检测字符串
    optionalSymbol: PropTypes.symbol,//ES6新增的symbol类型
    optionalObjectWithShape: propTypes.shape({ // 特定结构对象
        num: PropTypes.number,
        str: PropTypes.string,
    })
    optionalArray: PropTypes.element, // 检测元素
    optionalArray: PropTypes.array, // 检测数组类型
}

render-props: 共享数据,共享组件

1.
    1-1、 将复用的数据this.props.render(state),暴露出去
    1-2、 使用props.render()的返回值作为渲染的内容

    子组件
        state: {数据}
        render() {
            return this.props.render(this.state)
        }        
    父组件
        <子组件 render=((data) => <p>数据: {data}><p />)<子组件 />
2.
    2-1、children代替props
    2-2、优化,建议添加props校验
         子组件名称.ProTypes = {
             childlren: PropTypes.func.isRequired // 检查是否是函数
         }
    2-3、优化,组件卸载时,解除事件绑定,清楚定时器
    子组件
        state: {数据}
        render() {
            return this.props.render(this.state)
        }
    父组件
        <子组件>
            {(data) => <p>数据: {data}}
        <子组件 />

生命周期

    创建时:
        constructor -> 初始化state,为事件处理程序绑定this
        render -> 每次组件渲染时触发(渲染UI,不能调用this.setState)
        componentWillMount -> 组件挂载(完成dom渲染后)-> 发送请求,DOM操作
    更新时:
        render -> 完成UI渲染
        // 触发时机:调用this.setState(),更新props,this.forceUpdata():强制更新。
        // 调用this.setState()更改数据时,需要判断更新前后的值是否相同,来确实是否更新
        // 参数1:上次的props, componentDidUpdate(prveProps)
        componentDidUpdate -> 组件更新完成dom渲染 -> 发送请求,don操作,
    卸载时:
        componentWillUnmount -> 组件卸载时 -> 执行清理工作如:定时器、、
    更新执行渲染时执行:
        shoudComponentUpdata -> render
        // nextProps: 最新的props 
        // nextState: 最新的State
        shoudComponentUpdata(nextPrpos, nextState) {
            // 根据条件,判断是否重新渲染组件
            // true:重新渲染组件,false:不重新渲染组件
            return false/ture
        }

高阶组件

1.创建一个函数,名称约定以 with 开头
2.指定函数参数,参数应该以大写字母开头(作为要渲染的组件)
3.在函数内部创建类组件,提供复用的状态逻辑代码,并返回
4.在该组件中,渲染参数组件,同事将状态通过prop传递给参数组件
5.调用该高阶组件,传入要增强的组件,通过返回值拿到增强后的组件,并将其渲染到页面中
6.设置组件的displayName,区分组件,方便调试。
7.传递props,state

function withMouse(WrappedComponent) {
    class Mouse extends React.component {
        // 省略state,方法
        render <WrappedComponent (...this.state) (...this.props)> <WrappedComponent />
    }
    
    Mouse.displayName = `Mouse${getDisplayName(WrappedComponent)}`
    
    return Mouse
}

function getDisplayName(WrappedComponent){
    return WrappedComponent.displayName || WrappedComponent.name || 'Component'
}

// 获取增强 后的组件
const mouse = withMouse('子组件')

setState方法

1.使用'this.state({})',不能同步获取修改后最新的值,'this.setState()'是异步的
2.推荐使用'this.setState((state, props) => {return {}})',获取的都是最新的值
3.在状态更新完后,立即执行某个操作(页面完成重新渲染),使用'this.setState'第二个参数
'this.setState(
    (state, props) => {return {}},
    () => {
        console.log('状态更新后立即执行')
    }
)'

纯组件:PureComponent

纯组件:PureComponentReact.Component功能相似
区别:PureComponent内部自动实现了shuldConponentUpdata钩子,不需要手动比较
1.纯组件内部的对比是shallow compare(浅层对比)
2.state和props的值为引用类型时,应该创建新数据,不是直接修改属性中的值
//   const newObj = {...obj, num: 1} // 创建新数据
//   const newList = [...list, {num: 1}] // 创建新数据
//   this.setState({
//       obj: newObj
//      list: newList
//   })
class App extendds React.shuldComponent{
    rennder() {
        return (
            <div>纯组件</div>
        )
    }
}

路由

npm i react-router-dom
1. 导入import { BrowserRouter as Router, Route, Link } from 'react-router-dom'
       import { HashRouter as Router, Route, Link } from 'react-router-dom'
2. 使用Router组件包裹整个组件
3. 指定入口
4. 指定出口
Link: 导航菜单
编程式导航:this.poprs.history.push('/home'), 
返回:this.poprs.history.go(n)
默认路由: path="/"
匹配模式:
    react默认是模糊匹配,以path开头的都会匹配成功
    添加exact属性,让其变成精确匹配:<Router exact path="/first" component={first}></Router>


const first = () => <p>页面一</p>
<Router>
    <div className="App">
        // 路由入口
        <Link to="/first">页面一</Link>
        // 路由出口,要展示的组件
        <Router path="/first" component={first}></Router>
    </div>
</Router>


redux

npm i redux
import { createStore } from 'redux'
// 创建store
const store = createStore(reducer)
// 创建state