DC's blog DC's blog
首页
  • 计算机基础
  • linux基础
  • mysql
  • git
  • 数据结构与算法
  • axure
  • english
  • docker
  • opp
  • oop
  • 网络并发编程
  • 不基础的py基础
  • 设计模式
  • html
  • css
  • javascript
  • jquery
  • UI
  • 第一次学vue
  • 第二次学vue
  • Django
  • drf
  • drf_re
  • 温故知新
  • flask
  • 前后端不分离

    • BBS
    • 订单系统
    • CRM
  • 前后端部分分离

    • pear-admin-flask
    • pear-admin-django
  • 前后端分离

    • 供应链系统
  • 理论基础
  • py数据分析包
  • 机器学习
  • 深度学习
  • 华中科大的网课
  • cursor
  • deepseek
  • 杂文
  • 罗老师语录
  • 关于我

    • me
  • 分类
  • 归档
GitHub (opens new window)

DC

愿我一生欢喜,不为世俗所及.
首页
  • 计算机基础
  • linux基础
  • mysql
  • git
  • 数据结构与算法
  • axure
  • english
  • docker
  • opp
  • oop
  • 网络并发编程
  • 不基础的py基础
  • 设计模式
  • html
  • css
  • javascript
  • jquery
  • UI
  • 第一次学vue
  • 第二次学vue
  • Django
  • drf
  • drf_re
  • 温故知新
  • flask
  • 前后端不分离

    • BBS
    • 订单系统
    • CRM
  • 前后端部分分离

    • pear-admin-flask
    • pear-admin-django
  • 前后端分离

    • 供应链系统
  • 理论基础
  • py数据分析包
  • 机器学习
  • 深度学习
  • 华中科大的网课
  • cursor
  • deepseek
  • 杂文
  • 罗老师语录
  • 关于我

    • me
  • 分类
  • 归档
GitHub (opens new window)
  • html

  • css

  • javascript

  • jquery

  • UI库

  • 第一次学vue

  • 第二次学vue

    • vue语法基础
    • 创建vite项目
    • vue-router
      • 单页面应用
      • 快速使用
      • router组件 - 参数
        • 路由无参数
        • url参数的携带与接收
        • 基本实现
        • 同组件跳转不重新接收参数
        • 动态路由参数的携带与接收
      • router组件-嵌套
      • 编程式导航/js代码跳转
        • 关键语法
        • 登陆跳转(含顶部)
        • 登陆跳转(不含顶部)
      • 导航守卫
        • 浏览器的本地存储
        • 登陆才能访问+登出
    • pinia组件
    • cookie组件
    • axios组件
  • 前端
  • 第二次学vue
DC
2025-01-03
目录

vue-router

# 单页面应用

单页面应用 > 一个项目就一个页面
点击导航标签,页面会变换,看似是多个页面,实则是页面公共区域的替换(即加载不同的组件) -- 用Vue Router来实现!
1
2
image-20250103084536924

# 快速使用

dengchuan@MacBook-Air Desktop % npm create vue@latest

Vue.js - The Progressive JavaScript Framework

✔ 请输入项目名称: … vue04
✔ 是否使用 TypeScript 语法? … 否 / 是
✔ 是否启用 JSX 支持? … 否 / 是
✔ 是否引入 Vue Router 进行单页面应用开发? … 否 / 是    # 选择是,其余的都选否
✔ 是否引入 Pinia 用于状态管理? … 否 / 是
✔ 是否引入 Vitest 用于单元测试? … 否 / 是
✔ 是否要引入一款端到端(End to End)测试工具? › 不需要
✔ 是否引入 ESLint 用于代码质量检测? › 否

正在初始化项目 /Users/dengchuan/Desktop/vue04...

项目初始化完成,可执行以下命令:

  cd vue04
  npm install
  npm run dev
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

58

完整代码如下:

注 - <RouterLink> 的本质就是 a标签, 在浏览器上右键可观察到..

image-20250103091424125


# router组件 - 参数

<RouterLink> 的本质就是 a标签

携带参数(url参数、动态路由参数), 同一组件之间跳转的情况,
导航中一般不会出现, 在详情页里, 有其他推荐, 点击推荐, 就是同组件跳转.. 要用onBeforeRouteUpdate 钩子函数来解决!!

同组件跳转 ==>
http://localhost:5173/about?v1=123&v2=888 跳转到 http://localhost:5173/about?v1=123&v2=999
http://localhost:5173/about/1 跳转到 http://localhost:5173/about/2

在onBeforeRouteUpdate中获取到参数后,就可以通过axios重新发送请求来加载页面!!
1
2
3
4
5

# 路由无参数

/src/router/index.js

{
    path: '/about',
    name: 'about',
    component: () => import('../views/AboutView.vue'),
},
1
2
3
4
5

/src/App.vue

// 以下的三种写法皆可对应上面这个index.js中配置的about路由!任选其一即可.
<RouterLink to="/about">About</RouterLink>
<RouterLink :to="{name:'about'}">About</RouterLink>
<RouterLink :to="{path:'/about'}">About</RouterLink>

<RouterLink></RouterLink> 也可写成 <router-link></router-link>
<RouterView/> 也可写成 <router-view/>
1
2
3
4
5
6
7

# url参数的携带与接收

http://localhost:5173/about?v1=123&v2=888

# 基本实现

/src/router/index.js

{
    path: '/about',
    name: 'about',
    component: () => import('../views/AboutView.vue'),
}
1
2
3
4
5

/src/App.vue -- router-link 标签携带url参数..

// 以下两种携带方式任选其一即可
<router-link to="/about?v1=123&v2=888">About</router-link>
<router-link :to="{name:'about', query:{v1:123,v2:888}}">About</router-link>
1
2
3

/src/views/AboutView.vue -- 在/about路由对应的 AboutView.vue组件里进行接收

import {useRoute} from "vue-router"
const route = useRoute()
console.log(route.query)  // {v1: '123', v2: '888'}
1
2
3
# 同组件跳转不重新接收参数

问题: 同一组件(无参数到有参数; 有参数到有参数,但参数不同).. 此时若当前组件跳转到当前组件, 不会重新接收参数.页面不会变化..
解决: 用onBeforeRouteUpdate来解决..

简单来说,当路由仅是路径参数、query、hash 发生改变, 而不是 path 发生改变时, 便会触发 onBeforeRouteUpdate.
onBeforeRouteUpdate 钩子函数可接收三个参数:

  • to: 即将进入的目标路由对象

  • from: 当前导航正要离开的路由对象

  • next: 必须调用该函数来 resolve 这个钩子函数,可以传递一个参数来指示路由的行为

59

导航中, About、About1、About2属于同一个路由, 只是携带的url参数不同(没携带、携带的v2值时888、携带的v2值时999)
若我不使用onBeforeRouteUpdate,  
从Home到任一About, 页面都可正确变化; 若是About组件之间跳转, 浏览器的url地址会变, 但页面不会变化..
gif中是配置了onBeforeRouteUpdate后, 我们想要得到的效果..

/src/App.vue

<template>
    <header>
        <div class="wrapper">
            <nav>
                <RouterLink to="/">Home</RouterLink> |
                <RouterLink to="/about">About</RouterLink> |
                <router-link to="/about?v1=123&v2=888">About1</router-link> |
                <router-link :to="{name:'about', query:{v1:123,v2:999}}">About2</router-link>
            </nav>
        </div>
    </header>
    <RouterView/>
</template>

<script setup></script>

<style scoped></style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

/src/router/index.js

import {createRouter, createWebHistory} from 'vue-router'
import HomeView from '../views/HomeView.vue'

const router = createRouter({
    history: createWebHistory(import.meta.env.BASE_URL),
    routes: [
        {
            path: '/',
            name: 'home',
            component: HomeView,
        },
        {
            path: '/about',
            name: 'about',
            component: () => import('../views/AboutView.vue'),
        },
    ],
})

export default router
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

/src/views/AboutView.vue

<template>
    <h2>About - {{ query_dict }}</h2>
</template>

<style></style>

<script setup>
import {ref} from "vue";
import {useRoute, onBeforeRouteUpdate} from "vue-router"

const route = useRoute()
const query_dict = ref(route.query)

// 捕获到同一组件之间跳转时,路由的url参数等信息!!
onBeforeRouteUpdate(function (to, from) {
    // console.log(to, from)
    query_dict.value = to.query
})

</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

# 动态路由参数的携带与接收

它也存在类似的问题 - 同组件跳转不重新接收动态路由参数.. 同样的,可用onBeforeRouteUpdate来解决.

  • 此次不是用 to.query 来取, 而是用 to.params 来取..
  • {name:'about',params:{nid:1}} + path: '/about/:nid' 这里的nid是对应的.

60

/src/App.vue

<template>
    <header>
        <div class="wrapper">
            <nav>
                <RouterLink to="/">Home</RouterLink>
                |
                <RouterLink :to="{name:'about',params:{nid:1}}">About1</RouterLink>
                |
                <RouterLink :to="{name:'about',params:{nid:2}}">About2</RouterLink>
            </nav>
        </div>
    </header>
    <RouterView/>
</template>

<script setup>
</script>

<style scoped></style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

/src/router/index.js

import {createRouter, createWebHistory} from 'vue-router'
import HomeView from '../views/HomeView.vue'

const router = createRouter({
    history: createWebHistory(import.meta.env.BASE_URL),
    routes: [
        {
            path: '/',
            name: 'home',
            component: HomeView,
        },
        {
            path: '/about/:nid',
            name: 'about',
            component: () => import('../views/AboutView.vue'),
        },
    ],
})

export default router
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

/src/views/AboutView.vue

<template>
    <h2>About - {{ param_dict }}</h2>
</template>

<style></style>

<script setup>
import {ref} from "vue";
import {useRoute, onBeforeRouteUpdate} from "vue-router"

const route = useRoute()
const param_dict = ref(route.params)

onBeforeRouteUpdate(function (to, from) {
    // console.log(to, from)
    param_dict.value = to.params
})

</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# router组件-嵌套

关键点在于: 父路由对应的组件中定义<router-view/>, 用于显示子路由对应组件的内容.

需求: (点击父路由,会默认展示它的某个子路由)

首页按钮 http://localhost:5173
关于按钮 http://localhost:5173/about  
        > ★ 默认展示的是关于里的info按钮的内容!!写个子路由,用path: "", + component来实现.
关于里的info按钮  http://localhost:5173/about/info
关于里的blog按钮  http://localhost:5173/about/blog
1
2
3
4
5

61

在App.vue中, home、about这些一级路由都展示在下方代码的 <RouterView/> 的位置.
下方关于 关于 按钮的代码, 任选其一即可..

<template>
    <header>
        <div class="wrapper">
            <nav>
                <RouterLink to="/">首页</RouterLink>       <!-- http://localhost:5173 -->
                |
                <!--<RouterLink :to="{name:'about_'}">关于</RouterLink>-->
                <RouterLink to="/about">关于</RouterLink>  <!-- http://localhost:5173/about -->
            </nav>
        </div>
    </header>
    <RouterView/>
</template>

<script setup></script>
<style scoped></style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

假设about这个一级路由下有三个子路由..(其中一个是空子路由)
Ps: 其实about下的空子路由, 还可以 redirect: {name: "info"}, 但这种写法, url会有所不同.. 可以自我实验进行验证..
这种写法, 相当于点击 关于 按钮, http://localhost:5173/about 自动跳转到 http://localhost:5173/about/info

import {createRouter, createWebHistory} from 'vue-router'
import HomeView from '../views/HomeView.vue'

const router = createRouter({
    history: createWebHistory(import.meta.env.BASE_URL),
    routes: [
        {
            path: '/',
            name: 'home',
            component: HomeView,
        },
        {
            path: '/about',
            name: 'about',
            component: () => import('../views/AboutView.vue'),     // http://localhost:5173/about
            children: [
                {
                    path: "",
                    name: "about_",
                    component: () => import('../views/Info.vue'),
                },
                {
                    path: 'info',
                    name: 'info',
                    component: () => import('../views/Info.vue'),  // http://localhost:5173/about/info
                },
                {
                    path: 'blog',
                    name: 'blog',
                    component: () => import('../views/blog.vue'),  // http://localhost:5173/about/blog
                },
            ]
        },
    ],
})

export default router
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

那么about这个一级路由下的两个子路由info和blog展示在下方代码的<RouterView/> 的位置..

<template>
    <RouterLink :to="{name:'info'}">info</RouterLink>
    |
    <RouterLink :to="{name:'blog'}">blog</RouterLink>
    <RouterView/>
</template>

<style></style>

<script setup></script>
1
2
3
4
5
6
7
8
9
10

# 编程式导航/js代码跳转

在前面, 我们都是通过 <RouterLink> 标签实现路由的跳转..
其实, 使用RouterLink的地方我们都可以使用js代码实现路由的跳转..(这种方式就叫作编程导航)

编程式导航的应用场景: 登陆成功后跳转首页 -- 按钮触发了一个事件, 跳转到另一个路由.

# 关键语法

实现编程式导航的关键语法: (push跳转到指定路由

import {useRouter} from "vue-router"

const router = useRouter()
router.push({path:'/about/blog'}) 等同于 router.push({name: "blog"})
// 若路由配置有参数的话 动态路由参数、url的get参数
router.push({name: "blog", params: {nid: 100}, query: {page: 100}})

router.replace 与 router.push
- 使用都是一模一样的
- 当前历史记录 = [A,B,C,D]
  push > [A,B,C,D,blog]  --  新增
  replace > [A,B,C,blog] --  覆盖最新的
1
2
3
4
5
6
7
8
9
10
11
12

我们将上面 router组件-嵌套 小节示例中 的 blog路由相关的 RouterLink标签 给注释掉, 改用编程式导航实现相同的效果..
更改的代码如下:

<template>
    <RouterLink :to="{name:'info'}">info</RouterLink>
    |
    <!--<RouterLink :to="{name:'blog'}">blog</RouterLink>-->
    <span @click="doClick">blog</span>  <!--我试了 a、span、button标签都可以-->
    <RouterView/>
</template>

<style></style>

<script setup>
import {useRouter} from "vue-router";

const router = useRouter()

function doClick() {
    router.push({name: 'blog'})
}
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

下面我们通过登陆跳转来好好体会下编程式导航..
登陆跳转是否含顶部, 本质就在于 /src/router/index.js 里的路由嵌套不一样

# 登陆跳转(含顶部)

应用场景: 博客、公司官网、xx在线平台 不登陆即可看到一些内容 -- 首页、关于、登陆 都在导航条上面..

需求: 在未登录时, 就可以看 首页、关于 的内容.. 登陆成功后 跳转首页..

62

/src/App.vue

<template>
    <header>
        <div class="wrapper">
            <nav>
                <RouterLink to="/">首页</RouterLink>
                |
                <RouterLink to="/about">关于</RouterLink>
                |
                <RouterLink to="/login">登陆</RouterLink>
            </nav>
        </div>
    </header>
    <RouterView/>
</template>

<script setup></script>

<style scoped></style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

/src/router/index.js

import {createRouter, createWebHistory} from 'vue-router'
import HomeView from '../views/HomeView.vue'

const router = createRouter({
    history: createWebHistory(import.meta.env.BASE_URL),
    routes: [
        {
            path: '/login',
            name: 'login',
            component: () => import('../views/LoginView.vue'),
        },
        {
            path: '/',
            name: 'home',
            component: HomeView,
        },
        {
            path: '/about',
            name: 'about',
            component: () => import('../views/AboutView.vue'),
        },
    ],
})

export default router
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

/src/views/LoginView.vue

<template>
    <div>
        <input type="text" placeholder="用户名" v-model="username">
        <input type="text" placeholder="密码" v-model="pwd">
        <input type="button" @click="doLogin" value="登陆">
    </div>
</template>

<script setup>
import {ref} from "vue";
import {useRouter} from "vue-router";

const router = useRouter()
const username = ref("")
const pwd = ref("")

function doLogin() {
    // 1.获取数据 Todo-携带数据向后端发送请求进行验证
    console.log(username.value, pwd.value)
    // 2.假设登陆成功,本地存储用户信息(登录凭证 应该用后端返回的token,此处简单化用的用户名)
    //   其实token 不仅本地缓存持久化 + 我们还会将其放到 vuex、pinia 中,因为是存在内存中,读取更快
    localStorage.setItem("name", username.value)
    // 3.跳转到首页
    router.push({name: "home"})
}
</script>


<style scoped></style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

# 登陆跳转(不含顶部)

应用场景: 某平台的后台管理.. (没有登陆,就不能展现导航菜单) -- 登陆不在导航条上.. ★ 将后台跟登陆的页面区分开.

需求: 登陆页面是单独的, 登陆成功后, 跳转后台页面.

63

简单分析下:

vue是单应用/单页面开发, 可以简单理解就是App.vue组件!! 项目不管访问什么地址一直都在展示App.vue!!
既然展示的都是App.vue,那么为啥不同地址呈现的App.vue不一样呢?是因为路由的配置.
根据路由index.js的配置,配置中一级路由对应的组件通通都会渲染到 App.vue的<router-view>处!!
若一级路由有children属性,那么该属性下配置的二级路由都会渲染到当前一级路由对应组件的<router-view>处!!

App.vue组件里啥也没有,就剩下一个<router-view>!! 
意味着,每次往App.vue的<router-view>加载的组件就是该组件原本的内容.
所以,该登陆跳转的页面就不含顶部啦!!!
1
2
3
4
5
6
7
8

不含顶部和含顶部相比,/src/views/LoginView.vue 的内容不用改.
需要新增一个一级路由admin,将原本写在App.vue中的写在了该组件里 + 改一下App.vue和路由配置文件index.js.

/src/App.vue

<template>
    <RouterView/>
</template>

<script setup></script>
<style scoped></style>
1
2
3
4
5
6

/src/router/index.js

import {createRouter, createWebHistory} from 'vue-router'
import HomeView from '../views/HomeView.vue'

const router = createRouter({
    history: createWebHistory(import.meta.env.BASE_URL),
    routes: [
        {
            path: '/login',
            name: 'login',
            component: () => import('../views/LoginView.vue'),
        },
        {
            path: '/',
            name: 'admin',
            component: () => import('../views/AdminView.vue'),
            children: [
                {
                    path: '',
                    name: 'home',
                    component: HomeView,
                },
                {
                    path: '/about',
                    name: 'about',
                    component: () => import('../views/AboutView.vue'),
                },
            ]
        },
    ],
})

export default router
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

/src/views/AdminView.vue

<template>
    <header>
        <div class="wrapper">
            <nav>
                <RouterLink to="/">首页</RouterLink>
                |
                <RouterLink to="/about">关于</RouterLink>
            </nav>
        </div>
    </header>
    <RouterView/>
</template>

<script setup>
</script>

<style scoped></style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# 导航守卫

有些路由需要登陆后才能访问, 此时就需要导航守卫! - 就是Django中的中间件,其他框架里的拦截器. - 拦截请求进行处理

vue-router作拦截, 本地缓存中有token才表明已登陆, 否则登陆未成功就跳转登陆页面..
提一嘴, 后续还要实现axios拦截器, 携带token进行访问, 会验证token是否有效.. (待学习)

# 浏览器的本地存储

- cookie, 可设置有效期

- localStorage 可长期保存
  localStorage.setItem(key,value)
  localStorage.getItem(key)
  localStorage.removeItem(key)
  localStorage.clear()

- sessionStorage 一般不会用它,有个弊端:关闭浏览器,自动消失
  sessionStorage.setItem(key,value)
  sessionStorage.getItem(key)
  sessionStorage.removeItem(key)
  sessionStorage.clear()
  
> localStorage.clear()
  undefined
> localStorage.setItem('name','dc')
  undefined
> localStorage.getItem('name')
  'dc'
> localStorage.getItem('xxx')
  null
  
> if(null){}else{console.log(123)}
  123
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

# 登陆才能访问+登出

64

需求: 不登陆就没法访问 首页和关于; 登陆后跳转首页; 退出登陆后,清空本地缓存,跳转登陆页面. 在登陆跳转(不含顶部) 这个示例上, 进行一点代码的修改, 即可实现该需求, 完整代码如下:

/src/App.vue

<template>
    <RouterView/>
</template>

<script setup></script>
<style scoped></style>
1
2
3
4
5
6

/src/router/index.js

import {createRouter, createWebHistory} from 'vue-router'
import HomeView from '../views/HomeView.vue'

const router = createRouter({
    history: createWebHistory(import.meta.env.BASE_URL),
    routes: [
        {
            path: '/login',
            name: 'login',
            component: () => import('../views/LoginView.vue'),
        },
        {
            path: '/',
            name: 'admin',
            component: () => import('../views/AdminView.vue'),
            children: [
                {
                    path: '',
                    name: 'home',
                    component: HomeView,
                },
                {
                    path: '/about',
                    name: 'about',
                    component: () => import('../views/AboutView.vue'),
                },
            ]
        },
    ],
})


// ★ 导航守卫!!
router.beforeEach((to, from, next) => {
    /*
    * to   即将访问的的路由对象
    * from 当前要离开的路由对象
    * next()      继续向后执行,去to的页面
    * next(false) 不跳转,还在当前页面
    * next("/xxx") next({name:"xxx"}) next({path:"/xxx"}) 跳转指定的页面
    * */
    //1.白名单 eg:访问登录页面,该页面不需要登录就可以直接去查看
    if (to.name === "login" || to.name === "Index") {
        next()
        return
    }

    //2.检查用户登录状态(登录成功,继续往后走next(); 未登录,跳转到登录页面)
    let username = localStorage.getItem("name")
    if (username) {
        next()
    } else{
        next({name: "login"})
    }
})

export default router
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57

/src/views/LoginView.vue

<template>
    <div>
        <input type="text" placeholder="用户名" v-model="username">
        <input type="text" placeholder="密码" v-model="pwd">
        <input type="button" @click="doLogin" value="登陆">
    </div>
</template>

<script setup>
import {ref} from "vue";
import {useRouter} from "vue-router";

const router = useRouter()
const username = ref("")
const pwd = ref("")

function doLogin() {
    // 1.获取数据 Todo-携带数据向后端发送请求进行验证
    console.log(username.value, pwd.value)
    localStorage.setItem("name", username.value)  // 应存后端返回的token,此处为了方便,存的是name
    // 3.跳转到首页
    router.push({name: "home"})
}
</script>


<style scoped></style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

/src/views/AdminView.vue

<template>
    <RouterLink to="/">首页</RouterLink>
    |
    <RouterLink to="/about">关于</RouterLink>
    --
    <span @click="doLogout" style="cursor: pointer;">退出</span>
    <RouterView/>
</template>

<script setup>
import {useRouter} from "vue-router";

let router = useRouter()
function doLogout() {
    // 清除localStorage并跳转登陆页.
    localStorage.clear()
    router.push({name: 'login'})
}
</script>

<style scoped></style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

创建vite项目
pinia组件

← 创建vite项目 pinia组件→

最近更新
01
deepseek本地部署+知识库
02-17
02
实操-微信小程序
02-14
03
教学-cursor深度探讨
02-13
更多文章>
Theme by Vdoing | Copyright © 2023-2025 DC | One Piece
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式