4.27 react第一天

react 语法基础

  • 概念介绍

  • 项目初始化

  • 目录结构

  • 单文件组件 SFC 与 mustach语法 模板语法

  • 响应式数据 useState

  • react 合成事件

  • useEffect 生命周期与监听

  • 组件开发

    • 基础使用

    • 父传子

    • 子传父

    • 插槽

    • 上下文 context useContext 跨层级数据共享

  • react 状态管理库 redux redux-toolkit(最佳实践) mobx dva ...... reducer

  • react 路由 react-router-dom

  • UI库的使用 ant design 系列 antd mobile nutUi

1.react概念介绍

11年 facebook (meta) 开源react

第一次提出的概念:

  • 组件化开发

  • 响应式数据 数据驱动 最小粒度更新算法 性能远超vue ref reactive

  • 虚拟dom更新 驱动 真实dom更新 diff算法 fiber算法

  • react 语法 更加倾向原生JS

13年 10月 vue 发布了vue2.x ----22年

vue: 融合了 react 核心理念 和核心代码 融合和 anglur js 指令系统 14个指令

  • vue3语法 模仿了react 16.8语法

react 版本历史

  • <16.8 版本 基于 类的开发(面向对象的开发) 学习难度非常高

  • >16.8 版本 基于函数式的开发(面向函数开发) 学习难度较低 【大量的项目 都是基于函数式语法】

  • 目前最新react版本 19.x 16.x 17.x 18.x 19.x

2.项目初始化

react 组成部分:

  • react 核心语法 react

  • react 操作dom节点的库 react-dom

  • react 跨端原生开发(安卓 ios 小程序): react native RN

复制代码
  https://react.docschina.org/
  • 脚手架: 可以通过某种工具 快速的创建项目 (某种工具===脚手架工具)

    • vue vite vue-cli webpack

    • react vite create-react-app

2.1vite初始化 项目过程命令

复制代码
  
  pnpm create vite 项目名 --template react
复制代码
  
  pnpm install 
  pnpm run dev 

3.单文件组件 SFC

文件后缀 .js .jsx .tsx

一个函数 return 一段html 代码(被渲染到页面上 根据挂载的根节点确定渲染位置)

复制代码
  import './app.css'
  function App() {
    const xxx = 1000;
    let yyy = 2000;
    // mustach  {表达式}    <></>  有且只有一个根节点
    //  vue{{}} template     ES6 ${}
    return (
      <>
        <div id="app" >hello world---   {xxx}
          <p className="box"> 我是xxx 你好啊</p>
        </div>
        <div  >我是嘻嘻嘻</div>
      </>
    )
  }
  ​
  export default App;
复制代码
  
  import './app.css'
  export default () => {
    const a = 1100;
    return (
      <div className="box">
        {a}
      </div>
    )
  }

4.响应式数据 useState

数据改 页面改

页面改 数据改

复制代码
  
   const [变量,修改变量函数] = useState(初始值);
  //修改变量函数: 调用函数时,
  //1.首先修改变量的值
  //2.通过diff算法(递归)  比对 所有的dom节点(只是比对虚拟dom),找出使用了这个变量的dom节点
  //3.根据render函数,重新渲染涉及到的 真实 dom节点
复制代码
  
  import {useState} from 'react'
  ​
  export const ()=>{
      // 变量==响应式数据的特征
      //set变量 ==  接受一个 可以修改 这个变量的函数
      //之后修改数据变量,必须使用 set变量的方法进行修改  
      const [变量,set变量] = useState(初始值);
      const [a,setA] = useState(1000);
      
      const reduce = ()=>{
          //新数据如果是根据元数据改变过来的
          // 不要直接修改原数据的值  a-1  a--
          // 如果原值是引用数据类型,一定注意  深浅拷贝问题 
          //    修改引用数据类型时,应该先通过拷贝拿到原数据 给一个临时变量存起来 更改临时变量 最后setXXx修改响应式数据
          setA(a-1)
      }
  }
  ​
复制代码
  
  import './app.css'
  import { useState } from 'react';
  ​
  ​
  export default () => {
   const [a,setA] = useState(1000)
    const reduce = ()=>{
      // 异步修改函数  promise?  setTimeout 
      // 闭包: 永远拿到的都是老值
        setA(a-1) 
    }
    // const add = ()=>{
    //   setA(a+1)
    // }
    return (
      <>
        <button onClick={reduce}>-</button>
        <h1>{a}</h1>
        <button onClick={()=>setA(a+1)}>+</button>
      </>
  ​
    )
  }

5.react 合成事件

复制代码
  
  <div  on事件类型={事件的执行函数}>
复制代码
  
  const ()=>{
      const changeNum = ()=>{}
      return (<div  οnclick={changeNum}>)
  }
复制代码
  
  const ()=>{
      return (<div  οnclick={()=>{}}>)
  }
复制代码
  
  const ()=>{
          const changeNum = (num)=>{}
      return (<div  οnclick={()=>changeNum(1000)}>)
  }
  ​
复制代码
  
  const ()=>{
          const changeNum = (event,num)=>{}
      return (<div  οnclick={(event)=>changeNum(event,1000)}>)
  }

6.useEffect 副作用函数 hooks

useEffect 代替生命周期 (挂载完成,卸载之前)

​ <16.8版本 完整的生命周期(类组件为主 没有函数式组件)

useEffect 代替数据的监听(vue:watch computed)

复制代码
  
  import {useEffect} from 'react'
  export default  ()=>{
      //副作用:watch computed  就是监听的变量
      useEffect(()=>{},[副作用])
  }
  ​

生命周期 :

  • 初始化周期 init

  • 挂载周期 mounting

    • componentWillMount 组件挂载之前

    • componentDidMount 组件挂载之后 ----mounted

  • 更新周期 updation

  • 卸载周期 unMounting

    • componentWillUnmount 卸载之前 销毁之前

6.1 useEffect 代替生命周期

不去监听任何数据的改变 就代表的是 挂载完成周期

复制代码
  
  ​
  import {useEffect} from 'react'
  export default  ()=>{
     useEffect(()=>{
         //函数体:挂载完成执行的代码   componentDidMount
         return ()=>{
             //销毁周期的代码
         }
     },[])
    //这里一定要写[],不然就会死循环
  }
  ​

6.2 useEffect 监听某个数据的改变

注意:!!!

如果在监听某个变量的改变,useEffect 函数体中 千万不要 更改这个变量的值 的代码

副作用的[] 一定要写,不写会造成死循环

复制代码
  //变量1  变量2 任意1个变量的值发生改变 函数体就会自动执行一次
  import {useEffect} from 'react'
  export default  ()=>{
      
     useEffect(()=>{
         //函数体:挂载完成执行的代码   componentDidMount
         return ()=>{
             //销毁周期的代码
         }
     },[监听的变量1,监听的变量2...])
  }
  ​
复制代码
  
  //变量1  变量2 任意1个变量的值发生改变 函数题就会自动执行一次
  import {useEffect,useState} from 'react'
  export default  ()=>{
      const [a,setA] = useState(0)
     useEffect(()=>{
         //函数体:挂载完成执行的代码   componentDidMount
        setA(a+1)
     },[a])
       useEffect(()=>{
         //函数体:挂载完成执行的代码   componentDidMount
       
     },[监听的变量2])
  }
  ​

7.useRef 获取dom || 获取子组件的实例对象

复制代码
  
  import {useRef,useEffect} from 'react'
  ​
  ​
  export default ()=>{
      const boxRef = useRef(null); 
      
      useEffect(()=>{
          console.log(boxRef.current)   // <div ref={boxRef}> xxx </div>
      },[])
      
      return <div ref={boxRef}> xxx </div>
  }
复制代码
  
  import { useEffect,useState,useRef } from 'react'
  ​
  export default function App1() {
  ​
      const [num,setNum] = useState(100)
      const [a,setA] = useState(122)
  ​
       const boxRef = useRef(null);  
      // const timer = setInterval(() => {
      //     console.log('定时器');
      // },10000)
  ​
  ​
      useEffect(() => {
          // 挂载完成
          // let ulDom = document.querySelector('ul')
          // console.log(ulDom);
              console.log(boxRef.current);
               
          // 销毁周期 
          // return () => {
          //     clearInterval(timer)
          // }
      }, [])  
  ​
  ​
      const changeNum = () => {
          let num1 = num + 1
          setNum(num1)
          console.log(num1);
      }
      useEffect(()=>{
          console.log('变化了');
          console.log(num);
          console.log(a);
      },[num,a])
  ​
      return (
          <div>
              <div ref={boxRef} className="box">我是一个盒子</div>
              <ul>
                  <li>菜单{num}</li>
                  <li>菜单02</li>
                  <li>菜单03</li>
                  <li>菜单04</li>
                  <li>菜单05</li>
              </ul>
              <button onClick={changeNum}>递增</button>
              <button onClick={()=>setA(a+1)}>A</button>
          </div>
      )
  }
  ​

7.判断 三目运算

三目运算 使用场景: 显示隐藏 dom节点 动态样式 display:none 动态类名

复制代码
  
  import React from 'react'
  ​
  export default function App2() {
      const [gedner,setGender] = useState(0)
    return (
      <div>
            {gender%2==0?<span>男</span>:<span>女</span>} 
       </div>
    )
  }
  ​
复制代码
  
  import React,{useState} from 'react'
  ​
  ​
  // 子组件
  const getGender = (gender) => {
      return gender%2==0?<span>男</span>:<span>女</span>
  }
  ​
  // 导出一个默认的函数组件App2
  export default function App2() {
      // 使用useState钩子,初始化gender为0,并设置setGender函数用于更新gender的值
      const [gedner,setGender] = useState(0)
    return (
      <div>
            {getGender(gedner)}   
            <button onClick={()=>setGender(gedner+1)}>++++</button> 
       </div>
    )
  }
  ​
  • 判断成绩 >90 输出优秀,否则什么都不输出
复制代码
  
  import React,{useState} from 'react'
  ​
  export default function App3() {
      const [num,setNum] = useState(85)
    return (
      <div>
          {num>=90?<h1>优秀</h1>:null   }
      </div>
    )
  }

成绩范围

90 优秀

80 良好

70 中等

60 及格

60以下 不及格

复制代码
  
  import React,{useState} from 'react'
  ​
  ​
  const getGreade = (num)=>{
    let str = '不及格'
    switch(Math.floor(num/10)){
      case 10:
      case 9:str = '优秀'; break;
      case 8: str = '良好';break;
      case 7:str = '中等'; break;
      case 6: str = '及格';break;
      default:str = '不及格';
    }
  ​
    return  <h1>{str}</h1>
  }
  ​
  ​
  export default function App4() {
    const [num,setNum] = useState(46)
    
    return (
        <>
        {getGreade(num)}
          {/* {
            num>=90?<h1>优秀</h1>: num>=80?<h1>良好</h1>:num>=70?<h1>中等</h1>:num>=60?<h1>及格</h1>:<h1>不及格</h1>
          } */}
        
        
        </>
    )
  }
  ​
  • 动态样式操作
复制代码
  
  import React ,{useState} from 'react'
  ​
  export default function App5() {
      const [gender,setGender] = useState(0)
    return (
      <div>
          {/* 动态样式 */}
          <h1 style={{display:gender%2==0?'block':'none',background:'red'  } }>男</h1>
          <h1 style={{display:gender%2==1?'block':'none',background:'red'  } }>女</h1>
  ​
              <button onClick={()=>setGender(gender+1)}>+++</button>
      </div>
    )
  }
  ​
  • 动态类名

开关灯效果

复制代码
  
  import React, { useState } from 'react'
  import './App.css'
  ​
  export default function App6() {
      const [isLigiht, setIsLight] = useState(true)
      return (
          <>
              <div className={isLigiht?'box active':'box black'}>
  ​
              </div>
         
              <button onClick={() => setIsLight(true)}>开灯</button>
              <button onClick={() => setIsLight(false)}>关灯</button>
          </>
      )
  }
  ​
  • 选项卡 tab实现 17:05

希望清单的 标题 希望列表 添加希望

点击某个标题: 选中当前这个标题(添加选中样式) , 显示对应的内容区域

8.循环 map

循环数组 ||对象

最终目的: 必须要有 return 出来的 html代码到 页面上

复制代码
  
  import React,{useState } from 'react'
  ​
  export default function App8() {
      
  const [userList,setUserList] = useState([
      {name:'张麻子',age:40},
       {name:'黄四郎',age:35},
       {name:'马邦德',age:42},
  ])
  ​
  const add = ()=>{
   const obj = {name:'胡桂源',age:20}
  //  const list = [...userList]
  //  list.push(obj)
  // // setUserList(userList)  //地址没有发生改变 ,所以不会重新渲染
  // // 需要临时的空的数组 有新的地址  装所有的新数据,再调用修改变量的值 set方法 才可以有响应式数据的特征
  //  setUserList(list)
  ​
  userList.push(obj)
  setUserList([...userList])  //地址没有发生改变 ,所以不会重新渲染
  // 需要临时的空的数组 有新的地址  装所有的新数据,再调用修改变量的值 set方法 才可以有响应式数据的特征
  ​
  }
  ​
    return (
      <>
      <button onClick={add}>添加数据</button>
          {
              userList.map((item,index)=>{
                  return <p key={index}>姓名:{item.name};年龄:{item.age}</p>
              })
          }
  ​
      </>
    )
  }
复制代码
  
  const [students,setStudents] = useState([
      {sno:'12000',name:'纪英龙',greade:95},
         {sno:'1202200',name:'查其才',greade:85},
      {sno:'123330',name:'蒋盛林',greade:55},
  ])
  //渲染默认数据
  //点击事件  添加一个对象     {sno:'222',name:'xxxx',greade:55},
  // 删除按钮 删除对应的数据  
  ​

9.受控组件 与 非受控组件|表单 获取数据

非受控组件 : 通过 useRef 获取到dom ,再通过dom节点获取表单数据 antd

受控组件: 通过useState 做数据的绑定 加上 onChange 事件 e.target.value 然后赋值给那个变量useState=e.target.value

复制代码
  
  import React,{useRef} from 'react'
  ​
  export default function App9() {
      // 非受控组件  useRef
      const accountRef = useRef(null);
      const passwordRef = useRef(null);
  ​
      const saveBtn = () => {
          console.log(accountRef.current.value);
          console.log(passwordRef.current.value);
      }
      
    return (
      <>
          账号: <input type="text" ref={accountRef} />
          密码: <input type="password" ref={passwordRef}/>
          <button onClick={saveBtn}>提交</button>
      </>
    )
  }
  ​
复制代码
  
  import React,{useState} from 'react'
  ​
  export default function App9() {
      const [formData,setFormData] = useState({account:'',password:''})
  ​
      const saveBtn = () => {
         console.log(formData);
         
      }
      const change = (data)=>{
          setFormData(data)
      }
  ​
    return (
      <>
          账号: <input type="text"  onChange={(e)=>change({account:e.target.value, password:formData.password})}/>
          密码: <input type="password" onChange={(e)=>change({account:formData.account, password:e.target.value})} />
          <button onClick={saveBtn}>提交</button>
      </>
    )
  }
相关推荐
拉不动的猪1 小时前
前端常见数组分析
前端·javascript·面试
小吕学编程1 小时前
ES练习册
java·前端·elasticsearch
Asthenia04121 小时前
Netty编解码器详解与实战
前端
袁煦丞1 小时前
每天省2小时!这个网盘神器让我告别云存储混乱(附内网穿透神操作)
前端·程序员·远程工作
一个专注写代码的程序媛2 小时前
vue组件间通信
前端·javascript·vue.js
一笑code2 小时前
美团社招一面
前端·javascript·vue.js
懒懒是个程序员3 小时前
layui时间范围
前端·javascript·layui
NoneCoder3 小时前
HTML响应式网页设计与跨平台适配
前端·html
凯哥19703 小时前
在 Uni-app 做的后台中使用 Howler.js 实现强大的音频播放功能
前端
烛阴3 小时前
面试必考!一招教你区分JavaScript静态函数和普通函数,快收藏!
前端·javascript