十分钟学会react基础语法

114 阅读4分钟

1.创建项目

npx create-react-app demo
cd demo 
npm start // 启动

2.组件化开发

import ReactDOM from "react-dom";
import App from "./App"; // 引入组件
ReactDOM.render(
  <App />
  document.getElementById("root"),
);

import React from 'react'

export default function app11() {
  return (
    <div>你好</div>
  )
}

小结

  • 1.文件名可以是jsx或者js,不影响文件中的代码
  • 2.组件名称必须大写
  • 3.JS中出现()代表其中想要写html
  • 4. HTML中出现{}代表其申相要写is
  • 5.其实export default也可以写到class前面
  • if判断三元运算、for循环使用map

3.state完整写法和方法的调用

import React, {Component} from 'react'

export default class App extends Component {
  constructor(props) {
    super(props)
    this.state = {
      num: 1
    }
    this.add = this.add.bind(this)
  }
  render() {
    return (
      <>
        <h2>数字:{this.state.num}</h2>
        {/* 更新state */}
        <button onClick={()=> this.setState({num: this.state.num++})}></button>
        {/* 第二种 */}
        <button onClick={this.add}></button>
        {/* 第三种 */}
        <button onClick={()=> this.add()}></button>
        {/* 第四种 */}
        <button onClick={this.add.bind(this)}></button>
      </>
    )
  }
  add() {
    this.setState({num: this.state.num++})
  }
}

4.函数式组件

export default function App() {
  return <h2></h2>
}

特点:

  • 函数式组件没有生命周期
  • 函数式组件没有this
  • 函数式组件没有state状态

5.hook-useState

import { useState } from "react"
const App = () => {
  const [a, setA] = useState(1)
  return (
    <>
      <h2>{a}</h2>
      <button onClick={()=>{setA(2)}}>按钮</button>
    </>
  )
}
export default App

6.hook-useEffect

import { useState, useEffect } from "react"

const App = () => {
  const [a, setA] = useState(1)
  // 模拟 mounted
  useEffect(() => {
    console.log(‘挂在完成’) 
  })
  
  // 模拟 updated
  // 1.检测那个值就把那个值放到数组中
  // 2.检测页面中所有变量删掉数组
  // 3.不想检测任何数据,给个空数组
  useEffect(() => {
    console.log(‘a更新了’) 
  }, [a])
  
  // 模拟 beforDestroy
  useEffect(() => {
    return () => {
       console.log(‘页面销毁前’)
    }
  })
  
  return (
    <>
      <h2>{a}</h2>
      <button onClick={()=>{setA(2)}}>按钮</button>
    </>
  )
}

export default App

7.父传子

// 孙子组件
function Child(props) {
  return <h2>子组件 - {props.num}</h2>
}
// 父组件
function Father(props){
  return <Child num={props.num} />
}
// 顶级组件
export default function App1() {
  return <Father num={456} />
}

8.子传父

// 孙子组件
function Child(props) {
  return (
    <>
      <h2>{props.num}</h2>
      <button onClick={()=>{ props.setNum(456) }}>按钮</button>
    </>
   )
}
// 父组件
function Father(props){
  return <Child num={props.num} setNum={props.setNum} />
}
// 顶级组件
export default function App() {
  const [num, setNum] = useState(123)
  return <Father num={num} setNum={props.setNum} />
}

9.hook-createContext跨级组件传值

import { createContext, useState } from 'react'
// 创建上下文空间(Provider提供器,Consumer消费者)
const NumContext = createContext()

// 孙子组件
function Child(props) {
  return (
    <NumContext.Consumer>
      {
        ({num, setNum}) => (
          <>
            <h2>{num}</h2>
            <button onClick={()=>{ setNum(456) }}>按钮</button>
          </>
        ) 
      }
    </NumContext.Consumer>
   )
}
// 父组件
function Father(props) {
  return (<Child  />)
}
// 顶级组件
export default function App() {
  const [num, setNum] = useState(123)
  return (
    <NumContext.Provider value={{num, setNum}}>
      <Father />
    </NumContext.Provider>
  )
}

10.hook-useContext

import { createContext, useState, useContext } from 'react'
// 创建上下文空间(Provider提供器,Consumer消费者)
const NumContext = createContext()

// 孙子组件
function Child(props) {
  const {num, setNum} = useContext(NumContext)
  return (
    <>
      <h2>{num}</h2>
      <button onClick={()=>{ setNum(456) }}>按钮</button> 
    </>
  )
}
// 父组件
const Father = () => <Child />
// 顶级组件
export default function App() {
  const [num, setNum] = useState(123)
  return (
    <NumContext.Provider value={{num, setNum}}>
      <Father />
    </NumContext.Provider>
  )
}

11.受控组件和非受控组件 模仿v-model

import { useState, useRef } from 'react'

export default function App() {
  const [a, setA] = useState('')
  const ele = useRef(null)
  return (
    <div>
      <h2>受控组件-{a}</h2>
      <input type="text" value={a} onChange={(e)=> { setA(e.target.value) }} />
      <h2>不受控组件-{a}</h2>
      <input type="text" ref={ele} />
      <button onClick={()=> {console.log(ele.current.value)}}>获取</button>
    </div>
  )
}
  • 受控组件只存在于表单元素
  • 受控组件就是表单元素的value,需要通过state(或useState)来定义
  • 不受控组件就是表单元素的value无法通过state获取,只能使用ref(或useRef)来获取

12.hook-memo

import { useState, memo } from 'react'

const Child1 = ()=> {
  console.log(‘没加memo,父组件更新,子组件也会被刷新’);
  return <div>Child1</div>
}

const Child2 = memo(()=> {
  console.log(‘加memo,只有页面初始化的时候才会触发一次’);
  return <div>Child2</div>
})

export default function App4() {
  const [num, setA] = useState(1)
  return (
    <div>
      <h2>{num}</h2>
      <button onClick={()=> setA(num+1) }>累加</button>
      <Child1 />
      <Child2 />
    </div>
  )
}

13.hook-useCallback和useMemo

import { useState, memo, useCallback, useMemo } from 'react'

const Child1 = memo((props)=> {
  console.log(‘即使加了memo,点击事件放在子组件不使用useCallback,子组件还是会每次更新’);
  return <button onClick={()=> props.numSet1() }>Child1累加</button>
})

const Child2 = memo(()=> {
  console.log(‘使用useCallback且第二个参数给孔数组,每次点击子组件就不会更新了’);
  return return <button onClick={()=> props.numSet2() }>Child2累加</button>
})

export default function App4() {
  const [num, setA] = useState(1)
  const numSet1 = ()=>{
    setA((num)=>num+1)
  }, [])
  const numSet2 = useCallback(()=>{
    setA((num)=>num+1)
  }, [])
  
  // useMemo 写法和useCallback类似效果一致。从函数中返回函数
  const numSet2 = useMemo(()=>{
    return ()=> setA((num)=>num+1)
  }, [])
  return (
    <div>
      <h2>{num}</h2>
      <Child1 numSet={numSet1} />
      <Child2 numSet={numSet2} />
    </div>
  )
}

14.React Redux安装

npm i redux react-redux --save

15.仓库与reducer创建

// 仓库的入口文件
// 引入reducer
import reducer from "./reducer";
// 创建仓库
import { createStore } from "redux";

const store = createStore(reducer);

export default store;

// 创建初试状态
const defaultState = {
  num: 1,
};

// eslint-disable-next-line import/no-anonymous-default-export
export default (state = defaultState) => 
  return state;
};

16.提供器与连接器

import ReactDOM from "react-dom";
import App from "./App";
import { Provider } from "react-redux"; // 提供器
import store from "./store"; // 引入

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


import React from 'react'
import { connect } from 'react-redux'   // 连接器 

const App = (props) => {
  return (
    <>
      <div>{props.num}</div>
    </>
  )
}
// 状态映射:将reducer中的state映射成props
// props.num去调用state的num
const mapStateProps = (state) => {
  return {
    num: state.num
  }
}


// export default connect(state映射,dispatch映射)(当前组件的名字)
export default connect(mapStateProps)(App) 

17.state映射和dispatch映射

import React from 'react'
import { connect } from 'react-redux'   // 连接器 

const App = (props) => {
  return (
    <>
      <div>{props.num}</div>
    </>
  )
}
// 状态映射:将reducer中的state映射成props
// props.num去调用state的num
const mapStateProps = (state) => {
  return {
    num: state.num
  }
}

// 事件派发映射:将reducer中的事件映射成props
// props.leijia()去实现num的累加
const mapDispatchToProps = (dispach) => {
  return {
    leijia() {
      const action = {type:'a'} // 指定类型
      dispach(action)
    }
  }
}

// export default connect(state映射,dispatch映射)(当前组件的名字)
export default connect(mapStateProps, mapDispatchToProps)(App) 

// 创建初试状态
const defaultState = {
  num: 1,
};

// eslint-disable-next-line import/no-anonymous-default-export
export default (state = defaultState, action) => {
  // 这里需要深拷贝变量,不能修改原始数据
  let newState = JSON.parse(JSON.stringify(state));

  if (action.type === "a") {
    newState.num++;
  }
  return newState;
};

18.路由安装和创建

npm i react-router-demo@6 --save

import ReactDOM from "react-dom";
import Router from "./router";
ReactDOM.render(
  <Router />document.getElementById("root"),
);

import A from "../pages/A";  // 新建A组件
import B from "../pages/B";  // 新建B组件
import App from "../App"; // 引入承接页

import { BrowserRouter, Routes, Route } from "react-router-dom"; 
// BrowserRouter是history模式 不带# 需要配置nginx
// HashRouter是Hash模式 不带#
const BaseRouter = () => (
  <BrowserRouter>
    <Routes>
      <Route path='/' element={<App />}>
        <Route path='/A' element={<A />} />
        <Route path='/B' element={<B />} />
        <Route path='/C/:id' element={<C />} />
      </Route>
    </Routes>
  </BrowserRouter>
)

export default BaseRouter

19.router的hooks

import React from 'react'
import { Outlet, Link, useLocation, useNavigate, useParams } from 'react-router-dom'

export default function App() {
  const a = useLocation() // 获取页面路径信息
  const navigate = useNavigate() // 页面跳转传参方法
  const param = useParams() // 获取页面参数
  console.log(111, a, param);
  return (
    <div>
      <ul>
        <li><Link to='/A'>首页</Link></li>
        <li><Link to='/B'>测试</Link></li>
        <li><Link to='/C'>测试区</Link></li>
      </ul>
      <button  onClick={()=> navigate('/C', {state:{ id: 123 }})}>11s</button>
      <hr />
      <Outlet />  // 占位符 A、B、C组件展示在这里
    </div>
  )
}