react入门(上)

react入门

react是什么?

React 是一个开源的 JavaScript 库,由Facebook开发,主要用于构建用户界面,特别是复杂的单页应用程序(SPA)。它专注于视图层,即用户界面的开发,可以与多种库或框架结合使用,以管理应用程序的状态和数据流动。

React 的特点:

  1. 虚拟 DOM
    • React 引入了虚拟 DOM 的概念,这是一种内存中的轻量级数据结构,表示实际 DOM 的抽象。当应用状态改变时,React 会高效地计算出虚拟 DOM 的最小变更量,并将这些变更应用到实际 DOM 上,从而大幅提升了性能。
  2. 组件化开发
    • React 鼓励采用组件化的方式来构建 UI,即将 UI 分解为可复用的独立组件。每个组件负责管理自己的状态(state)和属性(props),这样可以提高代码的模块化程度,易于维护和重用。
  3. 单向数据流
    • React 推崇一种单向数据流的架构,数据通常自上而下地传递给组件树,这简化了状态管理和问题追踪,减少了数据流动的复杂性。
  4. JSX
    • JSX 是一种语法扩展,允许在 JavaScript 中混写 HTML 样式的代码。这使得描述 UI 结构变得更加直观和简洁,同时也方便静态代码分析工具进行检查。
  5. 服务器端渲染
    • React 支持服务器端渲染(SSR),这对于改善首屏加载速度和搜索引擎优化(SEO)非常有利。

React 的优势:

  • 性能优化:通过虚拟 DOM 减少了直接操作实际 DOM 的次数,提升了应用运行效率。
  • 易学易用:React 的学习曲线相对较平缓,开发者可以快速上手并开始开发。
  • 强大的生态系统:React 拥有庞大的社区支持和丰富的第三方库,如 Redux、React Router 等,可以满足各种开发需求。
  • 代码复用与模块化:组件化的开发方式促进了代码的复用,使得开发大型项目更加高效。
  • 兼容性和灵活性:React 不限定于特定的技术栈,可以与多种后端技术和前端库集成,提供了高度的灵活性。
  • React Native:React 的理念还延伸到了原生移动应用开发,React Native 允许使用相同的开发模式来构建原生移动应用,实现了跨平台开发能力。

这些特点和优势使得 React 成为了现代Web开发中极为流行的工具之一。

初始化一个react项目

输入以下命令来创建一个新的React项目,其中react-demo替换为你想要的项目名称:

bash 复制代码
npx creact-react-app react-demo

使用 npx 命令会自动安装React及相关依赖,并设置好项目的基本结构

cd 切换到创建的文件夹

使用 npm starrt 启动项目

项目的目录结构

java 复制代码
react-demo
    ├─ node_modules
    ├─ public
	├─ favicon.ico
	├─ index.html
	├─ logo192.png
	├─ logo512.png
        ├─ manifest.json
        ├─ robots.txt
    ├─ src
        ├─ App.css
        ├─ App.js
	├─ App.test.js
	├─ index.css
	├─ index.js
	├─ logo.svg
	├─ reportWebVitals.js
        ├─ setupTests.js		
    ├─ package.json

下边我们分别来说一下每个文件(夹)的作用:

Node_modules

node的包目录,项目所依赖到的所有第三方包,没啥可说的

Public

public用来存放首页模板及静态资源,该目录中除了index.html都可以删除

  • index.html 首页模板(不能删)
  • favicon.ico 收藏夹图标(可以删,开发中会替换为自己的图标)
  • logoxxx.png React的Logo(删)
  • manifest.json(PWA的配置文件,大部分情况没啥用,删)
  • robots.txt(搜索引擎配置文件,可删)

Src

源码目录,我们写代码就是在这里

index.js

项目入口文件,不能删。

index.css

index.js的样式表,可改可删

App.js

主组件,可改可删

App.css

App.js的样式表,可改可删

xxx.test.js

带有test的都是单元测试的文件,可删

reportWebVitals.js

应用性能统计相关的代码,简单说用户在使用应用时,该模块可以统计用户加载应用所花费的时间,并且根据需要发送给统计服务器,如果没有相关需求可删。

编写我们的第一个react应用,浅尝一下

jsx 复制代码
// app.tsx
function App() {
  return <div className="App">你好,这是我的第一个react项目!</div>;
}

export default App;
jsx 复制代码
import { createRoot } from "react-dom/client"; // react18 的新方法, 创建根节点,替代原来的 createDOM

import App from "./App.tsx";  // 导入 app 组件,也是入口文件和顶级组件
/**
 * createRoot 接收一个 DOM 元素作为参数,返回一个根节点,在后面继续链式调用 render 方法渲染根组件到获取的 dom 元素中
 */
createRoot(document.querySelector("#root")).render(<App />);

createRoot()

createRoot(domNode, options?)

domNode:一个 ,DOM 元素React 将为这个 DOM 元素创建一个根节点然后允许你在这个根节点上调用函数

options?:可选的根节点配置对象

返回值

createRoot 返回一个带有两个方法的的对象,这两个方法是:renderunmount

unmount()

调用 unmount 以销毁 React 根节点中的一个已经渲染的树

返回值

返回 undefined

render()

  • 用来将React元素渲染到根元素中
  • 首次调用 root.render 时,React 会先清空根节点中所有已经存在的 HTML,然后才会渲染 React 组件
  • 重复调用会在内部进行diff算法,将两次渲染结果进行比较,只修改发生变化的部分,避免没必要的更新,提高性能

react17 写法,不建议使用,后续可能会不再维护

jsx 复制代码
import React from "react"; // react 核心包,在 17 之前不手动导入会报错,在 17 之后可选不用手动导入
import ReactDOM from "react-dom"; 
import App from "./App.jsx";  // 导入App组件,作为应用的入口

// 使用ReactDOM.render方法,将<App />组件渲染到id为"root"的DOM元素中
ReactDOM.render(<App />, document.querySelector("#root")); // 接收两个参数要渲染的结构和目标 DOM

在react的核心包中createRoot方法创建根节点,还有一个方法createElement创建react元素,且创建后无法修改,只能覆盖

jsx 复制代码
import { createElement } from 'react-dom/client'
createElemnet('div',{id:'box',type:'div',className:'btn',onClick:()=>{alert('哎呀!你干嘛.')}},'你好!我是蔡徐坤') 
// 接收三个参数,第一个是创建元素的类型,第二个是元素对应的一些样式的配置对象,第三个参数是要填充的内容

元素名称必须为html格式的小写

标签中的属性class属性使用className,设置事件属性名采用驼峰命名

元素的内容,子元素,直接在后面使用逗号隔开添加

jsx概念

JSX是JavaScript XML的缩写,它是一种用于在React中编写UI组件的语法扩展。JSX允许开发者在JavaScript代码中编写类似HTML的结构,使得编写和阅读React组件更加直观和简洁。虽然它看起来像是在JavaScript中直接写HTML,但实际上,JSX被编译成普通的JavaScript函数调用,这些函数调用会创建虚拟DOM元素树,最终渲染为真实的DOM元素。

jsx本质

JSX并不是标准的JS语法,它是JS的语法扩展,浏览器本身不能识别,需要通过解析工具做解析之后才能在浏览器中运行

jsx是声明式编程,简单理解就是以结果为导向,就像是你的老板,我不管你的过程我只要结果

jsx 复制代码
// 命令式编程
// 使用createElement创建一个react元素,就相当于我告诉你,我给你10块钱,出门右转,到第二个红路灯路口右转,到旁边的商店买一包盐,再怎么怎么回来
const button = createElement('button',{},'按钮')

// 使用jsx 面向结果声明式编程,以结果为导向
//  可以简单理解为,我告诉你家里炒菜现在没盐了,想办法整一包来,我不管你是使用什么方法 
const button = <button>我是按钮</button>

jsx中使用js表达式

在jsx中可以通过 大括号语法{ }识别JavaScript中的表达式,比如常见的变量、函数调用、方法调用等等

jsx 复制代码
<script setup>
 const app = <div calssName="app">
          // 使用引号传递字符串
          {'php是世界上最好的语言'}
          // 识别变量
          const name = tom
          { name }
          // 函数调用
          const getUserInfo = () => {
              return { name: Tom , age: 18 }
          }
          { getUserInfo() }
          // 方法调用
          { New Date().getDate() }
          //使用js对象
          <div style={{color:'red'}}>Hello World</div> // 外层{ }识别表达式语法,内层{ }为对象
      </div>
</script>

注意:

  • jsx不是字符串,不要加引号
  • jsx中的html标签小写开头,React组件为大写开头
  • jsx有且只有一个根标签,必须正确结束
  • 布尔类型、Null 以及 Undefined 将会忽略
  • if语句、Switch语句、变量声明属于语句,不是表达式,不能出现在{ }中

列表渲染

jsx 复制代码
const heroList = [
  {
    id: 1,
    name: '锐雯',
    lane: '上单',
  },

  {
    id: 2,
    name: '泰拉米尔',
    lane: '上单',
  },

  {
    id: 3,
    name: '奎因',
    lane: '上单',
  },

  {
    id: 4,
    name: '奥恩',
    lane: '上单',
  },

  {
    id: 5,
    name: '亚索',
    lane: '中单',
  },

  {
    id: 6,
    name: '李青',
    lane: '打野',
  },

  {
    id: 7,
    name: '努努',
    lane: '打野',
  },

  {
    id: 8,
    name: '艾希',
    lane: 'ADC',
  },

  {
    id: 9,
    name: '薇恩',
    lane: 'ADC',
  },

  {
    id: 10,
    name: '卡特琳',
    lane: '辅助',
  },

  {
    id: 11,
    name: '莫德凯撒',
    lane: '辅助',
  },
]

function getHeroList() {
  return (
    <ul>
      {heroList.map(hero => (
        <li key={hero.id}>{hero.name}&nbsp;&nbsp;分路:{hero.lane}</li>
      ))}
    </ul>
  )
}

export default getHeroList;

条件渲染

jsx 复制代码
export const isLogin = false

export selectedValue = 1

export const getOptions = (val)=>{
if (val === 1) {
  return <div>选项1</div>
}else if (val === 2) {
  return <div>选项2</div>
}else {
  return <div>选项3</div>
 }
}

function App() {
    return (
        // 需要判断两个内容的显示隐藏的时候 可以使用 if else 或是使用简短的三元
    <div>{ isLogin ? '登录成功' : '未登录' }</div> // 未登录
        // 只需判断一个内容显示隐藏,无需使用 else 的时候,可以选择逻辑或 && 来判断,当值为真时,显示,否则反之
    <div>{ isLogin && '登录成功!' }</div> 
        // 判断多组内容
        //无法在 jsx 内书写 if else 语句 我们通过调用函数来判断,在函数内进行 if else 判断
     <div>{ getOptions(selectedValue) }</div>
    )
}

响应事件

jsx 复制代码
function myButton () {
    const handleClick = () => alert('喜中500万,请到缅北kk园区兑换!')
    return (
    <button onClick={ handleClick }>开奖</button>
    )
}

onClick={handleClick} 的结尾没有小括号!不要调用事件处理函数:你只需把函数传递给事件即可

当用户点击按钮时 React 会调用你传递的事件处理函数

更新数据,设置数据

vue3 中我们使用 refreactive 来声明响应式数据

而在 react 中我们使用 useState 钩子,来创建一个响应式数据,通过 count 来访,通过 setCount 来修改数据

tsx 复制代码
import { useState } from 'react'

function App() {
  const [count, setCount] = useState(0)
// 你将从 useState 中获得两样东西:当前的 state(count),以及用于更新它的函数(setCount)。你可以给它们起任何名字,但按照惯例会像 [something, setSomething] 这样为它们命名
  return (
      <div>
        <div>{count}</div>
        <button onClick={() => setCount(count + 1)}>按钮</button>
      </div>
  )
}

一个组件中与多个相同的组件,数据之间是相互隔离的

tsx 复制代码
import { useState } from 'react';

export default function MyApp() {
  return (
    <div>
      <h1>数据更新</h1>
      <MyButton />
      <MyButton />
    </div>
  );
}

function MyButton() {
  const [count, setCount] = useState(0);

  function handleClick() {
    setCount(count + 1);
  }

  return (
    <button onClick={handleClick}>
      当前数据: {count} 
    </button>
  );
}

组件间共享数据

tsx 复制代码
import { useState } from 'react';

export default function MyApp() { 
  // 在 MyApp 组件中定义 count 状态和 handleClick 事件处理函数
  const [count, setCount] = useState(0);

  function handleClick() {
    // 当按钮被点击时,更新 count 状态
    setCount(count + 1);
  }

  return (
    <div>
      <h1>数据更新</h1>
      {/* 将 handleClick 函数和 count 状态通过 props 传递给 MyButton 组件 */}
      <MyButton onClick={ handleClick } count={ count }/>
      <br/>
      <MyButton onClick={ handleClick } count={ count }/>
    </div>
  );
}

// MyButton 组件接收 onClick 和 count 作为 props
function MyButton({ onClick, count }: { onClick: () => void, count: number }) {
  // 当按钮被点击时,调用父组件传递过来的 onClick 函数
  return (
    <button onClick={ onClick }>
      {/* 显示从父组件传递来的 count 值 */}
      当前数字为:{ count }
    </button>
  );
}
  1. 我们将 count 状态和 handleClick 事件处理函数从 MyButton 组件移动到了 MyApp 组件中。这种做法称为"状态提升",可以将共享的状态和行为放在更高层级的组件中。
  2. MyApp 组件中,我们通过 props 将 handleClick 函数和 count 状态传递给每个 MyButton 组件。这样,每个按钮都可以访问相同的状态和行为。
  3. MyButton 组件中,我们接收 onClickcount 作为 props,并将 onClick 函数绑定到按钮的点击事件上。每个按钮显示的数字都是从父组件传递过来的 count 值。
相关推荐
程序员Qian2 分钟前
从开发天气MCP服务入门什么是MCP
前端
用户2031196600964 分钟前
sheet的基本用法
前端
火星思想10 分钟前
都2025年了,还在问构建工具是干嘛的?
前端·前端框架·设计
杨进军13 分钟前
MutationObserver 实现 iframe 自适应高度
前端
土豆125013 分钟前
构建高级半圆形进度条:SVG 与 纯 CSS 方案深度解析与完整代码
css·react.js·svg
火星思想14 分钟前
Promise 核心知识点(非基础)
前端·javascript·面试
前端大白话15 分钟前
炸裂!10个 React 实战技巧,让你的代码从“青铜”秒变“王者”
前端·javascript·react.js
Paramita15 分钟前
Koa源码解读
前端
用户614722537720315 分钟前
JavaScript 性能优化实战:从理论到落地的全面指南
前端
专业掘金16 分钟前
0426 手打基础丸
前端