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 / setStateuseState
React.createRefuseRef
componentDidMountuseEffect(,[])
componentDidUpdateuseEffect (,[依赖])
componentWillUnmountuseEffect 返回清理函数
缓存计算值useMemo
缓存方法useCallback
多层传 propsuseContext

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

和localStorage对比

对比维度Redux StorelocalStorage
存储位置浏览器的内存(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开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐