React-学习笔记

React

概念:

​ 数据单向流

脚手架使用:

安装

npx i -g create-react-app

创建项目

create-react-app <项目名>

目录结构:

  • 加载页面 public\index.html
  • 入口文件src\index.js

主要的三个包:

  • react 引入React对象
  • react-dom 实现页面挂载

组件:

函数组件(无状态组件):

​ 没有this, his—>undefined

//函数组件
// const Node = ()=>{
//     return (
//         <div>
//             <h1>我是函数组件</h1>
//         </div>
//     )
// }


ReactDOM.render(
    Node(),
    document.getElementById('root')
)

类组件(状态组件):

​ this指向实例

// 类组件--状态组件
// 先定义一个普通类,然后继承Component类,此类就为一个类组件
// 在继承过来的React.Component类中有一个必须实现的render方法

// class Node extends React.Component{
//    render(){
//        return(
//            <div style={{width:500,height:500,backgroundColor:'red',}}>
//                <h1>我是类组件</h1>
//            </div>
//        )
//    }
// }



ReactDOM.render(
    <Node/>,
    document.getElementById('root')
)

数据绑定

​ 语法:{}

import React, { Component } from 'react'

export default class Index extends Component {
    fun(){
        console.log('fun函数');
        console.log(this);
    }
    fun1(){
        console.log('fun1函数');
        console.log(this);
    }
    fun2(){
        console.log('fun2函数');
        console.log('this:',this);
        console.log('arguments',arguments);
    }
    render() {
        return (
            <div>
                <p onClick={()=>{
                    console.log('this:',this);
                }}>点击事件-直接写在标签内'this-Index组件'</p>
                <hr/>
                <button onClick={this.fun}>render外部的方法,this.函数名,函数内部thisundefined</button>
                <hr/>
                <button onClick={this.fun1.bind(this)}>render外部的方法,使用bind(this),改变this指向-Index</button>
                <hr/>
                <button onClick={this.fun2.bind(this,new Date(), 'today', 21)}>传值方法</button>
            </div>
        )
    }
}

遍历渲染:

import React, { Component } from 'react'
export default class mapRender extends Component {
    render() {
        //定义一个空数组
        let arr = []
        //向空数组中添加10条数据
         for (let i = 0;i<10;i++){
             arr.push(
                 <li key={i}>
                     <span>我的待办事项-{i+1}</span>
                     <span>状态:未处理</span>
                 </li>
             )
         }
        return (
            <div>
                <h1>待办事项列表</h1>
                <hr/>
                <ul>
                    { arr }
                </ul>
                <hr/>
                <h1>数组的遍历渲染2</h1>
                <ul>
                    {
                        //定义一个长度为10的空数组。并填充值
                        Array(10).fill({title:'我的待办事项--',state:'完成状态:'}).map((v,i)=>{
                            //定义一个变量保存value 的值,并改变
                            let item = v.title+(i+1)
                            return(
                                <li key={i}>
                                <span>{item}</span>
                                <span>{v.state}</span>
                                </li>
                            )
                        })

                    }
                </ul>
                <hr/>
                <h1>条件渲染</h1>
                {<Tj/>}
                <hr/>
                <h1>父传子</h1>
                {<FZ/>}
            </div>
        )
    }
}

条件渲染:

条件渲染和状态管理

import React, { Component } from 'react'
//条件渲染
export default class conditionRender extends Component {
    state={
        //定义一个参照值flag=true
        flag : false
    }
    change(){
        console.log('this:',this);
            this.setState({
                flag:!this.state.flag
            },
            
            )
        }
    render() {
        //定义一个参照值flag=true
        // let flag = true
        
        return (
            <div>
                
                <hr/>
                {
                    this.state.flag
                    ?
                    <h2> flag = true</h2>
                    :
                    <h2>flag = false</h2>
                }
                {/* <button onClick={
                    ()=>{
                        this.change()
                    }
                }>改变flag的值</button> */}

                 <button onClick={this.change.bind(this)}>改变flag的值</button>
            </div>
        )
    }
}

事件绑定:小驼峰命名οnclick=>onClick

数据类型检测:

​ 安装:npm i -s prop-types

父子组件:

父传子:

import React, { Component } from 'react'
//父组件
import Son from './day02/son'
export default class father extends Component {
    state={
        lilu:0.4
    }
    handel(){
        this.setState({
            lilu:(Math.random()).toFixed(3)
        })
    }
    render() {
        return (
            <div>
            //传递给子组件,若是方法注意改变this指向
                {<Son lilu={this.state.lilu} change={this.handel.bind(this)}/>}
            </div>
        )
    }
}


import React, { Component } from 'react'
//子组件
export default class son extends Component {
    state={
        //贷款金额
        num:10000
    }
    render() {
        console.log('fghjk:',this);
        return (
            <div>
                <h1>贷款金额:{this.state.num}</h1>
                <hr/>
                <h1>当前利率:{this.props.lilu}</h1>
                <hr/>
                <h1>当前利息:{this.state.num*this.props.lilu}</h1>
                <hr/>    
                    //父组件改变了this指向过后,在子组件的props中可直接使用父组件的方法
                <button onClick={this.props.change}>改变利率</button>

            </div>
        )
    }
}

生命周期(类组件)

react 16.8 之后才有函数组件

挂载阶段

  • constructor() 用于定义state 已不常用

  • 特殊的 getDerivedStateFromProps ()

  • render() 渲染生命周期,在更新的时候会执行

    • render中的setSate不会合并操作,不建议在render中执行setSate
  • componentDidMount() 挂载完成的生命周期,常用于初始化数据

更新阶段

  • shouldComponentUpdate():通常在性能优化的时候使用,此生命周期是在更新之前执行,因此可用于页面渲染优化,它需要返回一个Boolean值,为true则进行更新,反之则不更新
  • render()
  • **componentDidUpdate() **: 更新后立即调用,如:设置一个盒子的高度,然后去动态获取盒子的高度的方法可以在这个生命周期中执行

销毁

  • componentWillUnmount():销毁前调用

函数组件与HOOKS

函数组件:

没有this,没有state

HOOKS:

  • 在函数组件中可以使用该 hook 创建类似于 class 组件中的 state

    const [state, setState] = useState(initialValue)
    
    • useState() 返回的是数组,数组第一个元素为状态,第二个元素为修改状态的函数,initialValue 为状态初始值
  • useEffect 副作用函数 – 它可以用于监听数据变化,来做一个事情,类似Vue中的watch属性;它还可以实现类组件的生命周期(componentDidMount、componentWillUnmount)的功能
    1)如果只传入一个方法参数,相当于监听所有的 state 数据
    2)第二个参数为一个数组(React.DependencyList),在数组中传入需要监听的数据,这样的话,只有被监听的数据发生变化,才会执行函数方法

      	```
      	第一个参数为 callback 回调函数,即执行副作用操作的函数
      	
      	第二个参数为依赖项的数组
      	
      	`useEffect()` 相当于是 class 组件中 `componentDidMount()`、`componentDidUpdate()`、`componentWillUnmount()` 钩子函数的结合。
      	
      	第二个参数为空数组,相当于模拟的是 `componentDidMount()`
      	
      	第二个参数数组中有依赖项,相当于模拟的是 `componentDidUpdate()`,即依赖项发生变化,会重新执行 callback 回调函数
      	
      	第一个参数 callback 回调函数中如果有返回一个函数,该返回的函数相当于模拟的是 `componentWillUnmount()`
      	```
    
  • useMemo 监听数据变化,必须返回一个新数据,类似Vue中的computed属性
    1)使用的时候,两个参数必须全部传递
    2)第一个参数为一个回调方法,必须有返回值
    3)第二个参数为依赖数据项

    useMemo方法接收工厂函数,() => any 这是一个函数,并且这个函数需要有一个返回值,它的依赖项一定要写,并且这个方法会返回一个值
        // 它相当于Vue的computed属性,它会根据依赖项的变化来执行回调函数,更新数据并缓存数据
        const newFullName = useMemo(function() {
            return firstName + ' -- ' + secondName
        }, [firstName, secondName])
    
  • useCallback 用于缓存定义的方法,避免函数组件在执行更新的时候对同一个方法进行多次定义

    // 在函数组件中可以使用useCallback来定义和缓存方法
    // useCallback(callback: (...args: any[]) => any, deps: React.DependencyList): (...args: any[]) => any
    // 用于定义方法
    // 依赖为定义的方法需要使用到的数据,当数据发生变化的时候,方法会被更新
    const clickEvt = useCallback(function() {
        console.log(arguments);
        console.log('useCallback: ', firstName, secondName);
    }, [firstName, secondName])

Context:

​ a、使用 createContext 方法创建一个 Context 对象
​ b、在需要进行数据传递的地方使用 Context.Provider 组件 value 进行数据下发
​ c、在需要使用数据的地方使用 Context.Consumer (注意点:此处的Consumer必须与Provider成对使用)组件的回调方法,所有的数据在回调方法的入参对象中,来进行数据消费、使用
​ d、因为React中,所有的数据更新,会触发组件更新的数据只有 state 数据

import React, { Component, createContext } from 'react'

// Context在使用的是偶一定要注意:Provider和Consumer必须成对使用
const Context = createContext()

// 导出当前Context的Consumer方法
export const Consumer = Context.Consumer

......省略
//函数内部的render()
render() {

        let store = {
            list: this.state.list,
            handleMethod: this.handleMethod
        }

        return (
            // 在React中如果一个对象有一个组件,可以使用JS的方法来进行组件编写
            // Provider必须有一个value属性
            <div>
                <Context.Provider value={ store }>
                    <div>
                        <h1>待办页面</h1>
                        <Form/>
                        <List list={this.state.list}/>
                    </div>
                </Context.Provider>
           
            </div>
        )
    }
    

或者单独提出来写

//创建一个context.js文件
//引入createContext
import { createContext } from 'react'

// 创建 Context 对象
const TodoContext = createContext()

// 解构组件
const {
  Provider: TodoProvider, // 生产者,主要用于保存数据
  Consumer: TodoConsumer, // 消费者,主要用于使用数据
} = TodoContext

// const TodoProvider = TodoContext.Provider

// 导出
export {
  TodoProvider,
  TodoConsumer,
  TodoContext
}

//使用时APP文件中使用
 <TodoProvider value={{
        todos: this.state.todos,
        add: this.addTodoItem,
        toggle: this.toggleTodoItem,
        remove: this.removeTodoItem
      }}>
          
          被包裹的组件都可以使用TodoConsumer来接收TodoProvider的值来使用
          
  </TodoProvider>
包裹,
在Item中使用
    return (
      <TodoConsumer>
        {
            // 在使用Consumer的时候,所有在对应的Provider上提供的数据,都将在组件的回调方法中进行入参
            // Consumer只能在对应的Provider中使用
           arg => {
                        console.log(arg);
                        return (
                             <button onClick={
                                    () => {
                                        arg.toggle()
                                    }
                                }>切换</button>
							
							<button onClick={
                                    () => {
                                        arg.remove()
                                    }
                                }>删除</button>
                        )
                    }
        }
      </TodoConsumer>
    )
    
    
    
    

 !!!!! connect !!!!
 上面的Consumer使用过于麻烦,所以react-redux中提供了connect高阶组件,将数据和方法挂载到齐props上

// connect实现了两个功能:跨组件传值(实现了Context.Consumer的功能),
//还实现了Redux.subscribe的功能
import { connect } from 'react-redux'
 const mapStateToProps = state =>{
        return {
            count:state.count
        }
        
    }
// connect(mapStateToProps,mapDispatchToProps)
// 参数1:数据   参数2:方法
export default connect(mapStateToProps)(Index)

HOC:高阶组件

  • HOC及CRA中装饰器模式的写法支持
    a、HOC–高阶组件、全称High Order Component,一个方法返回一个组件即为一个高阶组件,它可以实现类似于Vue的插槽功能,只是这个组件只能是顶层组件;它原由高阶函数的思想来实现的,主要是在开发业务的时候,需要每一个组件都是一个纯功能组件,也就是每一个组件只实现具体某一个功能,类似纯函数(slice、map、filter、concat);它主要的思想是:功能柯里化、业务解耦
    b、HOC组件的使用方法,在使用的页面把自己的组件作为HOC组件的方法参数,并得到一个功能增强的组件
    c、CRA的第三方配置库react-app-rewired使用
    c0、安装:cnpm i -D react-app-rewired
    c1、修改package.json文件的命令
    c2、添加config-overrides.js文件
    c3、添加自定义重装webpack配置库:cnpm i -D customize-cra
    c4、在配置文件中添加:override、addDecoratorsLegacy库用于支持ES6装饰器的语法,提高HOC组件的可读性

Redux

文档

Redux 是 JavaScript 应用的状态容器,提供可预测的状态管理。

Redux 是一个小型的独立 JS 库,redux 与 react 没有任何的关系,Redux 除了和 React 一起用外,还支持其它界面库。

要在 react 中使用 redux,需要安装绑定库:react-redux

概念

  • store:仓库,用于集中式管理 redux 中的状态
  • state:需要共享管理的状态数据
  • action:描述发生了什么,是一个普通对象,通常具有 type(动作的类型) 与 payload(动作所携带的有效载荷) 属性,如:
{
  type: 'ADD_TO_CART',
  payload: {
    id: 1,
    title: '标题',
    price: 9.9,
   	amount: 1,
    checked: false
  }
}
  • action creator:函数,用于创建并返回 action 对象
  • reducer:纯函数,主要用于同步更新状态。该函数会传递 state 与 action 作为参数,返回新的 state 值。reducer 函数是唯一能够更新 state 状态的地方。

纯函数:一个函数的返回结果只依赖于它的参数,并且在执行过程里面没有副作用,我们就把这个函数叫做纯函数

Reducer 必需符合以下规则:
1. 仅使用 state 和 action 参数计算新的状态值
2. 禁止直接修改 state。必须通过复制现有的 state 并对复制的值进行更改的方式来做 不可变更新(immutable updates)。
3. 禁止任何异步逻辑、依赖随机值或导致其他“副作用”的代码
  • dispatch:函数,传递 action 作为参数,在函数体内部调用 reducer(state, action) 实现状态更新,并执行一些其它注册的监听任务(如响应式渲染刷新页面)。

使用

安装
$ npm i redux
# 或
$ yarn add redux
创建目录

store 目录用于保存所创建 store 对象相关

reducers 目录用于保存同步更新状态的 reducer 函数相关

actions 目录用于保存 action 对象(action creator创建)相关

reducer
const initialState = {

}

export default (state = initialState, { type, payload }) => {
  switch (type) {

  case typeName:
    return { ...state, ...payload }

  default:
    return state
  }
}

如果应用中有多种类别的状态数据需要管理,可定义不同的 reducer 函数来处理,最后将各独立的 reducer 合并为一个根 reducer 即可:

import { combineReducers } from 'redux'
import todosReducer  from './todos'
import usersReducer from './users'

export default combineReducers({
  todos: todosReducer,
  users: usersReducer
})
store
import { createStore } from 'redux'
import rootReducer from '../reducers'

const store = createStore(rootReducer)

export default store
action creator
import { ADD_TODO_ITEM } from "./constants";

export const addActionCreator = title => ({
  type: ADD_TODO_ITEM,
  payload: {
    id: Math.random(),
    title,
    completed: false
  }
})
安装 react-redux
$ npm i react-redux
保存 redux 的 store
import React from 'react'
import { render } from 'react-dom'
import { Provider } from 'react-redux'
import store from './store'
import App from './App'

import 'bulma/css/bulma.min.css'

render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('root')
)

利用 react-redux 库中提供的 Provider 组件,缓存 store

在组件中连接 store
import { connect } from 'react-redux'

// 函数,用于将 store 中的状态数据映射到组件中
// 函数返回值是一个对象,该对象会被合并到组件的 props 中
const mapStateToProps = state => ({
  todos: state.todos.todos
})

// 函数,用于 dispatch (触发) action 调用 reducer 更新状态
const mapDispatchToProps = null

// connect() 调用后返回一个函数,该函数为 HOC
const hoc = connect(mapStateToProps, mapDispatchToProps)

export default hoc(TodoList)
const mapStateToProps = null

// 函数的返回值是一个对象,会被合并到组件的 props 中
const mapDispatchToProps = dispatch => ({
  toggle: id => dispatch(toggleActionCreator(id)),
  remove: id => dispatch(removeActionCreator(id))
})

export default connect(mapStateToProps, mapDispatchToProps)(TodoItem)

异步 Action

使用 redux-thunk 中间件

安装:cnpm i -S redux-thunk

import { createStore, applyMiddleware } from 'redux'
import reducer from './reducer'
import thunk from 'redux-thunk'


// createStore(reducer: Reducer, enhancer?: StoreEnhancer)
// 在使用中间件的时候,一定要用一个applyMiddleware方法来进行注入
export default createStore(reducer, applyMiddleware(thunk))

react-redux

文档

API

Provider 组件

使得所有嵌套在内部的后代组件都可以访问到保存在 Provider 中的 redux 中 store内容,使用 store 属性去缓存 redux 的 store 对象。

connect() 方法:

使用 connect() 方法来连接 react 组件与 redux 的 store

function connect(mapStateToProps?, mapDispatchToProps?, mergeProps?, options?)
  • mapStateToProps,函数,传递 state 参数,返回一个对象,主要用于处理 redux 的 store 中的 state。任何时间 store 中的 state 修改了,都会重新计算返回值。返回值(对象)会被合并到组件的 props 中。
  • mapDispatchToProps,函数,传递 dispatch 参数,返回一个对象,主要用于处理 redux 中 store 的 dispatch。通常返回的对象中包含的就是一个个的方法,各方法体内部实现 dispatch(action) 操作,返回的对象会被合并到组件的 props 中

React路由

安装

npm i -S react-router-dom

组件使用

  • HashRouter:创建 hash 路由模式

  • BrowserRouter:history 路由模式

  • Route:配置静态路由,访问 path 路径时渲染对应的 component 组件

    <Route path="" component={} render={}>{children}</Route>
    
    • path:URL 路径
    • component:待渲染的组件
    • render:渲染函数,可用于复杂结构的渲染,component 与 render 不能同时出现,如果同时出现,会忽略 render 的渲染
    • children:类似于 render 实现复杂结构的渲染,是 react 元素结构

动态传参

  • 动态路由,在定义路由的时候在路由字符串上添加(/:paramsName)属性,在页面上使用props.match.params.paramsName来接收参数;
  • 在页面上的history.push()方法中传递一个对象,{pathname: 路由名字, state: {key-value形式来传递参数}},在页面上使用props.location.state对象来接收数据;
  • 在Route中使用render方法,routeParams => RouteComponent,对应的数据在页面上使用props直接接收;
 {/* 动态路由,在页面使用的时候,需要在match.params对象中获取数据 */}
     <Route path="/login/reg/:id" component={Register}/>

路由匹配时:需要使用精确匹配模式 => exact

路由跳转
{/* 用它来实现默认路由跳转 */}
 	<Redirect path="/" to="/login" exact/>
{/* 把Redirect认为是一个default分支 */}
{/* 如果用户输入的路由在系统中不存在 */}
	<Redirect to="/404"/>
{/* Lnik跳转 */}
<Link to="/home">登录</Link>
路由权限
<Route path="/home" render={
        routeProps => {
          // routeProps => location,match,history
          // 对home路由进行拦截,直接返回到login路由
         // sessionStorage中去去一个数据,如果数据存在进入页面,否则直接跳转到'/login'
		let token = sessionStorage.getItem('x-token')
        return (
             !token
             ?
             <NotRight/>
             :
             <Home value="10" {...routeProps}/>
                )
           }

路由高阶组件

withRouter():高阶组件,可访问 history 对象的属性和最近的 ,当路由渲染时,withRouter会将已更新的match、history、location属性传递给被包裹的组件

项目搭建

  • 脚手架构建结构 creact-react-app <项目名>

    • 建立入口文件src\index.js
  • 建立 Views 视图文件夹

    • APP.js
  • 建立通用的样式文件

    • 安装less解析器:cnpm i -D less less-loader@7

    • 定义用户爱好的样式

       const [style, setstyle] = useState(false)
          return (
              <div className={style ? "样式名1":"样式名2"}>
                  入口文件汇总处
              </div>
          )
      
  • eject webpack 配置:

    • 安装:cnpm i -D react-app-rewired customize-cra,自定义脚手架加载器
    • 修改配置文件
    package.json -> scripts -> build、start命令 react-scripts -> react-app-rewired
    
    • config-overrides.js文件
    const {
        override,
        addLessLoader
    } = require('customize-cra')
    
    module.exports = override(
        addLessLoader()
    )
    
  • 全局状态数据管理,建立store文件:

    • 安装:npm i -s redux

    • 创建 store\index.js 文件

      import { createStore, applyMiddleware } from 'redux'
      import thunk from 'redux-thunk'
      
      import RootReducer from './reducer'
      
      export default createStore(RootReducer, applyMiddleware(thunk))
      
      //applyMiddleware,thunk 处理一步action
      
    • 创建 store\reducer\index.js

      import { combineReducers } from 'redux'  //combineReducers 合并导出reducer
      
      import common from './commonReducer'//方法
      //combineReducers接收对象
      export default combineReducers({
          common
      })
      
    • 创建store\reducer\commonReducer.js

      import { SET_TOKEN, SET_USERINFO } from '../action/types'
      
      const initState = {
          token: 'init token',
          userInfo: {}
      }
      
      export default function(state = initState, action) {
          switch (action.type) {
              case SET_TOKEN:
                  return {
                      ...state,
                      token: action.token
                  }
              case SET_USERINFO:
                  return {
                      ...state,
                      userInfo: action.userInfo
                  }
              default:
                  return JSON.parse(JSON.stringify(state))
          }
      }
      
    • 创建 store\action\types.js ,用于定义reducer方法中的 type 值

      //标准写法
      //symbol => Symbol用于生成项目全局的一个唯一值,它的参数只接收string和number类型数据
      export const SET_TOKEN = Symbol('type')
      export const SET_USERINFO = Symbol('type')
      
    • 创建 store\action\index.js 异步方法操作

      import { SET_TOKEN, SET_USERINFO } from './types'
      
      export function tokenAct(token) {
          return {type: SET_TOKEN, token}
      }
      
      export function userinfoAct() {
          return async dispatch => {
              let userInfo = await asyncFunc()
              dispatch({type: SET_USERINFO, userInfo})
          }
      }
      function asyncFunc() {
          return new Promise(resolve => {
              console.log('------------------ promise start');
              setTimeout(() => {
                  console.log('------------------ promise end');
                  resolve({id: 'admin', name: '超级管理员'})
              }, 1500)
          })
      }
      
  • withRouter: 把不是通过路由切换过来的组件中,将react-router 的 history、location、match 三个对象传入props对象上

  • 路由懒加载(拆包)

    安装:cnpm i -S react-loadable

    使用:

    function myLoader(loader) {
        return loadable({
            loader,
            loading: function() {
                return (
                    <div>Page Loading...</div>
                )
            }
        })
    }
    
    const Login = myLoader(() => import("./login"))
    
  • api接口

    • 请求发送

      1、安装依赖包:cnpm i -S axios

      2、实现axios的基本封装:

      // 引入 axios 库
      import axios from 'axios'
      
      // 设置开发环境与生产环境下 baseURL
      // const baseURL = process.env.NODE_ENV === 'development' ? '开发环境下的模拟接口' : '生产环境的真实接口'
      // const baseURL = process.env.NODE_ENV === 'development'
      //   ? 'http://rap2api.taobao.org/app/mock/284783' // 开发环境
      //   : 'http://www.xiongmaoyouxuan.com' // 生产环境
      const baseURL = 'http://www.xiongmaoyouxuan.com'
      
      // 创建 axios 实例
      const service = axios.create({
        baseURL,
      })
      
      // 请求拦截
      service.interceptors.request.use(config => {
          let token = 'my token'
      
          if (!token) {
              return Promise.reject({code: 0, message: '没有通过请求拦截'})
          } else {
              config.headers.token = token
              return config
          }
      })
      
      // 响应拦截
      service.interceptors.response.use(config => {
        // 有响应数据返回,则关闭加载提示
        Toast.clear()
        // 判断响应返回结果
        if (config.status >= 200 && config.status < 300) {
          // 获取到后端返回数据
          const resData = config.data
          // 判断
          if (resData.code === 200) {
            return resData.data
          } else {
            const e = new Error('接口 code 不为 200')
            e.error = resData
            Promise.reject(e)
          }
        } else {
          const err = new Error('后端接口返回 status 不为 200')
          err.error = config
          Promise.reject(err)
        }
      })
      
      // 导出 axios 实例
      export default service
      
      
    • 实现请求代理:

      1、安装依赖包:cnpm i -D http-proxy-middleware

      2、新建代理文件:src/setupProxy.js

      const { createProxyMiddleware } = require('http-proxy-middleware')
      
      module.exports = app => {
          app.use(
              '/apis',
              createProxyMiddleware({
                  //代理的目标地址
                  target: 'http://www.shuiyue.info:14600',
                  //路径重写
                  pathRewrite: {'/apis': ''},
                  
                  changeOrigin: true
              })
          )
      }
      

补充:

set()

var a = [1,2,3,4,5,3,2,4,1]
new Set(a)//得到的是一个对象
Array.from(new Set(a))
注:只能用于纯数组,若包含对象则不能去除重复对象

Symbol()可生成全局唯一值

var a = symbol(1)
var b = symbol(1)
a!=b
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
React 18是React的最新版本,它引入了一些新的功能和改进。在学习React 18时,你可以关注以下几个方面: 1. React组件:React组件是构建用户界面的基本单元。你可以使用React.createElement()函数或JSX语法来创建React元素和组件。React元素是不可变的,而React组件是可复用的。\[1\] 2. react-dom.development.jsreact-dom/client模块:这些模块提供了处理真实DOM的功能,包括Diff算法和渲染成真实DOM的过程。你可以在HTML文件中引入这些模块,并使用ReactDOM.createRoot()方法来渲染React的DOM。\[2\] 3. Hook:Hook是React中的特殊函数,它允许你在函数组件中添加状态和其他特性。例如,useState是一个Hook,它可以让你在函数组件中添加状态。你可以使用useState来定义和更新状态,并在组件中使用它们。\[3\] 在学习React 18时,你可以通过阅读官方文档、参考教程和实践项目来深入了解这些概念和用法。同时,你也可以与其他开发者交流和分享经验,加深对React的理解。 #### 引用[.reference_title] - *1* *2* *3* [2023年React18笔记【慕课网imooc】【尚硅谷】【Vue3+React18 + TS4考勤系统】](https://blog.csdn.net/qq_28838891/article/details/124598439)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值