React快速入门(语法篇),一文带你了解react的基础知识,看完你就能上手react写东西了(最适合有vue基础的同学)

一、JSX 基础与项目创建

如果你有过vue或者其他框架的经验,那你肯定对组件这个知识有一定的了解,在react,组件就是通过jsx来写的(本文主要是函数式组件)

举个最简单的jsx的例子:

jsx 复制代码
function App() {
  return (
    <div className="App">
      <header className="App-header">
        <h1>Hello, React!</h1>
      </header>
    </div>
  );
}

对于jsx,最简单粗暴的就是,在函数的return值里面写html,其中这个html通过()进行包裹 ,其他的数据处理放置在函数的函数体(return之前)

下面我们正式开始react项目的书写

首先,我们要创建react的项目工程,这里提供两种方式:

方式一:通过官方脚手架创建

bash 复制代码
npx create-react-app my-app

方式二:通过vite

bash 复制代码
npm create vite
# 之后在选择模板的时候直接选择react即可

其实更推荐使用pnpm,无他,就是快

创建好之后,我们进入目录,装好依赖就可以开始写我们的react代码了:

bash 复制代码
npm install

二、React 基础语法:

1、模板语法:

jsx 复制代码
function App() {
    const name = "Hello World!!!"
  return (
    <div className="App">
      <header className="App-header">
        <h1>
            {name} {/*通过大括号包裹就可以在页面中渲染出name的值*/}
        </h1>
      </header>
    </div>
  );
}

2、注释

在函数体使用注释和js使用注释一致,不在过多的讲述

在标签内部如何使用呢?

jsx 复制代码
function App() {
    const name = "Hello World!!!"
  return (
    <div className="App">
      <header className="App-header">
           {/* 这是 JSX 内部的单行注释 */}
           {/* 
        这是 JSX 内部的
        多行注释
           */}
        <h1>
            {name} {/*通过大括号包裹就可以在页面中渲染出name的值*/}
        </h1>
      </header>
    </div>
  );
}

三、在react中实现vue的各种功能

1、实现类似vue的各种指令(v-if,v-for...)

react中并没有提供各种指令,但是,我们依旧也是可以实现的

(1)v-if / v-else / v-else-if(条件渲染)

Vue 中通过指令控制元素是否渲染;React 中通过JavaScript 条件表达式(三目运算、逻辑与、if 语句)实现。

vue:

vue 复制代码
<div>
  <p v-if="type === 'a'">A</p>
  <p v-else-if="type === 'b'">B</p>
  <p v-else>Other</p>
</div>

react:

jsx 复制代码
function MyComponent({ type }) {
  // 方式1:三目运算符(适合简单分支)
  return (
    <div>
      {type === 'a' ? <p>A</p> : 
       type === 'b' ? <p>B</p> : 
       <p>Other</p>}
    </div>
  );

  // 方式2:if 语句(适合复杂逻辑)
  // let content;
  // if (type === 'a') content = <p>A</p>;
  // else if (type === 'b') content = <p>B</p>;
  // else content = <p>Other</p>;
  // return <div>{content}</div>;
}

通俗来讲就是使用if表达式来条件性的渲染,你可以直接在if-else体内return你要渲染的部分,注意要使用{}进行包裹

(2)v-show(显示 / 隐藏元素)

Vue 中通过 display: none 控制元素显示;React 中直接通过动态 style 或类名控制。

Vue :

vue 复制代码
<p v-show="isVisible">会被隐藏的文本</p>

react:

jsx 复制代码
function MyComponent({ isVisible }) {
  return (
    // 方式1:通过 style 控制 display
    <p style={{ display: isVisible ? 'block' : 'none' }}>
      会被隐藏的文本
    </p>

    // 方式2:通过类名(配合 CSS)
    // <p className={isVisible ? 'visible' : 'hidden'}>文本</p>
    // CSS: .hidden { display: none; } .visible { display: block; }
  );
}

(3)v-for(列表渲染)

Vue 中通过指令遍历数组;React 中通过数组的 map 方法 实现,需手动添加 key(类似 Vue 的 :key)。

vue:

vue 复制代码
<ul>
  <li v-for="(item, index) in list" :key="index">
    {{ item.name }}
  </li>
</ul>

react:

jsx 复制代码
function MyComponent({ list }) {
  return (
    <ul>
      {list.map((item, index) => (
        <li key={index /* 推荐用唯一ID,如item.id */}>
          {item.name}
        </li>
      ))}
    </ul>
  );
}

(4)v-bind(属性绑定)

Vue 中通过 v-bind:xxx 绑定属性;React 中直接在 JSX 中用大括号 {} 绑定。

vue:

vue 复制代码
<img v-bind:src="imgUrl" v-bind:alt="imgAlt" />
<!-- 简写 -->
<img :src="imgUrl" :alt="imgAlt" />

react:

jsx 复制代码
function MyComponent({ imgUrl, imgAlt }) {
  return <img src={imgUrl} alt={imgAlt} />;
}

注意:React 中部分属性名与 HTML 不同(如 className 对应 class,htmlFor 对应 for)。

(5)v-on(事件绑定)

Vue 中通过 v-on:xxx 绑定事件;React 中通过 onXxx 驼峰命名法 绑定,事件处理函数直接传入。

vue:

vue 复制代码
<button v-on:click="handleClick">点击</button>
<!-- 简写 -->
<button @click="handleClick">点击</button>

react:

jsx 复制代码
function MyComponent() {
  const handleClick = () => {
    console.log('点击了');
  };
  return <button onClick={handleClick}>点击</button>;
}

(6)v-model(双向绑定)

Vue 中 v-modelvalue + input 事件的语法糖;React 中需手动实现「状态绑定 + 事件更新」

如果你完全没了解过react,那么我建议你先去看完下一节实现ref和reactive数据响应式再看这个

vue:

vue 复制代码
<input v-model="username" />
<p>输入的内容:{{ username }}</p>

react:

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

function MyComponent() {
  // 1. 用 state 存储值
  const [username, setUsername] = useState('');

  // 2. 定义事件处理函数更新 state
  const handleChange = (e) => {
    setUsername(e.target.value);
  };

  // 3. 绑定 value 和 onChange
  return (
    <div>
      <input value={username} onChange={handleChange} />
      <p>输入的内容:{username}</p>
    </div>
  );
}

2、在react中实现类似vue的 refreactive的数据响应式:

React 的 useState 可以很简洁地实现类似 Vue 中 ref 的响应式功能。核心思路是:用 useState 存储数据,通过状态更新函数触发视图刷新,达到数据变化自动更新 UI 的效果:

jsx 复制代码
// 和vue一样需要导入
import { useState } from 'react';

function Counter() {
  // 1. 调用useState,初始值为0
  // 返回 [当前计数, 更新计数的函数],用数组解构获取
  const [count, setCount] = useState(0);

  return (
    <div>
      {/* 显示当前状态 */}
      <p>当前计数:{count}</p>
      {/* 点击按钮时,调用更新函数修改状态 */}
      <button onClick={() => setCount(count + 1)}>
        +1
      </button>
    </div>
  );
}
export default Counter;

在react中实现数据响应式麻烦一点,需要你手动的调用更新函数去更新页面才会更新,在react中这叫状态管理,而类似的useStateHook

3、父子组件之间传递数据:Props 传递

父组件通过属性(props)把数据传给子组件。子组件通过 props 接收,若要修改,需调用父组件传过来的更新函数。跟vue的比较像

jsx 复制代码
// 父组件
function Parent() {
  const [name, setName] = useState("小明");

  return (
    <div>
      <Child name={name} onNameChange={(newName) => setName(newName)} />
    </div>
  );
}

// 子组件
function Child({ name, onNameChange }) {
  return (
    <div>
      <p>姓名:{name}</p>
      <button onClick={() => onNameChange("小红")}>改名</button>
    </div>
  );
}

4、react中实现全局状态管理

当多个组件(跨层级、非父子)需要共享数据(如用户信息、购物车、主题设置),可以用:

  • useContext + useReducer:React 内置方案,适合中小型应用。
  • 第三方库:如 Redux、Zustand、Jotai 等,适合大型应用。

这里主要演示第一种,第三方库的可以自行了解或者有需要后期出教程

jsx 复制代码
// 1. 创建上下文
const ThemeContext = createContext();

// 2. 顶层组件提供数据
function App() {
  const [theme, setTheme] = useState("light");
  return (
    <ThemeContext.Provider value={{ theme, setTheme }}>
      <Header />
      <Content />
    </ThemeContext.Provider>
  );
}

// 3. 任意子组件使用数据
function Header() {
  const { theme } = useContext(ThemeContext);
  return <div>当前主题:{theme}</div>;
}

5、react中的事件处理:

React 的事件处理机制与原生 JavaScript 类似,但有一些语法和行为上的差异,在给标签绑定事件的时候,采用驼峰命名法(如 onClick 而非 onclick

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

function EventExamples() {
  const [message, setMessage] = useState('');
  const [coords, setCoords] = useState({ x: 0, y: 0 });
  const [isHovered, setIsHovered] = useState(false);

  // 1. 点击事件 (onClick)
  const handleClick = () => {
    alert('按钮被点击了!');
  };

  // 2. 输入框变化事件 (onChange)
  const handleInputChange = (e) => {
    setMessage(e.target.value);
  };

  // 3. 键盘按下事件 (onKeyDown)
  const handleKeyDown = (e) => {
    if (e.key === 'Enter') {
      alert(`你输入了:${message}`);
    }
  };

  // 4. 鼠标移动事件 (onMouseMove)
  const handleMouseMove = (e) => {
    setCoords({
      x: e.clientX,
      y: e.clientY
    });
  };

  // 5. 鼠标悬停/离开事件 (onMouseEnter / onMouseLeave)
  const handleMouseEnter = () => {
    setIsHovered(true);
  };

  const handleMouseLeave = () => {
    setIsHovered(false);
  };

  // 6. 表单提交事件 (onSubmit)
  const handleSubmit = (e) => {
    e.preventDefault(); // 阻止默认提交行为
    alert(`表单提交:${message}`);
  };

  return (
    <div style={{ padding: 20 }}>
      {/* 1. 点击事件 */}
      <button onClick={handleClick}>点击我</button>
      <br /><br />

      {/* 2. 输入框变化 + 3. 键盘事件 */}
      <input
        type="text"
        placeholder="输入内容,按回车确认"
        value={message}
        onChange={handleInputChange}
        onKeyDown={handleKeyDown}
      />
      <br /><br />

      {/* 4. 鼠标移动事件 */}
      <div 
        style={{ border: '1px solid #ccc', padding: 10, marginTop: 10 }}
        onMouseMove={handleMouseMove}
      >
        移动鼠标查看坐标:
        X: {coords.x}, Y: {coords.y}
      </div>
      <br />

      {/* 5. 鼠标悬停/离开事件 */}
      <div 
        style={{ 
          width: 100, 
          height: 100, 
          backgroundColor: isHovered ? 'lightblue' : 'lightgray' 
        }}
        onMouseEnter={handleMouseEnter}
        onMouseLeave={handleMouseLeave}
      >
        {isHovered ? '鼠标在这' : '鼠标离开'}
      </div>
      <br />

      {/* 6. 表单提交事件 */}
      <form onSubmit={handleSubmit}>
        <input
          type="text"
          placeholder="输入内容提交"
          value={message}
          onChange={handleInputChange}
        />
        <button type="submit">提交</button>
      </form>
    </div>
  );
}

export default EventExamples;

6、在react中获取dom实例

在 React 中获取 DOM 元素实例主要通过 useRef 钩子函数实现,这是官方推荐的方式。useRef 会创建一个可变的 ref 对象,其 .current 属性可以存储 DOM 元素的引用。

步骤:

  1. useRef(null) 创建一个容器,用来存 DOM 元素
  2. 通过 ref={myInput} 把 input 元素和这个容器绑定
  3. myInput.current 就能拿到真实的 DOM 元素(如输入框)
  4. 可以直接调用 DOM 方法(如 focus())或访问属性(如 value
jsx 复制代码
import { useRef, useEffect } from 'react';

function SimpleRef() {
  // 1. 创建ref
  const myInput = useRef(null);

  // 2. 组件挂载后操作DOM
  useEffect(() => {
    // myInput.current 就是input的DOM元素
    myInput.current.focus(); // 自动聚焦
  }, []);

  // 3. 点击按钮获取输入框值
  const showValue = () => {
    alert(myInput.current.value); // 直接访问DOM的value
  };

  return (
    <div>
      {/* 绑定ref到input */}
      <input ref={myInput} placeholder="请输入..." />
      <button onClick={showValue}>显示输入内容</button>
    </div>
  );
}

export default SimpleRef;

7、react的生命周期(主要通过用 useEffect 实现)

组件挂载时(初始化):

jsx 复制代码
useEffect(() => {
  console.log('组件挂载完成');
  // 可做初始化操作(如请求数据、绑定事件)
}, []); // 空依赖数组:只执行一次

组件更新时(依赖变化):

jsx 复制代码
const [count, setCount] = useState(0);

useEffect(() => {
  console.log(`count 变化了:${count}`);
  // 依赖 count,只有 count 变了才执行
}, [count]); // 依赖数组:指定监听的变量

组件卸载时(清理):

通过useEffect return 函数,在函数体内进行清理操作

jsx 复制代码
useEffect(() => {
  // 组件挂载时执行
  const timer = setInterval(() => console.log('定时器运行中'), 1000);
  
  // 返回清理函数,组件卸载时执行
  return () => {
    clearInterval(timer); // 清理定时器
    console.log('组件卸载,清理完成');
  };
}, []);

完整示例:

jsx 复制代码
import { useState, useEffect } from 'react';

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

  // 1. 挂载时执行(只一次)
  useEffect(() => {
    console.log('组件挂载了');
    return () => {
      // 3. 卸载时执行
      console.log('组件卸载了');
    };
  }, []);

  // 2. 依赖 count 更新时执行
  useEffect(() => {
    console.log(`count 变为:${count}`);
  }, [count]);

  return (
    <div>
      <p>count: {count}</p>
      <button onClick={() => setCount(count + 1)}>加1</button>
    </div>
  );
}

8、react的路由:

React 路由用于实现单页应用(SPA)的页面跳转,核心是通过 react-router-dom 库实现:

(1)安装依赖:

bash 复制代码
npm install react-router-dom

(2)基础路由示例:

jsx 复制代码
import { BrowserRouter as Router, Routes, Route, Link } from 'react-router-dom';

// 1. 定义两个页面组件
function Home() {
  return <h2>首页</h2>;
}

function About() {
  return <h2>关于页</h2>;
}

// 2. 配置路由
function App() {
  return (
    <Router>
      <div>
        {/* 导航链接(类似a标签,但不会刷新页面) */}
        <nav>
          <Link to="/" style={{ marginRight: 10 }}>首页</Link>
          <Link to="/about">关于</Link>
        </nav>

        {/* 路由匹配区域:url对应哪个组件就显示哪个 */}
        <Routes>
          <Route path="/" element={<Home />} /> {/* 根路径显示Home */}
          <Route path="/about" element={<About />} /> {/* /about显示About */}
        </Routes>
      </div>
    </Router>
  );
}

export default App;

说明:

  • <Router>:路由容器,必须包裹整个路由系统(通常放在根组件)。
  • <Link>:导航链接,类似 HTML 的 <a> 标签,但点击时不会刷新页面,只是修改 URL;to 属性:指定跳转的路径(如 to="/about")。
  • <Routes>:路由匹配容器,内部包含多个 <Route>
  • <Route>:定义路径与组件的对应关系;path:URL 路径(如 path="/about");element:该路径对应的组件(如 element={<About />})。
相关推荐
渊不语3 小时前
PasteTextArea 智能文本域粘贴组件 - 完整实现指南
react.js
Spider_Man4 小时前
React 组件缓存与 KeepAlive 组件打造全攻略 😎
前端·react.js·typescript
GISer_Jing5 小时前
React Native核心技术深度解析_Trip Footprints
javascript·react native·react.js
默默地离开6 小时前
React当中受控组件与非受控组件的区别
前端·javascript·react.js
江城开朗的豌豆6 小时前
useCallback:从性能焦虑到精准优化的轻松之路
前端·javascript·react.js
江城开朗的豌豆6 小时前
Redux 与 React-Redux:从“全局变量”到“响应式状态”的优雅之道
前端·javascript·react.js
江城开朗的豌豆6 小时前
点击弹窗外部自动关闭?一个useRef Hook就搞定!
前端·javascript·react.js
海海思思21 小时前
React 虚拟列表中的 Hook 使用陷阱
react.js
车前端1 天前
React 18 核心新特性解析
react.js