欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 教育 > 培训 > vue-有关于TS与路由器

vue-有关于TS与路由器

2025/2/27 16:46:06 来源:https://blog.csdn.net/2401_87202881/article/details/145395075  浏览:    关键词:vue-有关于TS与路由器
title: vue(TS)+路由器
date: 2025-01-28 12:00:00
tags:- 前端
categories:- 前端

Vue3-第二部分

这里是代码中出现TS的,后面是路由器

现在先上代码,步步分析。

eg1-props的使用

步步分析代码(先理解,再实践)

框架

image-20250128003823892

先分析main.ts

常规出现,就是创建与引入

// 引入createApp用于创建应用
import {createApp} from 'vue'
// 引入App根组件
import App from './App.vue'
​
createApp(App).mount('#app')

分析组件内的person.vue

模版部分
<template><div class="person"><ul><li v-for="p in list" :key="p.id">{ {p.name} } -- { {p.age} }</li></ul></div>
</template>

功能说明:

1. 渲染数据列表

• list 是通过 props 传递给 Person 组件的。

• 使用 v-for 循环遍历 list 数组,动态生成 <li> 列表项。

• 每个 li 显示每个对象的 name 和 age。

2. 绑定唯一的 key:

• 使用 :key="p.id" 为每个列表项绑定唯一的 key,提高渲染效率。

脚本部分
<script lang="ts" setup name="Person">import { withDefaults } from 'vue'import { type Persons } from '@/types'
​// 接收list + 限制类型 + 限制必要性 + 指定默认值withDefaults(defineProps<{list?: Persons}>(), {list: () => [{ id: 'ausydgyu01', name: '康师傅·王麻子·特仑苏', age: 19 }]})
</script>

上面的import是什么?

一般是导入工具与类型

• withDefaults:

• 用于为 defineProps 定义的 props 设置默认值。它接收两个参数:

• defineProps 的返回值(包含 props 的类型约束)。

• 一个对象,用来指定每个 prop 的默认值。

• Persons:

• 从 @/types 导入的类型别名,表示一个由多个 person 对象组成的数组,符合以下结构:

也就是如果我要用到 prop的时候用

知识点解析:

1. defineProps:

• Vue 3 提供的 API,用于定义组件接收的 props。

• defineProps<{list?: Persons}>():

• 定义了一个可选的 list 属性,类型为 Persons(数组,每个元素是一个符合 PersonInter 的对象)。

2. withDefaults:

• 用来为可选 props(如 list?)设置默认值。

• 默认值为:

[{ id: 'ausydgyu01', name: '康师傅·王麻子·特仑苏', age: 19 }]

再分析index.ts

// 定义一个接口,用于限制person对象的具体属性
export interface PersonInter {id: string,name: string,age: number,
}
​
// 一个自定义类型
export type Persons = PersonInter[]

1. 接口 PersonInter:

• 定义了 person 对象的结构,强制要求每个对象包含以下属性:

• id:字符串,唯一标识。

• name:字符串,人员姓名。

• age:数字,人员年龄。

2. 类型别名 Persons:

• 定义了一个数组类型,数组的每个元素都必须符合 PersonInter 接口。

App.vue解析

<template><!-- 务必看懂下面这一行代码 --><!-- <h2 a="1+1" :b="1+1" c="x" :d="x" ref="qwe">测试</h2> --><Person a="哈哈" />
</template>

静态属性:a = "1 + 1"是一个普通的字符串,直接作为属性值

动态属性:b = "1 + 1"是一个动态表达式,结果会被计算后作为属性值

ref="qwe",绑定DOM引用,可以在JavaScript中通过ref操作这个DOM元素

2. 子组件 <Person /> 的使用:

• <Person /> 是导入的子组件,代表 person.vue 文件。

• a="哈哈" 是传递给 <Person /> 的一个普通属性。

脚本部分

<script lang="ts" setup name="App">import Person from './components/Person.vue'import { reactive } from 'vue'import { type Persons } from '@/types'
​let x = 9
​let personList = reactive<Persons>([{ id: 'asudfysafd01', name: '张三', age: 18 },{ id: 'asudfysafd02', name: '李四', age: 20 },{ id: 'asudfysaf)d03', name: '王五', age: 22 }])
</script>

1. 引入 Person 组件:

• import Person from './components/Person.vue' 引入 person.vue,使得 <Person /能够在模板中使用。

  1. 定yi响应式数据:

  2. reactive 的作用:

    • 使得 personList 成为响应式数据。当 personList 或其内部的对象属性发生变化时,Vue 会自动更新视图。

整体逻辑总结

Index.ts 定义了personInter接口和Person类型,用来约束person数据结构

Person.vue 接收list作为props,通过withDefaults为list设置默认值

渲染list数据。动态生成列表

App.vue

定义一个响应式数据personalist,并可以通过props传递给pweson.vue

image-20250128010109534

vue2生命周期

<template><div class="person"><h2>当前求和为:{ { sum } }</h2><button @click="add">点我sum+1</button></div>
</template>

功能说明:

1. 数据绑定:

• { { sum } } 用来动态展示变量 sum 的值。

• 每次点击按钮,sum 的值增加 1。

2. 事件绑定:

• @click="add":绑定按钮点击事件,触发 add 方法,更新 sum 的值。

<script lang="ts" setup name="Person">import { ref, onBeforeMount, onMounted, onBeforeUpdate, onUpdated, onBeforeUnmount, onUnmounted } from 'vue'// 数据let sum = ref(0)// 方法function add() {sum.value += 1}// 创建console.log('创建')// 挂载前onBeforeMount(() => {// console.log('挂载前')})// 挂载完毕onMounted(() => {console.log('子---挂载完毕')})// 更新前onBeforeUpdate(() => {// console.log('更新前')})// 更新完毕onUpdated(() => {// console.log('更新完毕')})// 卸载前onBeforeUnmount(() => {// console.log('卸载前')})// 卸载完毕onUnmounted(() => {// console.log('卸载完毕')})
</script>

image-20250128011042599

app.vue

<template><Person v-if="isShow" />
</template>

1. <Person v-if="isShow" /

• 条件渲染子组件 Person。

• 当 isShow 为 true 时,<Person / 会被挂载。

• 当 isShow 为 false 时,<Person /会被卸载。

脚本部分

<script lang="ts" setup name="App">import Person from './components/Person.vue'import { ref, onMounted } from 'vue'let isShow = ref(true)// 挂载完毕onMounted(() => {console.log('父---挂载完毕')})
</script>

功能解析:

1. 引入子组件:

• Person 是一个子组件,来自 ./components/Person.vue。

2. 响应式数据:

• let isShow = ref(true):定义了一个响应式布尔值 isShow,控制 <Person /> 的显示和隐藏。

3. 生命周期钩子:

• onMounted:在 App 组件挂载到 DOM 后执行。这里输出 父---挂载完毕,用于标记父组件挂载完成。

运行流程

  1. 父组件挂载(App

• isShow 默认为 true。

• <Person / 被挂载到 DOM 中。

• 控制台输出:

父---挂载完毕
创建
子---挂载完毕

. 子组件更新(Person

• 点击按钮时,sum.value 增加 1,触发子组件更新。

• 在更新阶段,执行以下生命周期钩子:

• onBeforeUpdate

• onUpdated

3. 子组件卸载(Person

• 如果将 isShow 设置为 false(例如通过交互),<Person /> 会被卸载。

• 卸载阶段执行:

• onBeforeUnmount

• onUnmounted

5. 总结

person.vue 的功能

• 通过按钮点击实现 sum 的动态更新。

• 使用 Vue 3 的生命周期钩子监控组件的各个阶段,包括挂载、更新、卸载。

app.vue 的功能

• 使用 v-if 控制子组件 Person 的挂载和卸载。

• 父组件负责管理子组件的存在与否,同时通过生命周期钩子记录父组件的挂载阶段。

生命周期运行示意图

1. 父组件挂载:

• onMounted -> 输出:父---挂载完毕

2. 子组件挂载:

• 创建

• onBeforeMount(未输出)

• onMounted -> 输出:子---挂载完毕

3. 子组件更新:

• onBeforeUpdate

• onUpdated

4. 子组件卸载:

• onBeforeUnmount

• onUnmounted

image-20250128012228275

对应页面

Eg2-hook自定义

<template><div class="person"><h2>当前求和为:{ { sum } },放大10倍后:{ { bigSum } }</h2><button @click="add">点我sum+1</button><hr><img v-for="(dog,index) in dogList" :src="dog" :key="index"><br><button @click="getDog">再来一只小狗</button></div>
</template><script lang="ts" setup name="Person">import useSum from '@/hooks/useSum'import useDog from '@/hooks/useDog'const {sum,add,bigSum} = useSum()const {dogList,getDog} = useDog()
</script><style scoped>.person {background-color: skyblue;box-shadow: 0 0 10px;border-radius: 10px;padding: 20px;}button {margin: 0 5px;}li {font-size: 20px;}img {height: 100px;margin-right: 10px;}
</style>

这个是person.vue

在模版部分,

• 图片渲染:

• 使用 v-for 循环 dogList,通过动态绑定 src 和 key 属性渲染小狗图片。

在脚本部分

• 引入逻辑模块:

• 从 useSum.ts 中引入了 sum、add 和 bigSum,负责数值的处理。

• 从 useDog.ts 中引入了 dogList 和 getDog,负责图片列表的管理和 API 请求。

• 使用组合式 API:

• 通过解构的方式,将逻辑解耦到独立的模块中,提高代码的可复用性。

在useDog.ts模块

import { reactive, onMounted } from 'vue'
import axios from 'axios'export default function () {// 数据let dogList = reactive(['https://images.dog.ceo/breeds/pembroke/n02113023_4373.jpg'])// 方法async function getDog() {try {let result = await axios.get('https://dog.ceo/api/breed/pembroke/images/random')dogList.push(result.data.message)} catch (error) {alert(error)}}// 钩子onMounted(() => {getDog()})// 向外部提供东西return { dogList, getDog }
}

功能分析

1. 响应式数据

• 使用 reactive 定义了图片列表 dogList,默认包含一张图片。

2. API 请求方法

• getDog 方法使用 Axios 请求 https://dog.ceo 提供的小狗图片 API。

• 将获取的图片 URL 推入 dogList 中。

• 通过 try-catch 捕获请求错误。

3. 生命周期钩子

• 在组件挂载时 (onMounted) 自动调用 getDog,预加载一张小狗图片。

关键点

• 合理使用 reactive 管理数组的响应式更新。

• 在组件加载时预先获取数据,优化用户体验。

在这里面有一个地方发送异步请求

zlet result = await axios.get('https://dog.ceo/api/breed/pembroke/images/random')

axios.get():

• 使用 axios 发起一个 HTTP GET 请求。

• 请求地址是 https://dog.ceo/api/breed/pembroke/images/random,这是一个提供随机小狗图片的 API。

• 返回的数据是一个包含 message 属性的 JSON 对象

await:

• await 暂停代码的执行,直到请求完成并返回结果。

• 返回值存储在 result 变量中,具体数据保存在 result.data 中。

在useSum.ts模块

import { ref, onMounted, computed } from 'vue'export default function () {// 数据let sum = ref(0)let bigSum = computed(() => {return sum.value * 10})// 方法function add() {sum.value += 1}// 钩子onMounted(() => {add()})// 给外部提供东西return { sum, add, bigSum }
}

功能分析

1. 响应式数据

• 使用 ref 定义了单一响应式数据 sum。

• 使用 computed 定义了计算属性 bigSum,动态计算 sum 的 10 倍值。

2. 方法

• add 方法使 sum 增加 1。

3. 生命周期钩子

• 在 onMounted 中调用 add,在组件加载时使 sum 初始值为 1。

路由

在 Vue 3 中,路由管理通常通过 Vue Router 实现。路由的主要功能是实现页面的导航和组件的动态渲染。以下是关于路由的核心概念和代码实现的详细说明。

1. 什么是路由?

路由是一种通过 URL 映射组件或视图的方式。它允许用户在单页应用(SPA)中导航,而无需重新加载整个页面。

例如:

• /home 映射到 Home 组件。

• /about 映射到 About 组件。

image-20250128081820700

页面组件

<template><div class="home"><img src="http://www.atguigu.com/images/index_new/logo.png" alt=""></div>
</template>

功能:展示一个居中的图片。

样式:通过 flex 布局将内容水平和垂直居中。

用途:作为首页内容。

<script setup lang="ts" name="Home">
</script>

作用

• 表示该组件使用 Vue 3 的 <script setup> 语法。

• lang="ts" 表示代码使用 TypeScript,增加类型安全。

• name="Home" 给组件命名为 Home,方便调试和递归调用。

样式部分

<style scoped>.home {display: flex;justify-content: center;align-items: center;height: 100%;}
</style>

作用

• 定义组件的样式。

• scoped 表示样式只作用于当前组件,不影响其他组件。

细节解析

• display: flex;:

• 使用 Flex 布局,使子元素容易居中对齐。

• justify-content: center;:

• 子元素水平居中。

• align-items: center;:

• 子元素垂直居中。

• height: 100%;:

• 根容器的高度设置为父级容器的 100%。

About.vue

<template><div class="about"><h2>大家好,欢迎来到尚硅谷直播间</h2></div>
</template><script setup lang="ts" name="About"></script><style scoped>
.about {display: flex;justify-content: center;align-items: center;height: 100%;color: rgb(85, 84, 84);font-size: 18px;
}
</style>

News.vue

<template><div class="news"><ul><li><a href="#">新闻001</a></li><li><a href="#">新闻002</a></li><li><a href="#">新闻003</a></li><li><a href="#">新闻004</a></li></ul></div>
</template><script setup lang="ts" name="News"></script><style scoped>
/* 新闻 */
.news {padding: 0 20px;display: flex;justify-content: space-between;height: 100%;
}
.news ul {margin-top: 30px;list-style: none;padding-left: 10px;
}
.news li>a {font-size: 18px;line-height: 40px;text-decoration: none;color: #64967E;text-shadow: 0 0 1px rgb(0, 84, 0);
}
</style>

路由配置

// 创建一个路由器,并暴露出去// 第一步:引入createRouter
import {createRouter,createWebHistory} from 'vue-router'
// 引入一个一个可能要呈现组件
import Home from '@/components/Home.vue'
import News from '@/components/News.vue'
import About from '@/components/About.vue'// 第二步:创建路由器
const router = createRouter({history:createWebHistory(), //路由器的工作模式(稍后讲解) routes:[ //一个一个的路由规则{path:'/home',component:Home},{path:'/news',component:News},{path:'/about',component:About},]
})// 暴露出去router
export default router

createRouter

• 创建一个路由实例。

createWebHistory

• 使用 HTML5 的历史记录模式。

routes

• 定义路由规则,每条规则对应一个路径和组件。

应用入口

// 引入createApp用于创建应用
import {createApp} from 'vue'
// 引入App根组件
import App from './App.vue'
// 引入路由器
import router from './router'// 创建一个应用
const app = createApp(App)
// 使用路由器
app.use(router)
// 挂载整个应用到app容器中
app.mount('#app')

App.vue

模版部分

<template><div class="app"><h2 class="title">Vue路由测试</h2><!-- 导航区 --><div class="navigate"><RouterLink to="/home" active-class="xiaozhupeiqi">首页</RouterLink><RouterLink to="/news" active-class="xiaozhupeiqi">新闻</RouterLink><RouterLink to="/about" active-class="xiaozhupeiqi">关于</RouterLink></div><!-- 展示区 --><div class="main-content"><RouterView></RouterView></div></div>
</template>

<RouterLink:

• Vue Router 提供的导航组件,类似于 HTML 的 <a> 标签。

• to="/home":指定点击该链接时跳转的路由路径。

• active-class="xiaozhupeiqi":定义激活时的样式类名,当链接的路由匹配当前路径时会自动应用。

• 导航链接功能:

• 首页:跳转到 /home 路由。

• 新闻:跳转到 /news 路由。

• 关于:跳转到 /about 路由。

在展示区

<div class="main-content"><RouterView></RouterView>
</div>

• <RouterView :

• Vue Router 提供的内置组件,用于渲染当前路由匹配的组件。

• 根据用户点击的导航链接,<RouterView会动态切换为对应的组件内容,例如 Home.vue、News.vue 或 About.vue。

脚本部分

<script lang="ts" setup name="App">import { RouterView, RouterLink } from 'vue-router'
</script>

逐行解析

(1) lang="ts"

• 表示当前脚本部分使用 TypeScript,增强类型安全。

• 允许对变量、函数等进行类型声明。

(2) setup

• 使用 Vue 3 的组合式 API 的语法糖。

• 在 <script setup中定义的变量和方法,可以直接在模板中使用,无需显式返回。

(3) name="App"

• 为当前组件指定名称为 App。

• 在开发者工具(如 Vue DevTools)中调试时,可以看到组件名称为 App,便于区分。

(4) 引入 Vue Router 的组件

import { RouterView, RouterLink } from 'vue-router'

• RouterLink:用于定义路由导航链接。

• RouterView:用于动态渲染路由匹配的组件。

样式部分

.title {text-align: center;word-spacing: 5px;margin: 30px 0;height: 70px;line-height: 70px;background-image: linear-gradient(45deg, gray, white);border-radius: 10px;box-shadow: 0 0 2px;font-size: 30px;
}
.navigate {display: flex;justify-content: space-around;margin: 0 100px;
}
.navigate a {display: block;text-align: center;width: 90px;height: 40px;line-height: 40px;border-radius: 10px;background-color: gray;text-decoration: none;color: white;font-size: 18px;letter-spacing: 5px;
}

image-20250128085015970

image-20250128085239563

image-20250128085251179

xiaozhupeiqi 激活后呈现的

image-20250128085312669

这个就是超链接<a的时候,未点击前呈现的

视频中没有讲这一部分,少了一个知识点的讲解就是routeLink->转换为<a标签

image-20250128085843036

image-20250128090039568

image-20250128090244976

Query 参数-路由

Header.ts

<template><h2 class="title">Vue路由测试</h2>
</template><script setup lang="ts" name="Header"></script><style scoped>.title {text-align: center;word-spacing: 5px;margin: 30px 0;height: 70px;line-height: 70px;background-image: linear-gradient(45deg, gray, white);border-radius: 10px;box-shadow: 0 0 2px;font-size: 30px;}
</style>

About.ts

<template><div class="about"><h2>大家好,欢迎来到尚硅谷直播间</h2></div>
</template><script setup lang="ts" name="About">import {onMounted,onUnmounted} from 'vue'onMounted(()=>{console.log('About组件挂载了')})onUnmounted(()=>{console.log('About组件卸载了')})
</script><style scoped>
.about {display: flex;justify-content: center;align-items: center;height: 100%;color: rgb(85, 84, 84);font-size: 18px;
}
</style>

image-20250128092207216

Detail.ts

<template><ul class="news-list"><li>编号:{ { query.id } }</li><li>标题:{ { query.title } }</li><li>内容:{ { query.content } }</li></ul>
</template><script setup lang="ts" name="About">import {toRefs} from 'vue'import {useRoute} from 'vue-router'let route = useRoute()let {query} = toRefs(route)</script><style scoped>.news-list {list-style: none;padding-left: 20px;}.news-list>li {line-height: 30px;}
</style>

脚本部分

解析

(1) useRoute

定义

• useRoute 是 Vue Router 提供的组合式 API,用于获取当前路由对象。

作用

• 返回当前激活的路由信息,包括路径、参数、查询字符串等。

返回值

route 是一个响应式对象,包含当前路由的所有信息,例如:

{path: "/news",query: {id: "123",title: "Vue Router",content: "这是一个简单的示例"},params: { ... },...
}

(2) toRefs

定义

• toRefs 是 Vue 的组合式 API,用于将响应式对象的属性转换为独立的响应式引用。

作用

将 route.query 转换为响应式引用,使得在模板中访问 query 的属性时,能够保持响应式更新。

代码作用

let { query } = toRefs(route)

(3) 数据流程

• useRoute() 获取当前路由信息。

• 通过 toRefs(route) 解构出 query,用于动态绑定数据。

Params

image-20250128094158019

image-20250128094312633

<template><div class="news"><!-- 导航区 --><ul><li v-for="news in newsList" :key="news.id"><!-- 第一种写法 --><!-- <RouterLink :to="`/news/detail/${news.id}/${news.title}/${news.content}`">{ {news.title} }</RouterLink> --><!-- 第二种写法 --><RouterLink :to="{name:'xiang',params:{id:news.id,title:news.title,content:news.content}}">{ {news.title} }</RouterLink></li></ul><!-- 展示区 --><div class="news-content"><RouterView></RouterView></div></div>
</template><script setup lang="ts" name="News">import {reactive} from 'vue'import {RouterView,RouterLink} from 'vue-router'const newsList = reactive([{id:'asfdtrfay01',title:'很好的抗癌食物',content:'西蓝花'},{id:'asfdtrfay02',title:'如何一夜暴富',content:'学IT'},{id:'asfdtrfay03',title:'震惊,万万没想到',content:'明天是周一'},{id:'asfdtrfay04',title:'好消息!好消息!',content:'快过年了'}])</script><style scoped>
/* 新闻 */
.news {padding: 0 20px;display: flex;justify-content: space-between;height: 100%;
}
.news ul {margin-top: 30px;/* list-style: none; */padding-left: 10px;
}
.news li::marker {color: #64967E;
}
.news li>a {font-size: 18px;line-height: 40px;text-decoration: none;color: #64967E;text-shadow: 0 0 1px rgb(0, 84, 0);
}
.news-content {width: 70%;height: 90%;border: 1px solid;margin-top: 20px;border-radius: 10px;
}
</style>

这个是new.vue

image-20250128095252643

image-20250128095646602

Pinia

Count.vue

模版部分

<template><div class="count"><h2>当前求和为:{ { sum } }</h2><select v-model.number="n"><option value="1">1</option><option value="2">2</option><option value="3">3</option></select><button @click="add">加</button><button @click="minus">减</button></div>
</template>

• 使用 { { sum } } 动态绑定 sum 的值,显示当前的求和结果。

2. 选择操作数

• 使用 <select 元素,让用户选择一个数字(1、2 或 3)。

• 通过 v-model.number="n" 双向绑定选中的值到变量 n,并将其转换为数值。

  1. 加减操作

• 点击“加”按钮时调用 add 方法。

• 点击“减”按钮时调用 minus 方法。

脚本部分

<script setup lang="ts" name="Count">import { ref } from "vue";// 数据let sum = ref(1) // 当前求和let n = ref(1) // 用户选择的数字// 方法function add(){sum.value += n.value}function minus(){sum.value -= n.value}
</script>

1. ref 定义响应式数据

• sum:当前求和,初始值为 1。

• n:用户选择的数字,初始值为 1。

• 响应式数据会自动更新绑定到模板的内容。

2. 方法功能

• add:将选中的数字 n.value 加到 sum.value 上。

• minus:从 sum.value 中减去 n.value。

<script setup lang="ts" name="LoveTalk">import { reactive } from 'vue'import axios from "axios";import { nanoid } from 'nanoid'// 数据let talkList = reactive([{id:'ftrfasdf01',title:'今天你有点怪,哪里怪?怪好看的!'},{id:'ftrfasdf02',title:'草莓、蓝莓、蔓越莓,今天想我了没?'},{id:'ftrfasdf03',title:'心里给你留了一块地,我的死心塌地'}])// 方法async function getLoveTalk(){// 发请求,下面这行的写法是:连续解构赋值+重命名let {data:{content:title} } = await axios.get('https://api.uomg.com/api/rand.qinghua?format=json')// 把请求回来的字符串,包装成一个对象let obj = {id:nanoid(),title}// 放到数组中talkList.unshift(obj)}
</script>

在app.vue里面写

<template><Count/><br><LoveTalk/>
</template><script setup lang="ts" name="App">import Count from './components/Count.vue'import LoveTalk from './components/LoveTalk.vue'
</script>
npm i pinia

image-20250128103405430

import {createApp} from 'vue'
import App from './App.vue'
// 第一步:引入pinia
import {createPinia} from 'pinia'const app = createApp(App)
// 第二步:创建pinia
const pinia = createPinia()
// 第三步:安装pinia
app.use(pinia)
app.mount('#app')

image-20250128103603995

小菠萝出来啦!!!

存储+读取数据

创建一个store文件夹

Count.ts

import {defineStore} from 'pinia'export const useCountStore = defineStore('count',{// 真正存储数据的地方state(){return {sum:6}}
})

Lovetalk.ts

import {defineStore} from 'pinia'export const useTalkStore = defineStore('talk',{// 真正存储数据的地方state(){return {talkList:[{id:'ftrfasdf01',title:'今天你有点怪,哪里怪?怪好看的!'},{id:'ftrfasdf02',title:'草莓、蓝莓、蔓越莓,今天想我了没?'},{id:'ftrfasdf03',title:'心里给你留了一块地,我的死心塌地'}]}}
})

修改数据

import {defineStore} from 'pinia'export const useCountStore = defineStore('count',{// actions里面放置的是一个一个的方法,用于响应组件中的“动作”actions:{increment(value){console.log('increment被调用了',value)if( this.sum < 10){// 修改数据(this是当前的store)this.sum += value}}},// 真正存储数据的地方state(){return {sum:6,school:'atguigu',address:'宏福科技园'}}
})
import {defineStore} from 'pinia'
import axios from 'axios'
import {nanoid} from 'nanoid'export const useTalkStore = defineStore('talk',{actions:{async getATalk(){// 发请求,下面这行的写法是:连续解构赋值+重命名let {data:{content:title} } = await axios.get('https://api.uomg.com/api/rand.qinghua?format=json')// 把请求回来的字符串,包装成一个对象let obj = {id:nanoid(),title}// 放到数组中this.talkList.unshift(obj)}},// 真正存储数据的地方state(){return {talkList:[{id:'ftrfasdf01',title:'今天你有点怪,哪里怪?怪好看的!'},{id:'ftrfasdf02',title:'草莓、蓝莓、蔓越莓,今天想我了没?'},{id:'ftrfasdf03',title:'心里给你留了一块地,我的死心塌地'}]}}
})

现在展开解释

整体功能

这段代码通过 Pinia 定义了一个 Store,用于管理一个情话列表 talkList,并提供了一个方法 getATalk 来向 API 请求新的情话并添加到 talkList 中。

1. 引入的依赖

import { defineStore } from 'pinia'
import axios from 'axios'
import { nanoid } from 'nanoid'

解析

1. defineStore:

• 从 pinia 中引入,用于定义一个新的 Store。

• Store 是状态管理的核心,用于存储和管理全局共享的状态。

2. axios:

• 用于发送 HTTP 请求。

• 这里通过 axios.get() 从 https://api.uomg.com/api/rand.qinghua 获取随机土味情话。

3. nanoid:

• 一个小型的 ID 生成工具。

• 用于为每条情话生成唯一的 ID,确保 talkList 中的每条情话都有一个独特的标识。

2. 定义 Store

export const useTalkStore = defineStore('talk', { ... })

解析

1. export const useTalkStore:

• 定义了一个 Store,命名为 useTalkStore。

• 这个名字的命名规则通常是 use 开头,以表明它是一个 Store。

2. defineStore('talk', {...}):

• 'talk' 是这个 Store 的唯一标识符,用于区分其他 Store。

• 第二个参数是 Store 的配置对象,包含 state 和 actions 等。

3. state:存储数据

state() {return {talkList: [{ id: 'ftrfasdf01', title: '今天你有点怪,哪里怪?怪好看的!' },{ id: 'ftrfasdf02', title: '草莓、蓝莓、蔓越莓,今天想我了没?' },{ id: 'ftrfasdf03', title: '心里给你留了一块地,我的死心塌地' }]}
}

解析

1. state:

• 一个函数,返回一个对象,这个对象定义了 Store 中的数据。

• 在这里,state 定义了一个情话列表 talkList。

2. talkList:

• 是一个数组,存储了情话的初始数据。

• 每条情话是一个对象,包含以下字段:

• id:情话的唯一标识符。

• title:情话的具体内容。

3. 响应式特性

• Pinia 的 state 是响应式的。

• 当 talkList 数据发生变化时,绑定到 talkList 的视图会自动更新。

4. actions:定义方法

actions: {async getATalk() {let { data: { content: title } } = await axios.get('https://api.uomg.com/api/rand.qinghua?format=json')let obj = { id: nanoid(), title }this.talkList.unshift(obj)}
}

解析

1. actions:

• 定义了 Store 中的方法,通常用于处理复杂逻辑或修改状态。

• getATalk 是一个异步方法,用于从 API 获取新的情话并更新 talkList。

2. getATalk 的工作流程

发送请求

let { data: { content: title } } = await axios.get('https://api.uomg.com/api/rand.qinghua?format=json')

• 使用 axios.get() 发送请求,从 API 获取情话。

• 解构赋值提取 content 字段,并将其重命名为 title。

创建新对象

let obj = { id: nanoid(), title }

• 使用 nanoid() 生成一个唯一的 ID。

• 创建一个包含 id 和 title 的新情话对象。

更新 talkList:

this.talkList.unshift(obj)

• 使用 unshift 方法,将新情话添加到 talkList 的开头。

• 由于 talkList 是响应式的,更新数据后,绑定到 talkList 的 UI 会自动更新。


image-20250128104601061

1. storeToRefs 的使用

storeToRefs 是 Pinia 提供的一个工具函数,主要用于从 Store 中提取状态(state)和 Getter 的响应式引用,确保解构后不会丢失响应性。

import { storeToRefs } from 'pinia'const store = useSomeStore()
const { stateProp, getterProp } = storeToRefs(store)

作用

• 将 state 和 getter 转换为响应式 ref。

• 解构 Store 中的属性时,防止响应性丢失。

2. getters 的使用

Pinia 的 getters 是类似于 Vuex 中的计算属性,用于对 state 的值进行派生计算。

  state: () => ({talkList: [{ id: '1', title: '情话一' },{ id: '2', title: '情话二' }]}),getters: {talkCount: (state) => state.talkList.length // 返回情话总数}
})
import { useTalkStore } from '@/stores/talkStore'const talkStore = useTalkStore()// 直接访问 getter
console.log(talkStore.talkCount) // 输出情话总数

3. $subscribe 的使用

$subscribe 是 Pinia 提供的一个方法,用于监听 Store 中 state 和 action 的变化。

语法

store.$subscribe((mutation, state) => {console.log(mutation) // 包含 type 和 payloadconsole.log(state)    // 当前状态
})

4. store 组合式写法

Pinia 支持组合式 API(Composition API)风格的 Store 定义。

export const useTalkStore = defineStore('talk', () => {const talkList = ref([{ id: '1', title: '情话一' },{ id: '2', title: '情话二' }])const talkCount = computed(() => talkList.value.length)const addTalk = (id, title) => {talkList.value.push({ id, title })}return { talkList, talkCount, addTalk }
})
import { useTalkStore } from '@/stores/talkStore'const talkStore = useTalkStore()// 调用方法和访问属性
talkStore.addTalk('3', '情话三')
console.log(talkStore.talkCount) // 输出 3

image-20250128104929967

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词