React基础笔记2

一、生命周期函数

挂载卸载过程

constructor               props context

componentWillMount      服务器与客户端

componentDidMount      ajax请求

componentWillUnmount      清除动画

 

更新过程

componentwillRecieveUpdata(nextProps)

shouldComponentwillupdata(nextProps,nextState) 组件渲染监听

componentDidupdata()

componentWillupdata

render 更新组建

二、网络请求与反向代理

1、网络请求

   下载: npm i -S axios

// 组件挂载完毕后,执行的方法  只执行一次
componentDidMount() {
    axios.get('http://localhost:3000/data/users.json')
      .then(ret => {
        console.log(ret);
      })
  } 

2、反向代理

  下载:npm i -S http-proxy-middleware

  新建:setupProxy.js

复制代码
const {createProxyMiddleware: proxy} = require('http-proxy-middleware')

module.exports = app => {
  app.use('/api', proxy({
    target: 'http://localhost:8082',
    changeOrigin: true,
    pathRewrite: {
      '^/api': ''
    }
  }))
}
复制代码

 三、高阶组件(HOC)

  一个函数,传给它一个组件,它返回一个新的组件

  • 首先创建一个高阶组件函数
  • 指定函数参数,参数应该以大写字母开头
  • 在函数内部创建一个类组件,提供复用的状态逻辑代码并返回
  • 在该组件中,渲染参数组件,同时将状态通过prop传递给参数组件
  • 调用该高阶组件,传入要增强的组件,通过返回值拿到增强后的组件,并将其渲染到页面

1、普通写法

定义高阶组件

复制代码
import React, { Component } from 'react';
// Fragment jsx不会解析为html,但是它能当作 顶级元素  相当于vue中的template
// react提供一种简写 <></>

// 高阶组件是一个函数且 参数 是一个首字母要大写的组件
function withCmp(Cmp) {
  // 需要一个类组件且此组件要有返回
  return class HocCmp extends Component {
    // 渲染
    render() {
      // let title = this.props.title+'----...'
      return (
        <>
          <h1>头部</h1>
          {
            // 子组件 通过props传给参数组件
          }
          <Cmp {...this.props}></Cmp>
          <h4>底部</h4>
        </>
      )
    }
  }
}
export default withCmp
复制代码

调用高阶组件

复制代码
import React, { Component } from 'react'
// Home组件增强一些功能,使用此组件就自带头和尾,但是有时候又可不没有
// 对于Home组件使用高阶组件进行包裹
import Home from './pages/Home'

// 导入高阶组件 函数
import hocCmp from './hoc/withCmp'
let Myhome = hocCmp(Home)
export default class App extends Component {
  state = {
    title: '我是一个标题',
    desc: '描述'
  }

  render() {
    return (
      <div>
        {/* 高阶组件 */}
         <Myhome state={this.state} /> 
        <Home title={this.state.title} />
      </div>
    )
  }

}
复制代码

2、装饰器渲染

装饰器是一种函数,写成 @函数名

1、安装:npm i -D customize-cra react-app-rewired

2、修改package.json文件中scripts命令

  "scripts": {
    "start": "react-app-rewired start",
    "build": "react-app-rewired build",
}

3、创建config-overrides.js配置文件

复制代码
// 环境是一个commonjs规范环境
const path = require('path')
// customize-cra 把webpack配置定义成方法,方便使用调用,不用去写webpack配置
const { addDecoratorsLegacy, override } = require('customize-cra')

// 自定义一些webpack配置 定义成函数
const customize = () => (config, env) => {
  config.resolve.alias['@'] = path.join(__dirname, 'src')
  return config
}
// 模块导出  override=> 把你现在的配置和react中的webpack配置合并,它优先级更高
module.exports = override(
  // 让webpack支持 decorator
  addDecoratorsLegacy(),
  customize()
)
复制代码

4、使用装饰器

不用的写法

装饰器写法

 解决警告问题

我们解决这个警告 需要在根目录配置一个tsconfig.json 文件

{
    "compilerOptions": {
        "experimentalDecorators": true,
        "allowJs": true
    }
}

3、memoization(计算属性-记忆组件)

  连续两次相同传参,第二次会直接返回上次的结果,每次传参不一样,就直接调用函数返回新的结果,会丢失之前的记录,并不是完全记忆,可以在它的参数中传入state数据从而实现了类似Vue中的计算属性功能

   安装:npm i -S memoize-one

复制代码
# 引入
import memoizeOne from 'memoize-one'

# 使用
getValue = memoizeOne(
    (x,y) => x+y
)

# 调用
render(){
let total = this.getValue(this.state.x, this.state.y)
return <div>{total}</div>
}
复制代码

4、memo(自带)

  React.memo()是一个高阶函数,它与 React.PureComponent类似,但是一个函数组件而非一个类

复制代码
import React from 'react'
export default React.memo(
    props => {
      console.log('child---render')
      return (
          <div>{props.title}</div>
      )
    }
)
复制代码

三、状态管理(redux)

  项目组件的数量和层级也变得越来越多,越来越深,此时组件间的数据通信就变得异常的复杂和低效,为了解决这个问题,引入了状态管理(redux)从而很好的解决多组件之间的通信问题。

                

 

  安装:npm i -S redux

三大原则

  • 单一数据源  store
  • State 是只读的
  • 使用纯函数(reducer)来执行修改

          

 

 

复制代码
import {createStore} from 'redux'
// 数据源
const defaultStore={
    name:'张珊'
}
// 不能直接修改state
function reducers(state=defaultStore,action){
    try {
        if(action.type=='incr'){
            return {
                name:'sad'+state.name
            }
        }
    } catch (error) {
        return state
    }
}
// 创建仓库
const store=createStore(
    reducers,
    window._REDUX_DEVTOOLS_EXTENSION__&&window.__REDUX__DEVTOOLS_EXTENSION__()
)
// 导出
export default store
复制代码

app.jsx

复制代码
import React, { Component } from 'react'
import store from './index'
export default class App extends Comment {
    constructor(props) {
        super(props)
        // 1、获取数据store
        this.state = store.getState()
        // 2、订阅,数据修改自己更新状态数据
        store.subscribe(() => {
            this.setState(state => store.getState())
        })
    }
    render(){
        return(
            <div>
                <h3>{this.state.name}</h3>
                <button onClick={this.incr}>名称</button>
            </div>
        )
    }
    incr=()=>{
        // 3、action creator 必须是对象
        const actionCreator={
            type:'incr',
            payload:1
        }
        // 4、派发一个reducer任务
        store.dispatch(actionCreator)
    }
}
复制代码

 1、react-redux与redux-thunk

  react-redux:edux给我们提供一些高阶组件

  redux-thunk:redux异步操作

  npm i -S redux  react-redux redux-thunk

1)、全局共享store

  index.js

复制代码
import React from 'react'
import ReactDOM from 'react-dom'
import { Provider } from 'react-redux'
import store from './store'
import App from './App'
ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('root')
)
复制代码

 

2)、定义方法 action

  countAction.js  

复制代码
const incrAction = num => ({
    type: 'incr',
    payload: num
})
// 共有函数
export const incr = () => dispatch => {
    setTimeout(() => {
        let num = 10
        dispatch(incrAction(num))
    }, 2000);
}
复制代码

 

3)、app中调用方法  使用react-redux

  app.jsx

复制代码
import React,{Component} from 'react'
import {connect}from 'react-redux'
import * as actions from './store/actions/countAction'
/*
装饰器
参数1:吧redux的state映射成props
参数2 mapPropsToDispath 
 */
@connect(state=>(state),actions)
export default class App extends Component{
    render(){
        return(
            <div>
                <h3>{this.props.count}</h3>
                shouye
                <button onClick={this.incr}></button>
            </div>
        )
    }
    incr=()=>{
        this.props.incr()
    }
}
复制代码

4)、入口记录相关内容

  index.js

复制代码
import {createStore,applyMiddleware,compose} from 'redux'
import thunk from 'redux-thunk'
import reducer from './reducers/countReducer'
// 记录日志中间件
const mym=store=>next=>action=>{
    console.log(action,store)
    next(action)
}
// 配置chrom的dedux
const composeEnhancers=typeof window=='object'
&&window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__?
window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({}):compose
const engancer=composeEnhancers(
    applyMiddleware(thunk,mym)
)
// 导出
export default createStore(
    reducer,
    engancer
)
复制代码

5)、定义数据源

  countRedycer.js

复制代码
import CountMethod from '../methods/CountMethod'
const defaultState={
    count:1
}
export default (state=defaultState,action)=>{
    try {
        return CountMethod[actions.type](state,action.payload)
    } catch (error) {
        return state
    }
}
复制代码

6)、整合数据返回对应的值

复制代码
// 处理
class CountMethod{
    incr(state,data){
        return {
            count: state.count+data
        }
    }
}
export default new CountMethod
复制代码

 

四、路由

  • 前端路由功能:让用户从一个视图(组件)导航到另一个视图(组件)
  • 前端路由是一套映射规则,在React中,是URL路径与组件的对应关系
  • 使用React路由简单来说,就是配置路径和组件

                                  

npm i -S react-router-dom

使用路由

1、定义路由模式 index.js

复制代码
import React from 'react'
import reactDom from 'react-dom'
import App from './App.jsx'
// 全局共享store
import { Provider } from 'react-redux'
import {HasRouter as Router} from 'react-router-dom'
import store from './store'
reactDom.render(
    <Provider store={store}>
        <Router>
        <App />
        </Router>
    </Provider>,
    document.querySelector('#root')
复制代码

2、定义路由导航

复制代码
import React,{COmponent} from 'react'
import { Route } from 'react-router-dom'
// 导入相关模块
import Home from './views/home'
import News from './views/News'
class App extends Comment{
    constructor(props){
        super(props)
    }
    render(){
        return(
            <>
                {/* 
                    path:路径
                    component:渲染的组件
                    exact:严格匹配

                */}
                <Route exact path='/' component={Home}></Route>
                <Route  path='/news' component={News}></Route>
            </>
        )
    }
}
复制代码

声明式导航

使用LinkNavLink组件完成

 

Link :组件最终会渲染为 HTML 标签 <a>

 

NavLink:给已经渲染的元素添加参数

 

复制代码
// react中的路由规则都是以组件的方式定义


import { Route, Link, NavLink } from 'react-router-dom'


// 导入渲染的视图组件


import Home from './views/Home'


import News from './views/News


<li><NavLink exact activeClassName="active" to="/">首页</NavLink></li>


<li><NavLink activeClassName="active" to="/news">新闻列</NavLink></li>


{/* path访问的uri路径  component就是匹配成功后渲染的组件 */}


{/* exact 严格匹配 */}


{/* Rouet组件中匹配成功的渲中会自动在this.props添加路由导航相关属性方法 */}


<Route exact path="/" component={Home} />


<Route path="/news" component={News} />
复制代码

 

路由参数

 

    <Route path=’/aa/:id’ component={Main}>

 

  • params

 

    在路由目标页面中通过 this.props.match.params

 

  • query

 

    通过地址栏中的 ?key=value&key=value,通过 this.props.location.search

 

  • state

 

    隐式转参,一点用于数据的收集 this.props.location.state

 

posted @   久宇诗  阅读(85)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示