1.vue

1.1vue2

1.2vue3

2.react

创建项目

npm create vite@latest my-app -- --template react-ts

2.1基本语法

遍历

//遍历使用map  
const products = [
        { title: '卷心菜', isFruit: false, id: 1 },
        { title: '大蒜', isFruit: false, id: 2 },
        { title: '苹果', isFruit: true, id: 3 },
    ];
        const listItems = products.map(product => {
            return (
                <li key={product.id} style={{color:product.isFruit? 'magenta':'darkgreen'}}>
                    {product.title}
                </li>
                )
        })
    return (
        <>
            <ul>{listItems}</ul>
        </>

    )

条件判断

 const [state, setState] = useState(true)
    return (
        <>
            <h1>My</h1>
            <div>姓名:{name ?? "李四"}</div>
            <div>年龄: {age ?? 20}</div>
            <MyApp/>
            <MyButton1/>
            {/*条件判断*/}
            {!state && <MyButton1/>}
            {/*三元表达式*/}
            {state ? <div>大米多多</div> : <div>大米少少</div>}
        </>

组件传值props

function MyButton({count, onClick}: { count: number; onClick: () => void }) {

    return (
        <button onClick={onClick}>
            点击{count}次
        </button>
    )
}

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

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

    return (
        <div>
            <h1>共同更新的计数器</h1>
            <MyButton count={count} onClick={handleClick}/>
            <MyButton count={count} onClick={handleClick}/>
        </div>

    )
}

2.2类组件(Class Component)

基本格式

//继承 React.Component 的 ES6 class
class App extends React.Component {
//固定写法,必须第一行,继承父类 React.Component 的能力,否则拿不到 this.props
    constructor(props) {
        super(props);
//创建 DOM / 组件引用
        this.pageRef = React.createRef()
//初始化组件所有响应式数据
        this.state = {
            loading: false,
            sendChangeId: null,
            changeSettingId: null,
            changeProgressId: null,
        }
    }
render() {
        
        return <>
          //要返回的内容
        </>
    }
}

export default App

修改值

this.setState({ sendChangeId: id })

render () 渲染函数(类组件必备)

生命周期

生命周期是组件从创建→渲染→更新→销毁自动执行的钩子函数:

  1. componentDidMount:组件第一次渲染完成后执行,一般在这里发初始化接口请求加载表格数据
  2. componentDidUpdate:state/props 更新页面重渲染后执行
  3. componentWillUnmount:组件销毁前执行,清除定时器、取消请求,防止内存泄漏

2.3函数组件(Function Component)

基本格式

import React, { useState, useRef, useEffect } from 'react'
import { Button } from 'antd'

// 1. 定义函数,props接收父组件传参
const DemoPage = (props) => {
  // 2. 内部写所有Hook、变量、方法(Hook必须写在最顶部,不能分支/循环里)
  const [loading, setLoading] = useState(false)
  const tableRef = useRef(null)

  // 自定义方法
  const handleClick = () => {
    console.log(props.title)
  }
useEffect(() => {
  console.log('changeSettingId变化', changeSettingId)
}, [changeSettingId])

  // 3. return 返回JSX,唯一根节点
  return (
    <div>
      <h1>{props.title}</h1>
      <Button onClick={handleClick}>点击</Button>
    </div>
  )
}

// 导出组件
export default DemoPage

函数组件本质就是返回 JSX 的普通 JS 函数,无class、无this、无构造函数、无生命周期。

和 Class 组件核心区别

  1. 没有this,所有状态、ref、方法都是局部变量;
  2. 靠 Hooks 管理状态、副作用、DOM 引用;
  3. 无生命周期函数,用useEffect模拟挂载 / 更新 / 销毁;
  4. 代码更简洁,无 constructor、bind 绑定 this 的麻烦;
  5. Hook 有严格调用规则:只能在函数组件顶层调用,不能 if/for/ 子函数内调用
Class 功能 函数组件 Hook
this.state / setState useState
React.createRef useRef
componentDidMount useEffect(,[])
componentDidUpdate useEffect (,[依赖])
componentWillUnmount useEffect 返回清理函数
缓存计算值 useMemo
缓存方法 useCallback
多层传 props useContext

2.4路由跳转

安装

npm install react-router-dom

配置

在项目的入口文件(如 index.js 或 main.tsx)中,使用 BrowserRouter 包裹根组件 App

使用(声明式,命令式)

import {useState} from 'react'
import {Routes, Route, Link, useNavigate} from 'react-router-dom';
import Home from './pages/Home';
import Detail from './pages/Detail';
import My from './pages/My';
import About from './pages/About';
import Redux from './pages/Redux';
import './App.css';

function App() {
    const [count, setCount] = useState(0)
    const navigate = useNavigate();
    function Click() {
        // 路径参数
        navigate('/detail/23');
    }
    function ToAbout() {
        //查询参数
        navigate('/about?keyword=react&page=1');
    }
    function AddSum() {
        setCount(count + 1);
    }
    function ToMy() {
        //对象参数
        navigate('my',{
            state: {
                name:"张三",
                age:20
            }
        })
    }

    return (
        <>
            <div className="title">
                {/*声明式跳转,适用于不带参数的直接跳转*/}
                <Link to="/">首页</Link>
                <Link to="/detail/23">详情</Link>
                <Link to="/about">关于</Link>
                <Link to="/my">我的</Link>
                <Link to="/redux">状态</Link>
            </div>
            <div>
                {/*命令式跳转 适合带参数的跳转*/}
                <button onClick={Click}>点击详情</button>
                <button onClick={ToAbout}>点击关于</button>
                <button onClick={AddSum}>点击自增</button>
                <button onClick={ToMy}>点击我的</button>
                <div>{count}</div>
            </div>

            {/*  显示区域*/}
            <Routes>
                <Route path="/" element={<Home/>}/>
                <Route path="/detail/:id" element={<Detail/>}/>
                <Route path="/about" element={<About/>}/>
                <Route path="/my" element={<My/>}/>
                <Route path="/redux" element={<Redux/>}/>
            </Routes>


        </>
    )
}

export default App

2.4.1接收参数

路径参数使用 useParams 接收

查询参数使用 使用 useSearchParams接收

对象参数使用useLocation 接收

import {useSearchParams} from 'react-router-dom'
import {Button} from "antd";
function About() {

    return (
        <>
        <h1>About</h1>
            <Search/>
            <Button type="primary">Button</Button>
        </>
    )
}
function Search() {
    //接收查询参数
    const [searchParams] = useSearchParams();
    const keyword = searchParams.get('keyword'); // 获取到 "react"
    return <p>关键词:{keyword}</p>;
}
export default About;



import {useParams} from "react-router-dom";

function Detail() {
    //接收路径参数
    const { id } = useParams();
    return (
        <>
         <h1>我是Detail页面,id是{id}</h1>
        </>
    )
}

export default Detail



import {useLocation } from "react-router-dom";

function My() {
    //接收对象参数
   const data =  useLocation ()
    const {name,age} = data.state?? {}
    return (
        <>
            <h1>My</h1>
            <div>姓名:{name?? "李四"}</div>
            <div>年龄: {age?? 20}</div>
        </>
    )
}

export default My

2.4.2动态路由

2.4.3路由守卫

总结:

1. 声明式跳转:<Link> 组件
最常用在导航栏、菜单等位置,点击后直接跳转,不会刷新页面。

2. 命令式跳转:useNavigate Hook
最常用在按钮点击、表单提交成功或接口请求完成后的逻辑中。

2.5状态管理(Redux)

npm install @reduxjs/toolkit react-redux

创建状态切片

import {createSlice} from "@reduxjs/toolkit";

export const counterSlice = createSlice({
    name: "counter",
    initialState: {value:0,name:"存储的信息"},
    reducers: {
        increment: (state) => {
            state.value += 1
        },
        decrement: (state) => {
            state.value -= 1
        }
    }
})
//导出生成的 action creators(动作创建器)
export const {increment,decrement} = counterSlice.actions;
// 导出 reducer
export default counterSlice.reducer;

创建全局Store

import {configureStore} from "@reduxjs/toolkit";
import {counterSlice} from "./redux/counterSlice.tsx";
//使用 configureStore 创建 Store,并将上一步创建的 reducer 添加进去
export default configureStore({
    reducer: {
        counter: counterSlice.reducer,
    }
})

在应用入口提供Store

import { createRoot } from 'react-dom/client'
import './index.css'
import App from './App.tsx'
import {BrowserRouter} from "react-router-dom";
import {Provider} from "react-redux";
import store from "./store.tsx";

createRoot(document.getElementById('root')!).render(
      // Provider 包裹 能够使用redux
      <Provider store={store}>
      {/*    路由包裹,能偶使用router*/}
      <BrowserRouter>
          <App />
      </BrowserRouter>
      </Provider>
)

在页面中使用:


import {useDispatch, useSelector} from "react-redux";
import {decrement, increment} from "../redux/counterSlice.tsx";
function Redux () {
    // 从全局 store 中读取 count 值
    const count = useSelector((state) => state.counter.value);
    const name = useSelector((state) => state.counter.name);
    // 获取 dispatch 函数
    const dispatch = useDispatch();

    return (
        <div>
            <h1>当前计数:{count}</h1>
            <h1>姓名:{name}</h1>
            <button onClick={() => dispatch(increment())}>增加</button>
            <button onClick={() => dispatch(decrement())}>减少</button>
        </div>
    );
}

export default Redux;

核心

方法 / API 所属库 核心作用 一句话总结
createSlice Redux Toolkit 创建状态切片 自动帮你生成 actionreducer,你只需写更新状态的逻辑。
configureStore Redux Toolkit 创建全局 Store 一键创建 Store,自动配置好中间件和调试工具。
Provider React-Redux 全局注入 Store 在根组件包裹 <App />,让所有子组件都能访问到全局状态。
useSelector React-Redux 读取全局状态 在组件里“订阅”数据,状态一变,组件自动重新渲染。
useDispatch React-Redux 触发状态更新 拿到 dispatch 函数,用来派发 action,修改全局数据。

和localStorage对比

对比维度 Redux Store localStorage
存储位置 浏览器的内存(RAM)中 浏览器的本地磁盘(ROM)中
数据持久性 无法持久化。页面刷新(F5)或关闭后,内存释放,数据会被重置为初始值。 永久持久化。除非用户手动清除或代码删除,否则关闭浏览器后数据依然存在。
响应式更新 具备响应式。当 Store 中的数据发生变化时,订阅了该数据的组件会自动重新渲染,视图会实时更新。 无响应式。数据改变后,页面视图不会自动更新。如果两个组件共用该数据,一个改了,另一个无法自动感知。
数据读取速度 极快(直接读取内存对象)。 相对较慢(需要从磁盘读取,且存取时通常需要进行 JSON 序列化和反序列化)。
核心应用场景 管理应用内多个组件之间需要共享且频繁变化的状态(如购物车数据、全局筛选条件)。 管理跨页面、跨会话的静态数据(如 Token、用户ID、菜单记忆、用户偏好设置)。

3.ts

4.uni-app

uni-app 是一个使用 Vue.js 语法开发前端应用的框架。它的核心优势是“一套代码,多端运行”。开发者编写一套代码后,可以将其编译发布到 iOS、Android、Web(H5)、以及各种主流小程序(微信、支付宝、抖音、百度等)和鸿蒙系统上36。它采用原生渲染,性能接近原生项目,且完全兼容 Vue2/Vue3 语法,零学习成本

官网地址:uni-app快速上手 | uni-app官网

4.1重要概念和语法

  • pages/:存放所有业务页面,页面必须在此注册路由才能访问。
  • static/:存放图片、字体等静态资源。
  • components/:存放全局公共组件。
  • pages.json重中之重,用于配置页面路由、导航栏标题、颜色以及 tabBar 等
  • 单位rpx
  • 绑定事件用@click 或者@tap
  • onLoad(options):页面首次加载时触发,只执行一次。常用于初始化数据、解析 URL 参数或发起网络请求。
  • onShow():页面每次显示时触发(包括从其他页面返回)。常用于刷新列表或更新状态。
  • 下拉刷新:需在 pages.json 中开启 enablePullDownRefresh。在页面中监听 onPullDownRefresh 事件,用于重置页码并重新加载第一页数据,加载完成后调用 uni.stopPullDownRefresh() 停止动画。
  • 上拉加载更多:监听 onReachBottom 事件,当页面滚动到底部时触发,用于请求下一页数据。

4.2基本语法

创建项目(vue3+ts)

npx degit dcloudio/uni-preset-vue#vite-ts my-vue3-project

安装依赖:

npx @dcloudio/uvm@latest

tabbar

{
	"pages": [
		{
			"path": "pages/index/index",
			"style": {
				"navigationBarTitleText": "首页"
			}
		},
		{
			"path": "pages/cart/index",
			"style": {
				"navigationBarTitleText": "购物车"
			}
		},
		{
			"path": "pages/my/index",
			"style": {
				"navigationBarTitleText": "我的"
			}
		},
		{
			"path": "pages/subpage/list/list", // 页面路径是相对于 root 的,同样不写 .vue 后缀
			"style": {
				"navigationBarTitleText": "测试页面"
			}
		}
	],
//	"subPackages": [
//		{
//			"root": "subpage", // 分包的根目录
//			"pages": [
//				{
//					"path": "list/list", // 页面路径是相对于 root 的,同样不写 .vue 后缀
//					"style": {
//						"navigationBarTitleText": "测试页面"
//					}
//				}
//			]
//		}
//	],
	"tabBar": {
		"color": "#999999",
		"selectedColor": "#007AFF",
		"backgroundColor": "#ffffff",
		"list": [
			{
				"pagePath": "pages/index/index",
				"text": "首页"
			},
			{
				"pagePath": "pages/cart/index",
				"text": "购物车"
			},
			{
				"pagePath": "pages/my/index",
				"text": "我的"
			}
		]
	},
	"globalStyle": {
		"navigationBarTextStyle": "black",
		"navigationBarTitleText": "uni-app",
		"navigationBarBackgroundColor": "#F8F8F8",
		"backgroundColor": "#F8F8F8"
	}
}

4.3页面跳转

4.3.1保留式跳转:uni.navigateTo

  • 原理:保留当前页面,将其压入页面栈(page stack),跳转到新页面。用户可以通过左滑或返回按钮回到上一页。

  • 适用场景:列表页跳转到详情页、表单页跳转到确认页等所有需要支持返回的场景。

  • 传值方式:直接在 url 后面拼接参数(如 ?id=123&name=John)。

  • 接收参数:在目标页面的 onLoad(options) 生命周期中,通过 options.id 获取。

跳转代码演示:

uni.navigateTo({
    url: `/pages/basedataubpage/detail/studentdetail?id=${item.id}&templateId=${templateId}&schoolId=${schoolId}`
  })

接收:

onLoad(async (options: OnLoadOptions) => {
  const id = options.id
  const templateId = options.templateId 
  await getStudentInfoNameByIdInfo(id)
  loadForm(id, templateId, options.schoolId)
})

4.3.2. 替换式跳转:uni.redirectTo

  • 原理:关闭当前页面,再打开新页面。当前页面会被销毁,用户在新页面无法通过返回键回到被关闭的那一页。
  • 适用场景:登录成功后跳转首页、支付成功页、注册完成页等“一次性”操作完成后的跳转。

4.3.3. 全清重置跳转:uni.reLaunch

  • 原理:关闭应用内所有页面后,打开指定页面。页面栈被完全清空,是最彻底的跳转方式。
  • 适用场景:退出登录、切换账号、应用重置。

4.3.4 Tab 页跳转:uni.switchTab

  • 原理:专门用于跳转到 pages.json 中配置了 tabBar 的页面。跳转时会关闭所有非 tabBar 页面。
  • 适用场景:底部 Tab 切换、业务流程结束回到主页。
  • 注意:switchTab 的 url 不能带参数。如果需要向 Tab 页传递数据,可以通过全局变量(globalData)、Pinia/Vuex 或 Storage 中转。

4.3.5. 返回上级:uni.navigateBack

  • 原理:关闭当前页面,返回上一页或多级页面。
  • 适用场景:表单取消、弹窗关闭、跨级返回。

4.4组件传值

4.4.1父传子(Props)

子组件:

<template>
  <view>{{title}}</view>
  <view>{{count}}</view>
</template>
<script lang="ts" setup>
const props = defineProps({
  title: {
    type: String,
    default: '默认标题'
  },
  count: {
    type: Number,
    default: 0
  }
})
</script>
<style scoped>

</style>

父组件:

<template>
  <view>
    <button @tap ="gotoPage">点击跳转到列表页</button>
  </view>
  <view>
    <ChildComponent :title="title" :count="count"/>
  </view>

</template>

<script setup lang="ts">
import { ref } from 'vue'
import ChildComponent from './ChildComponent.vue'

const title = ref('Hello')
const count = ref(1222)
const gotoPage = () => {
  uni.navigateTo({
    url: '/pages/subpage/list/list'
  })
}
</script>

<style>

</style>

4.4.2子传父(emits)

子组件:

<template>
 <button @click="sendData">点击向父组件发送数据</button>
</template>
<script lang="ts" setup>
//定义要触发的事件名称
const emits = defineEmits(['sendData'])
//触发事件,并传递参数
const sendData = () => {
  emits(`sendData`,{name:'Hello',age:25})
}
</script>
<style scoped>

</style>

父组件:

<template>
  <view>
    <button @tap ="gotoPage">点击跳转到列表页</button>
  </view>
  <view>
<!-- 父传子-->
    <ChildComponent :title="title" :count="count"/>
<!--    子传父-->
    <child-component1 @sendData="handleChildData"/>
<!--    兄弟相传/跨页面-->
    <ChildComponent2/>
  </view>

</template>

<script setup lang="ts">
import { ref } from 'vue'
import ChildComponent from './ChildComponent.vue'
import ChildComponent1 from './ChildComponent1.vue'
import ChildComponent2 from '/src/pages/cart/Component2.vue'

const title = ref('Hello')
const count = ref(1222)
const handleChildData = (data:any) => {
  console.log("子组件传过来的值",data)
}
const gotoPage = () => {
  uni.navigateTo({
    url: '/pages/subpage/list/list'
  })
}
</script>

<style>

</style>

4.4.3兄弟/不同页面(uni.$emit,uni.$on,uni.$off)

A组件:

<template>
  <button @click="notifyBrother">跨页面/兄弟组件传值</button>
</template>
<script lang="ts" setup>
  const notifyBrother = () => {
    //全局触发事件
    uni.$emit('sync-user-info',{userId:1,userName:"张三"})
  }
</script>
<style scoped>

</style>

B组件:

<template>
  <view>我的购物车页面</view>
  <text>接受的用户数据是:{{userInfo}}</text>
</template>

<script lang="ts" setup>
import {ref,onMounted,onUnmounted} from 'vue'
const userInfo = ref(null);
//接收到的数据
const handleSync = (data:any) => {
  userInfo.value = data;
  console.log("接收到的数据",data);
}
//在组件挂载的时候监听
onMounted(() => {
  uni.$on('sync-user-info', handleSync);
})
//卸载前移除监听
onUnmounted(() => {
  uni.$off('sync-user-info', handleSync);
})
</script>
<style scoped>

</style>

4.4.4 v-model

子组件:

<template>
  <view>
    <input :value="modelValue" @input="handleInput" placeholder="请输入内容">
  </view>
</template>
<script lang="ts" setup>
const props = defineProps({
  modelValue: { //必须叫modelValue
    type: String,
    default: '',
  }
})
//触发事件
const emit = defineEmits(['update:modelValue'])

const handleInput = (e:any) => {
  //将新值通过事件回传给父组件
  emit('update:modelValue', e.detail.value)
}
</script>

<style scoped>

</style>

父组件:



<template>
   <view>我的页面</view>
<!--  自定义组件支持 v-model-->
   <ChildComponent3 v-model="inputValue"/>
  <text>输入的值是:{{inputValue}}</text>
<!--  父类直接操作子类的方法-->
  <Component4 ref="childRef"/>
  <button @click="callChild"> 调用子组件的方法</button>

</template>
<script lang="ts" setup>
import  {ref} from "vue";
import ChildComponent3 from './Component3.vue'
const inputValue = ref("")

import Component4 from './Component4.vue'
//创建一个ref来接收子组件的实例
const childRef = ref(null)
const callChild = () =>{
  childRef.value.childMethod("我是父组件传来的参数")
}
</script>
<style scoped>

</style>

4.4.5 ref

<template>
  <view>
    <text>子组件内容</text>
  </view>
</template>
<script lang="ts" setup>
const childMethod = (msg: string) => {
  console.log("父组件调用我的方法",msg)
}
//将方法暴漏出去
defineExpose(
    {
      childMethod
    }
)
</script>

<style scoped>

</style>

4.5常用方法

下拉刷新/上拉加载更多

在 pages.json 中开启配置

"pages": [
		{
			"path": "pages/index/index",
			"style": {
				"navigationBarTitleText": "首页",
				"enablePullDownRefresh": true, // 开启下拉刷新
				"onReachBottomDistance": 50    // 距离底部 50px 时触发上拉加载
			}
		},
		{
			"path": "pages/cart/index",
			"style": {
				"navigationBarTitleText": "购物车"
			}
		},
		{
			"path": "pages/my/index",
			"style": {
				"navigationBarTitleText": "我的"
			}
		},
		{
			"path": "pages/subpage/list/list", // 页面路径是相对于 root 的,同样不写 .vue 后缀
			"style": {
				"navigationBarTitleText": "测试页面"
			}
		}
	],

在代码处导入方法

import { onPullDownRefresh, onReachBottom } from '@dcloudio/uni-app'

//下拉刷新事件
onPullDownRefresh(() => {

})
//上拉触底事件
onReachBottom(() => {

})

4.6uni-app x

5.组件库

5.1.移动端

Button 按钮 | Wot UI

安装

pnpm add @wot-ui/ui

pnpm add sass@^1.98.0 -D

配置

//pages.json
"easycom": {
		"autoscan": true,
		"custom": {
			"^wd-(.*)": "@wot-ui/ui/components/wd-$1/wd-$1.vue",
		}
	},

使用

<wd-button>主要按钮</wd-button>
  <wd-button type="success">成功按钮</wd-button>
  <wd-button type="info">信息按钮</wd-button>
  <wd-button type="warning">警告按钮</wd-button>
  <wd-button type="danger">危险按钮</wd-button>

uni-ui 介绍 | uni-app官网

安装

pnpm add @dcloudio/uni-ui

配置

"easycom": {
		"autoscan": true,
		"custom": {
			"^uni-(.*)": "@dcloudio/uni-ui/lib/uni-$1/uni-$1.vue"
		}
	},

使用


  <uni-card>
    <text>这是一个基础卡片示例,内容较少,此示例展示了一个没有任何属性不带阴影的卡片。</text>
  </uni-card>

5.2.Web端

Ant Design - 一套企业级 UI 设计语言和 React 组件库

pnpm install antd --save

Ant Design Vue

一个 Vue 3 UI 框架 | Element Plus

pnpm install element-plus

6.前端全栈

6.1next.js

6.2nuxt3

6.3express(node的后端框架)

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐