JavaScript前端核心进阶课
本课作为React框架入门核心课,聚焦React基础语法与实战,从组件化、JSX、Hooks到项目搭建,完整覆盖React入门必备知识点。React以组件化为核心,通过虚拟DOM提升渲染效率,单向数据流保证代码可维护性,Hooks则简化了函数式组件的状态与副作用管理,是当前前端主流框架之一。课程通过单词管理实战案例,串联起组件创建、Props传参、useState响应式、useEffect副作用等核心内容,结合Vite工程化快速搭建项目,帮助建立React组件化开发思维。掌握本课内容,不仅能快速上手React基础开发,还能理解React与Vue3的差异,拓宽前端技术栈,为后续React进阶(路由、状态管理)和企业级项目开发奠定坚实基础。
一、课程学习目的
-
理解React框架的核心理念,掌握组件化开发 、虚拟DOM 、单向数据流三大核心特性。
-
掌握React基础语法,包括JSX语法、组件定义、Props传参、State状态管理。
-
熟练使用React Hooks(useState、useEffect),实现响应式数据与副作用管理。
-
学会React组件的创建、渲染、嵌套与通信,搭建简单的React页面。
-
结合Vite工程化搭建React项目,了解React与Vue3的差异,拓宽前端技术视野。
-
建立React组件化开发思维,为后续React进阶与企业级项目开发奠定基础。
二、核心知识点讲解
1. React 框架基础认知
React是由Facebook开发的开源前端框架,主打组件化 和声明式渲染,核心是将页面拆分为独立、可复用的组件,通过状态驱动视图更新。
核心优势:组件复用性强、虚拟DOM提升渲染效率、单向数据流使代码可预测、生态完善(适配移动端、后端渲染等)。
React 18为当前稳定版本,主推函数式组件+Hooks,替代传统类组件,语法更简洁、上手成本更低。
2. JSX 核心语法
JSX是React的模板语法,将HTML与JavaScript融合,允许在JavaScript中编写类似HTML的代码,最终会被编译为普通JavaScript执行。
核心规则:
-
标签必须闭合(如
、),禁止遗漏闭合标签。
-
className 替代HTML中的class(避免与JavaScript的class关键字冲突)。
-
内联样式需用对象形式编写,如style={{ color: 'red', fontSize: '16px' }}。
-
JavaScript表达式需用{}包裹,如{变量名}、{函数调用()}。
-
只能有一个根节点,多个标签需用
、(简写<></>)包裹。
3. React 组件基础
React组件是页面的最小组成单元,分为函数式组件(推荐)和类组件,函数式组件配合Hooks实现响应式。
-
函数式组件:本质是普通JavaScript函数,返回JSX模板,接收Props参数传递数据。
-
Props:组件间通信的核心,用于父组件向子组件传递数据,Props只读不可修改。
-
State:组件内部的响应式数据,修改State会触发组件重新渲染,需通过useState Hook定义。
4. React Hooks 基础(useState、useEffect)
Hooks是React 16.8推出的特性,允许函数式组件拥有状态和副作用,无需编写类组件。
-
useState:定义组件内部响应式状态,返回"状态变量+修改状态的函数",如const [count, setCount] = useState(0)。
-
useEffect:处理组件副作用(如数据请求、DOM操作、定时器),相当于类组件的生命周期钩子,可控制执行时机。
5. Vite 搭建 React 项目流程
依托前课npm+Vite知识,直接创建React模板项目,内置React环境和Hooks支持,无需手动配置,开箱即用,快速上手开发。
三、示例程序
示例1:React 函数式组件基础(单词展示组件)
jsx
// src/components/WordItem.jsx(子组件)
// 子组件:接收Props传递的单词数据
function WordItem(props) {
// 接收父组件传递的props参数
const { en, cn } = props;
return (
<div className="word-item">
<span>{en} - {cn}</span>
</div>
);
}
export default WordItem;
示例2:useState + useEffect 实战(单词管理器)
jsx
// src/App.jsx(主组件)
import { useState, useEffect } from 'react';
import WordItem from './components/WordItem';
function App() {
// 1. useState定义响应式状态:单词列表、输入框内容
const [wordList, setWordList] = useState([
{ en: 'apple', cn: '苹果' },
{ en: 'banana', cn: '香蕉' }
]);
const [inputEn, setInputEn] = useState('');
const [inputCn, setInputCn] = useState('');
// 2. 定义添加单词方法
const addWord = () => {
if (!inputEn || !inputCn) return;
// 修改状态(不可直接修改原数组,需返回新数组)
setWordList([...wordList, { en: inputEn, cn: inputCn }]);
// 清空输入框
setInputEn('');
setInputCn('');
};
// 3. useEffect处理副作用:页面加载时打印提示
useEffect(() => {
console.log('页面初始化完成,单词列表已加载');
// 依赖项为空数组,仅执行一次(相当于页面加载完成)
}, []);
return (
<div className="app">
<h1>React 单词管理器</h1>
<div className="input-box">
<input
type="text"
placeholder="请输入英文单词"
value={inputEn}
// 绑定输入事件,修改inputEn状态(单向数据流)
onChange={(e) => setInputEn(e.target.value)}
/>
<input
type="text"
placeholder="请输入中文释义"
value={inputCn}
onChange={(e) => setInputCn(e.target.value)}
/>
<button onClick={addWord}>添加单词</button>
</div>
<div className="word-list">
{/* 循环渲染子组件,传递props参数 */}
{wordList.map((item, index) => (
<WordItem key={index} en={item.en} cn={item.cn} />
))}
</div>
</div>
);
}
export default App;
示例3:Vite 创建 React 项目命令
bash
# 1. 创建Vite项目
npm create vite@latest
# 2. 配置项(按提示选择)
# 项目名称:react-word-project
# 框架选择:React
# 语言选择:JavaScript
# 3. 进入项目、安装依赖、启动项目
cd react-word-project
npm install
npm run dev
示例4:main.jsx(项目入口)
jsx
// src/main.jsx
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import './index.css';
// 挂载React组件到页面
ReactDOM.createRoot(document.getElementById('root')).render(
<React.StrictMode>
<App />
</React.StrictMode>
);
四、掌握技巧与方法
-
JSX语法需严格遵循React规则,标签闭合、className、内联样式格式不可出错,否则会导致渲染失败。
-
组件拆分遵循"单一职责",一个组件只做一件事,复杂组件拆分为多个子组件,提升复用性。
-
useState修改状态时,不可直接修改原状态(如wordList.push()),需返回新的状态值(如[...wordList, newItem])。
-
Props是只读的,子组件不可修改父组件传递的Props,如需修改,需通过父组件传递的方法修改。
-
useEffect依赖项控制执行时机:空数组仅执行一次,依赖特定变量则变量变化时执行,无依赖项则每次渲染都执行。
-
调试React组件时,可使用React Developer Tools插件,查看组件结构、状态和Props。
-
区分React与Vue3:React是单向数据流,Vue3支持双向绑定;React依赖Hooks实现响应式,Vue3依赖ref/reactive。
五、课后作业
基础作业
-
用Vite创建React项目,启动并运行默认页面,熟悉React项目结构(src、App.jsx、main.jsx)。
-
编写一个简单的函数式组件,使用useState定义一个响应式变量,通过按钮修改该变量并渲染到页面。
-
创建父组件与子组件,通过Props实现父组件向子组件传递数据并渲染。
进阶作业
-
完善单词管理器,添加删除单词功能,通过useState修改单词列表状态。
-
使用useEffect实现"页面加载时请求模拟数据",并渲染到页面。
-
实现组件嵌套,拆分输入组件、列表组件、单词项组件,提升代码复用性。
实战作业
- 搭建React单词管理系统,整合JSX语法、组件拆分、Props传参、useState、useEffect,实现单词增删、数据渲染、副作用处理,纳入Git版本管理,符合代码规范。
上一课:Vue3 核心进阶(路由与状态管理)实战作业代码
完整实战代码
一、项目结构(规范工程化结构)
Plain
vue3-router-pinia-demo/
├── index.html
├── package.json
└── src/
├── main.js # 全局注册路由、Pinia
├── App.vue # 路由出口、导航栏
├── router/ # 路由配置
│ └── index.js
├── stores/ # Pinia仓库
│ └── wordStore.js
└── views/ # 页面组件
├── Home.vue # 首页
├── WordList.vue # 单词列表页
└── WordDetail.vue # 单词详情页
二、package.json(依赖配置)
Plain
{
"name": "vue3-router-pinia-demo",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
},
"devDependencies": {
"vite": "^5.0.0",
"vue": "^3.4.0"
},
"dependencies": {
"pinia": "^2.1.7",
"vue-router": "^4.3.0"
}
}
三、src/router/index.js(路由配置)
Plain
import { createRouter, createWebHistory } from 'vue-router'
// 导入页面组件
import Home from '../views/Home.vue'
import WordList from '../views/WordList.vue'
import WordDetail from '../views/WordDetail.vue'
// 路由规则:path(路径)→ component(对应组件)
const routes = [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/word-list',
name: 'WordList',
component: WordList
},
// 动态路由传参::word 为参数名
{
path: '/word-detail/:word',
name: 'WordDetail',
component: WordDetail
}
]
// 创建路由实例
const router = createRouter({
history: createWebHistory(), // 历史模式(无#)
routes // 挂载路由规则
})
export default router
四、src/stores/wordStore.js(Pinia仓库)
Plain
import { defineStore } from 'pinia'
// 定义仓库:第一个参数是仓库名(唯一),第二个参数是配置
export const useWordStore = defineStore('word', {
// 存储共享数据
state: () => ({
wordList: [
{ en: 'apple', cn: '苹果' },
{ en: 'banana', cn: '香蕉' },
{ en: 'orange', cn: '橙子' }
]
}),
// 定义修改数据的方法(规范写法)
actions: {
// 添加单词
addWord(word) {
this.wordList.push(word)
},
// 删除单词
delWord(index) {
this.wordList.splice(index, 1)
}
}
})
五、src/main.js(全局注册)
Plain
import { createApp } from 'vue'
import App from './App.vue'
import router from './router' // 导入路由
import { createPinia } from 'pinia' // 导入Pinia
const app = createApp(App)
app.use(router) // 注册路由
app.use(createPinia()) // 注册Pinia
app.mount('#app') // 挂载到页面
六、src/App.vue(路由出口与导航)
Plain
<template>
<div class="app">
<!-- 路由导航栏 -->
<nav class="nav">
<router-link to="/">首页</router-link>
<router-link to="/word-list">单词列表</router-link>
</nav>
<!-- 路由出口:页面组件会渲染到这里 -->
<router-view class="content"></router-view>
</div>
</template>
<style scoped>
.nav {
padding: 20px;
background: #f5f5f5;
}
.nav router-link {
margin: 0 10px;
text-decoration: none;
color: #333;
}
.nav router-link.active {
color: #42b983;
font-weight: bold;
}
.content {
padding: 20px;
max-width: 600px;
margin: 0 auto;
}
</style>
七、src/views/Home.vue(首页)
Plain
<template>
<div class="home">
<h2>Vue3 路由与Pinia实战</h2>
<p>当前单词库总数:{{ wordStore.wordList.length }}</p>
<button @click="$router.push('/word-list')">进入单词列表</button>
</div>
</template>
<script setup>
// 导入Pinia仓库
import { useWordStore } from '../stores/wordStore'
const wordStore = useWordStore()
</script>
八、src/views/WordList.vue(单词列表页)
Plain
<template>
<div class="word-list">
<h2>单词列表</h2>
<div class="input-box">
<input v-model="inputEn" placeholder="英文单词" />
<input v-model="inputCn" placeholder="中文释义" />
<button @click="addWord">添加</button>
</div>
<ul>
<li v-for="(item, index) in wordStore.wordList" :key="index">
{{ item.en }} - {{ item.cn }}
<button @click="delWord(index)">删除</button>
<button @click="toDetail(item.en)">详情</button>
</li>
</ul>
</div>
</template>
<script setup>
import { ref } from 'vue'
import { useWordStore } from '../stores/wordStore'
import { useRouter } from 'vue-router'
const wordStore = useWordStore()
const router = useRouter()
const inputEn = ref('')
const inputCn = ref('')
// 添加单词(调用Pinia的actions方法)
const addWord = () => {
if (!inputEn.value || !inputCn.value) return
wordStore.addWord({ en: inputEn.value, cn: inputCn.value })
inputEn.value = ''
inputCn.value = ''
}
// 删除单词
const delWord = (index) => {
wordStore.delWord(index)
}
// 路由跳转传参
const toDetail = (word) => {
router.push(`/word-detail/${word}`)
}
</script>
<style scoped>
.input-box { margin: 20px 0; }
input { padding: 8px; margin-right: 8px; }
button { padding: 8px 12px; cursor: pointer; background: #42b983; color: #fff; border: none; border-radius: 4px; margin-right: 8px; }
li { margin: 10px 0; padding: 10px; background: #f9f9f9; border-radius: 4px; }
</style>
九、src/views/WordDetail.vue(单词详情页)
Plain
<template>
<div class="word-detail">
<h2>单词详情</h2>
<div v-if="currentWord" class="detail-box">
<p>英文:{{ currentWord.en }}</p>
<p>中文:{{ currentWord.cn }}</p>
</div>
<div v-else>单词不存在</div>
<button @click="$router.back()">返回列表</button>
</div>
</template>
<script setup>
import { useWordStore } from '../stores/wordStore'
import { useRoute } from 'vue-router'
const wordStore = useWordStore()
// 获取路由参数
const route = useRoute()
// 从路由参数中获取单词
const word = route.params.word
// 查找对应的单词信息
const currentWord = wordStore.wordList.find(item => item.en === word)
</script>
十、运行命令
Plain
# 1. 安装依赖(首次运行)
npm install
# 2. 启动开发服务器
npm run dev
# 3. 打包项目(上线用)
npm run build
代码功能说明
本实战代码基于Vite+Vue3,整合Vue Router4与Pinia,实现多页面单词管理系统。项目配置3个路由(首页、单词列表、单词详情),通过路由实现页面跳转与动态传参;用Pinia定义全局状态仓库,统一管理单词数据,实现跨组件数据共享;列表页可添加、删除单词,详情页通过路由参数接收并展示单词信息,首页展示仓库中的单词总数。代码结构规范、注释完整,涵盖路由配置、Pinia仓库定义、组件中使用路由与状态管理等核心知识点,直观演示Vue3进阶开发流程,巩固路由与状态管理用法,适配课程实战要求。
注意事项
-
必须先安装Vue Router和Pinia依赖(npm i vue-router pinia),否则会报模块引入错误。
-
路由配置需正确对应组件路径,动态路由传参格式为"/:参数名",接收参数需用useRoute()。
-
Pinia仓库需用defineStore定义,组件中使用需先通过useStore()获取实例,不可直接修改state。
-
main.js中必须注册Vue Router和Pinia(app.use(router).use(createPinia())),否则无法使用。
-
路由跳转优先使用router.push(),页面展示需用,导航栏用。
-
Pinia中修改数据建议写在actions中,规范统一,便于维护和调试。
-
动态路由参数不可为空,跳转时需确保参数有效,避免页面报错。
-
项目运行命令:npm install → npm run dev,确保依赖安装完整。
作业验收标准
-
项目可正常启动,路由导航切换流畅,无控制台报错。
-
Pinia仓库功能正常,添加、删除单词后,所有组件数据同步更新。
-
动态路由传参有效,详情页能正确接收并展示对应单词信息。
-
代码结构规范,路由配置、Pinia仓库定义、组件使用符合课程知识点。
-
页面交互正常,按钮点击、路由跳转、数据修改无异常。