react

基础内容

  1. 使用脚手架创建react项目

    npx create-react-app my-app
    
    //如果报错了就使用下面命令
    在npm uninstall -g create-react-app之后,我遇到了这个问题,这对我起了作用:
    
    npm cache clean --force
    npm cache verify
    npx clear-npx-cache以清除npx缓存。
    npx create-react-app your-app or npx create-react-app@latest my-app --use-npm
    
  2. 创建react元素-引入react --不推荐使用createElement,推荐使用jsx

    import React from 'react'
    let dom = react.createElement('h1',null,'111')
    
  3. jsx语法–需要babel编译处理脚手架中已经自动配置

    let dom = (<h1 className="title">111<h1>)
    //在jsx语法中class要写为className
    
  4. 渲染react元素-引入react-dom

    import ReactDOM from 'react-dom'
    ReactDOM.render(dom,document.getElementById('root'))
    //渲染多个时使用数组渲染
    ReactDOM.render([dom,dom1,dom2],document.getElementById('root'))
    
  5. 嵌入js表达式

    let name = JSX
    let dom = (<h1 className="title">{name}<h1>)
    
  6. 条件渲染

    const isLoading = true
    const loadData = () =>{
      if (isLoading) {
        return <div>loading...</div>
      }
      return <div>数据加载</div>
    }
    let dom = (<h1 className='title'>{loadData()}</h1>)
    
    ReactDOM.render(dom,document.getElementById('root'))
    
  7. 列表渲染

    const songs = [{id:1,name:"a"},{id:2,name:"b"},{id:3,name:"c"}]
    //注意要添加key,否则会报错
    let dom = (<ul>
        {songs.map(item=><li key={item.id}>{item.name}</li>)}
    </ul>)
    
    ReactDOM.render(dom,document.getElementById('root'))
    
  8. jsx样式处理

    <h1 style={{color:'red',background:'yellow'}}>jsx样式</h1>//不推荐
    
    //推荐使用类名处理样式
    import './index.css'//引入css文件
    
    let dom = (<h1 className="title">{name}<h1>)
    //css文件内容
    .title{
      color: red;
      text-align: center;
    }
    

组件

  1. 函数组件 – 函数名称必须以大写开头,必须有返回值 --无状态组件

    function Hello(){
    	return (
    		<div>函数组件</div>
    	)
    }
    //function Hello = ()=> <div>函数组件</div>//箭头函数
    ReactDOM.render(<Hello/>,document.getElementById('root'))
    
  2. 类组件 – 有状态组件

    //继承组件--类组件必须有render
    class Hello extends React.Component{
    	render(){
    		return (
    			<div>函数组件</div>
    		)
    	}
    }
    
  3. 组件抽离

    //Hello.js文件内容
    import React from "react"
    class Hello2 extends React.Component{
    	render(){
    		  return (
    			  <div>函数组件111</div>
    		  )
    	  }
      }
    
    export default Hello2
    
    //index.js文件内容
    import ReactDOM from 'react-dom';
    import Hello from './Hello'
    ReactDOM.render(<Hello/>,document.getElementById('root'))
    

事件处理

  1. 点击事件

    //函数组件事件处理程序
    function Hello(){
      function handleClick(){
          console.log("点我")
      }
      return (
         <button onClick={handleClick}>函数组件111</button>
      )
    }
    //类组件事件处理程序
    class Hello extends React.Component{
      // 事件处理程序
      handleClick(){
        console.log("点我")
      }
    	render(){
    		  return (
    			  <button onClick={this.handleClick}>函数组件111</button>
    		  )
    	}
    }
    
  2. 阻止事件触发

    function Hello(){
      function handleClick(e){
        e.preventDefault();
          console.log(e)
      }
      return (
         <a onClick={handleClick} href="https://www.baidu.com">函数组件111</a>
      )
    }
    

状态初始化

  1. class Hello extends React.Component{
      constructor(){
      	super()
       	this.state = {
          count:10
       	}
      }
      render(){
    		return (
    			<div>计数器{this.state.count}</div>
    		)
    	}
    }
    
  2. class Hello extends React.Component{
      state = {
        count:10
      }
      render(){
    		return (
    			<div>计数器{this.state.count}</div>
    		)
    	}
    }
    

修改状态

  1. 要使用setState修改数据–不能直接使用this.state.count++

    class Hello extends React.Component{
      state = {
        count:10
      }
      render(){
    		return (
    			<div>计数器{this.state.count}
          			<button onClick={()=>{
            			this.setState({
              			count:this.state.count +1
            		})
          			}}>+1</button>
          		</div>
    		)
    	}
    }
    
  2. this指向

    class Hello extends React.Component{
      state = {
        count:10
      }
      render(){ //render中的this指向组件实例
    		return (
    			<div>计数器{this.state.count}
          			<button onClick={()=>{//箭头函数中的this指向render,this指向所处的对象
            			this.setState({
              			count:this.state.count +1
            		})
          			}}>+1</button>
          		</div>
    		)
    	}
    }
    
    class Hello extends React.Component{
      state = {
        count:10
      }
      onIncrement(){
    	this.setState({//报错。。。this指向有问题 undefined
    		count:this.state.count +1
    	})
      }
      render(){ //render中的this指向组件实例
    		return (
    			<div>计数器{this.state.count}
          			<button onClick={this.onIncrement()}>+1</button>
          		</div>
    		)
    	}
    }
    
    解决方法一
    class Hello extends React.Component{
      state = {
        count:10
      }
      onIncrement(){
    	this.setState({//注意this指向,指向调用者
    		count:this.state.count +1
    	})
      }
      render(){ //render中的this指向组件实例
    		return (
    			<div>计数器{this.state.count}
          			<button onClick={()=>this.onIncrement()}>+1</button>
          		</div>
    		)
    	}
    }
    解决方法二
    class Hello extends React.Component{
      state = {
        count:10
      }
      this.onIncrement = this.onIncrement.bind(this)
      onIncrement(){
    	this.setState({//注意this指向,指向调用者
    		count:this.state.count +1
    	})
      }
      render(){ //render中的this指向组件实例
    		return (
    			<div>计数器{this.state.count}
          			<button onClick={this.onIncrement}>+1</button>
          		</div>
    		)
    	}
    }
    解决方法三
    class Hello extends React.Component{
      state = {
        count:10
      }
      this.onIncrement = this.onIncrement.bind(this)
      onIncrement = ()=>{
    	this.setState({//注意this指向,指向调用者
    		count:this.state.count +1
    	})
      }
      render(){ //render中的this指向组件实例
    		return (
    			<div>计数器{this.state.count}
          			<button onClick={this.onIncrement}>+1</button>
          		</div>
    		)
    	}
    }
    

表单处理

  1. 受控组件–表单绑定的对应的值,但react也想要控制表单的值

    state = {txt:''}
    
    <input type="text" value={this.state.txt} onChange={e=>this.setState({txt:e.target.value})}/>
    //通过绑定value
    //复选框通过绑定checked
    
    也可以通过name属性多项处理
    
  2. 非受控组件要使用ref

    //创建Ref
    this.txtRef = React.createRef()
    <input type="text" ref={this.txtRef} />
    console.log(this.txtRef.current.value)
    

组件通讯

  1. props–可以传递函数,表达式,默认为字符串–不能修改props

    <Hello name="jack" age={19} />
    
    function Hello(props){
    	console.log(props)
    	return (
    		<div>{props.name}</div>
    	)
    }
    
    class Hello extends React.Component(){
    	constructor(props){ //写了constructor之后就要传递props到supre
    		super(props)
    	}
    	render(){
    		return (
    			<div>{props.name}</div>
            )
    	}
    }
    
  2. 父组件给子组件传递数据

    class Parent extends React.Component{
    	state = {
    		name:"aaa"
    	}
    	render(){
    		return (
    			<div>
    				<Child name={this.state.name} />
    			</div>
            )
    	}
    }
    
    class Child extends React.Component{
    	render(){
    		return (
    			<div className="child">
    				<p>子组件,接收父组件的值{props.name}</p>
    			</div>
            )
    	}
    }
    
  3. 子组件传递数据给父组件

    class Parent extends React.Component{
    	state = {
    		parentMsg = ''
    	}
    	getChildMsg = data =>{
    		console.log('子组件传递的数据',data)
    		this.setState = {
    			parentMsg:data //将子组件的数据赋值给父组件
    		}
    	}
    	render(){
    		return (
    			<div>
    				<Child getMsg={this.getChildMsg} />
    			</div>
            )
    	}
    }
    
    class Child extends React.Component{
    	state = {
    		msg:"子组件的数据"
    	}
    	handleChick = ()=>{
    		this.props.getMsg(this.state.msg)//传递数据
    	}
    	render(){
    		return (
    			<div className="child">
    				子组件<button onClick={this.handleChick}>
    			</div>
            )
    	}
    }
    
  4. 兄弟组件传递值 – 将数据共享到同一个父组件中

    class Parent extends React.Component{
    	state = {
    		count: 0
    	}
    	//修改数据
    	setCount = ()=>{
    		this.setState({
    			count: this.state.count +1 
    		})
    	}
    	render(){
    		return (
    			<div>
    				<Child1 count={this.state.count} />
    				<Child2 setCount={this.setCount}/>
    			</div>
            )
    	}
    }
    const Child1 = props =>{
    	return <h1>计数器: </h1>
    }
    const Child2 = props =>{
    	return <button onClick={()=>props.setCount()}>计数器: </button>
    }
    
  5. 多层组件嵌套传递数据–Context

    const {Provider, Consumer} = React.createContext();
    
    <Provider value={/*共享的数据*/}>
    	父组件内容
        /*里面可以渲染对应的内容*/
    </Provider>
    
    <Consumer>
      子组件内容
      {value => /*根据上下文  进行渲染相应内容*/}
    </Consumer>
    
  6. children属性 类似于vue中的作用域插槽

    const App = props=>{
    	return(
    		<h1>组件标签的子节点</h1>
    		{props.children}
    	)
    }
    ReactDOM.render(<App><p>子节点</p></App>,document.getElementById('root'))
    
  7. prop校验–创建类型 array,bool,func,number,object,string

    ​ 也可以指定react元素类型 element

    ​ 必填项: isRequire

    ​ 特定结构的对象:shape({ })

    //约束props传入的类型
    安装prop-types(yarn add props-types/npm i props-types)
    
    import PropTypes from 'prop-types'
    
    const App = props=>{
    	const arr = props.colors
    	const lis = arr.map(item=>{<li key={index}>{item.name}</li>})
    	return(
    		<div>{lis}</div>
    	)
    }
    App.PropTypes = {
    	colors: PropTypes.array
    	add: PropTypes.func.isRequire //必填项的函数类型
    	option:PropTypes.shape({
    		colors: PropTypes.array
    		fontSize: PropTypes.number
    	})//特定类型
    }
    
    App.defaultProps = {
    	pageSize: 10//添加props默认值
    }
    

组件的生命周期–新版生命周期

  1. 只有类组件才有生命周期–以废除几个带will的生命周期

  2. 创建时(挂载阶段)

    constructor->render->componentDidMount
    constructor创建时就执行,一般用来状态初始化,为事件处理绑定this
    render每次组件渲染都会触发,不能调用setState
    componentDidMount组件挂载(完成DOM渲染)后,用来发送网络请求和DOM操作
    
  3. 更新时

    new props,setState(),forceUpdate()都会触发更新
    this.forceUpdate为强制更新
    render->componentDidUpdate
    componentDidUpdate(完成DOM渲染)后,用来发送网络请求和DOM操作,要setState()时要放在if中否则会导致递归更新
    
    componentDidUpdate(prevProps){
    	console.log(prevProps,'是更新前的数据',this.props,'是更新后的数据')
    }
    
    shouldComponentUpdate//更新时触发
    class Hello extends React.Component{
    	shouldComponentUpdate(nextprops,nextstate){
    		if(...){
    			return false //返回false就不会重新渲染
    		}
    	}
    }
    
  4. 卸载时

    componentWillUnmount页面消失是--执行清理工作
    
    componentWillUnmount(){
    	//清理定时器
    	clearInterval(定时器名称)
    }
    
  5. 不常用的钩子函数

    getDerivedStateFromProps//创建和更新时触发
    getSnapshotBeforeUpdat//更新时触发
    

高阶组件

  1. 创建一个函数,约定以with开头

  2. 参数为大写字母开头

  3. 函数内部创建一个类组件,提供复用代码并返回

    function withMouse(WrappedComponent) {
      class Mouse extends React.Component {
        state = {
          x: 0,
          y: 0
        }
        handleMouseMove = e => {
          this.setState({
            x: e.clientX,
            y: e.clientY
          })
        }
        componentDidMount() {
          window.addEventListener('mousemove', this.handleMouseMove)
        }
        componentWillUnmount() {
          window.removeEventListener('mousemove', this.handleMouseMove)
        }
        render(){
          return <WrappedComponent {...this.state}></WrappedComponent>
        }
      }
      return Mouse
    }
    const Position = props =>(
      <p>
        鼠标当前位置:(x:{props.x},y:{props.y})
      </p>
    )
    const img = props =>(
     <img src="../public/logo192.png" alt="react" style={{
         position:'absolute',
         top:props.y - 64,
         left:props.x -64
       }} />
    )
    const MousePosition = withMouse(Position)
    const Mouse = withMouse(img)
    ReactDOM.render(<MousePosition/>,document.getElementById('root'))
    
  4. displayName–设置组件返回的名称

    function withMouse(WrappedComponent) {
      class Mouse extends React.Component {...}
      Mouse.displayName = `withMouse${getDisplayName(WrappedComponent)}`
      return Mouse
    }
    function getDisplayName(WrappedComponent){
    	return WrappedComponent.dispalyName || WrappedComponent.name || 'component'
    }
    
  5. props丢失问题

    function withMouse(WrappedComponent) {
      class Mouse extends React.Component {
        ...
        render(){
          return <WrappedComponent {...this.state} {...this.props}></WrappedComponent>
        }
      }
      return Mouse
    }
    const Position = props =>(
      <p>
        鼠标当前位置:(x:{props.x},y:{props.y})
      </p>
    )
    const MousePosition = withMouse(Position)
    ReactDOM.render(<MousePosition/>,document.getElementById('root'))
    

setState

  1. 异步更新数据

  2. 可以多次调用setState,但只会触发一次render重新渲染,并且后面的setState不依赖前面的setState

    this.setState({
    	count: state.count+1
    })
    同时调用两次count还是为2
    
    推荐使用
    this.setState((state,props)=>{
    	return{
    		count: state.count+1
    	}
    })
    同时调两次count变为3
    
  3. 第二个参数

    this.setState((state,props)=>{
    	return{
    		count: state.count+1
    	}
    },()=>{
    	console.log(this.state.count)//为dom更新后的值
    })
    

组件的更新

  1. 在父组件更新中,只会同步更新子组件中的状态,但只会渲染当前组件子树

路由

  1. 安装路由

    yarn add react-router-dom
    
  2. 引入路由–注意在react-router-dom 6.0.1中Route要写在Routes中

    import { BrowserRouter as Router,Route , Link,Routes } from 'react-router-dom'
    
    const First = ()=><p>页面一的内容</p>
    
    function App() {
      return (
        <Router>
          <div>
            <h1>函数组件</h1>
            {/* 指定路由入口 */}
            <Link to="/first">页面一</Link>
            {/* 指定路由出口 */}
            <Routes>
            <Route path="/first" element={<First/>} />
            </Routes>
          </div>
        </Router>
      )
    }
    
  3. 常用路由HashRouter–url带#号和BrowserRouter

  4. 编程式导航在v6版本中使用useNavigate()

  5. 默认路由path写为’/’

  6. 路由匹配模式,模糊匹配path为"/a",to:"/a",to:"/a/xcv"都会匹配成功

    ​ 精确匹配给Route添加exact就变为精确匹配

    <Route exact path="/first" element={<First/>} />
    

Hooks–异步

  1. useState

    import {useState} from 'react'
    cosnt [count,setCount] = useState(0)
    count--为状态
    setCount--为行为
    useState(0)--给count赋值
    
    修改count的值 ()=>{setCount(count + 1)}
    
  2. Effect

    import {useEffect} from 'react'
    useEffect(()=>{
    	console.log(count,'变化')
    	return ()=>{
    		console.log('离开页面打印')
    	}
    },[count])
    //第二个参数count表示只有count改变时才执行return的方法,若第二个参数为[]表示页面跳转才执行
    useEffect相当于componentDIDMount和componentDidUpdate两个生命周期
    
  3. useContext–用于组件传值

    import React,{useState,createContext,useContext} from 'react';
    const CountContext = createContext();
    function Counter(){
    	let count = useContext(CountContext)
    	return (<h2>{count}<h2>)
    }
    
    function demo(){
    	const [count,setCount] = useState(0)
    	return (
    		<div>
    			<p>{count}</p>
    			<button onClick={()=>{setCount(count + 1)}}></button>
    			<CountContext.provider value={count}>
    				<Counter/>
    			</CountContext.provider>
    		</div>
    	)
    }
    
  4. useReducer

    import {useReducer} from 'react'
    function ReducerDemo(){
    	const [count,dispatch] = useReducer((state,action)=>{
    		switch(action){
    			case 'add': return state + 1
    			case 'sub': return state - 1
    			default: return state
    		}
    	})
    	return(
    		<div>
    			<p>{count}</p>
    			<button onClick={()=>{dispatch('add')}}></button>
    			<button onClick={()=>{dispatch('sub')}}></button>
    		</div>
    	)
    }
    
    根据useReducer和父子组件传值还能实现redux
    
  5. useMemo–缓存一个值,解决子组件重复执行

    const actionname = useMemo(()=>{actionname(name),[name]})
    
  6. useRef–获取dom

    const inputEl = useRef(null)
    
    <input ref={inputEl} type="text">
    console.log(inputEl,'获取input的dom节点')
    
  7. useCallback–缓存一个函数

    const [size,setSize] = useState({
    	width:document.documentElement.clientWidth,
    	height:document.documentElement.clientHeight
    })
    const onResize = useCallback(()=>{
    	setSize({
    		width:document.documentElement.clientWidth,
    		height:document.documentElement.clientHeight
    	})
    },[])
    
  8. 自定义hooks

    function useWinSize(){
    	const [size,setSize] = useState({
    	width:document.documentElement.clientWidth,
    	height:document.documentElement.clientHeight
        })
        const onResize = useCallback(()=>{
            setSize({
                width:document.documentElement.clientWidth,
                height:document.documentElement.clientHeight
            })
        },[])
    	return size
    }
    function demo(){
    	const size  = useWinSize()
    	return (<div>{size}</div>)
    }
    

React.memo

const demo = memo(params)=>{
	
}//控制何时重新渲染组件

React.pureComponent

class demo extends PureComponent//子组件不跟着父组件渲染

Redux

yarn add redux-app
yarn add redux
yarn add react-
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值