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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/67411.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mysql.sock.lock 导致mysql重启失败

背景 今天公司物业断电&#xff0c;导致机房服务器停电宕机&#xff0c;所有的服务都得重启。本着mysql实例都做了服务自启动&#xff0c;所以没有太担心影响开发的日常工作。但是今天一上班开发就找来&#xff0c;各种服务都没起来有问题&#xff0c;数据库连不上。马上登陆数…

【hot100】刷题记录(7)-除自身数组以外的乘积

题目描述&#xff1a; 给你一个整数数组 nums&#xff0c;返回 数组 answer &#xff0c;其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法&#x…

1-2 飞机大战游戏场景

前言&#xff1a; 根据前面的项目框架&#xff0c;搭建游戏的运行场景...... 1.0 框架预览 基于该框架首先实现游戏的运行场景 2.0 图片文件 创建图片文件&#xff0c;本次项目使用easyx作为图形库文件&#xff0c;在easyx中想要显示图片&#xff0c;需要有一张图片和图片的掩码…

进程通讯——类型和发展

进程常用交互方法如上

安装zsh并美化

0 Zsh 是一种功能强大的 shell&#xff0c;通常用于替代默认的 Bash shell。它为命令行提供了更多的功能&#xff0c;例如自动补全、强大的模式匹配和主题支持等。 Oh My Zsh 是用于管理 Zsh 配置的框架。 powerlevel10k是样式&#xff0c;通过p10k configure脚本可以调节自己…

GMSL 明星产品之 MAX96717

在上一篇文章中&#xff0c;我们详细介绍了车载市场中爆火的 GMSL 到底是个啥 &#xff1a; 揭开 GMSL 的面纱&#xff1a;自动驾驶背后的隐藏技术。今天我们就来详细了解下如今在摄像头侧超级火爆的加串器&#xff1a;MAX96717。 MAX96717 系列有三款产品&#xff1a; MAX967…

线段树 算法

文章目录 基础知识适用场景小结 题目概述题目详解300.最长递增子序列2407.最长递增子序列 II 基础知识 线段树和树状数组都只是一个工具来的&#xff0c;题目并不会一下子就告诉你这个题目用到线段树和树状数组&#xff0c;这个取决于你想使用的数据结构以及所要优化的方向 线…

MATLAB提供的颜色映射表colormap——伪彩色

图像处理领域的一个习惯&#xff1a;不是真实的颜色&#xff0c;一般用伪彩色。一是说明不是物体本身的颜色&#xff0c;二是彩色更容易分辨。 MATLAB陆续提供了16种颜色映射表colormap。 之前的都很丑&#xff0c;近5年新增的4种还可以。总的说来还是丑。 这是一种鸟的名字。…

20.Word:小谢-病毒知识的科普文章❗【38】

目录 题目​ NO1.2.3文档格式 NO4.5 NO6.7目录/图表目录/书目 NO8.9.10 NO11索引 NO12.13.14 每一步操作完&#xff0c;确定之后记得保存最后所有操作完记得再次删除空行 题目 NO1.2.3文档格式 样式的应用 选中应用段落段落→开始→选择→→检查→应用一个一个应用ctr…

【16届蓝桥杯寒假刷题营】第2期DAY4

【16届蓝桥杯寒假刷题营】第2期DAY4 - 蓝桥云课 问题描述 幼儿园小班的浩楠同学有一个序列 a。 他想知道有多少个整数三元组 (i,j,k) 满足 1≤i,j,k≤n 且 ai​aj​ak​。 输入格式 共2行&#xff0c;第一行一个整数 n&#xff0c;表示序列的长度。 第二行 n 个整数&#x…

MySQL查询优化(三):深度解读 MySQL客户端和服务端协议

如果需要从 MySQL 服务端获得很高的性能&#xff0c;最佳的方式就是花时间研究 MySQL 优化和执行查询的机制。一旦理解了这些&#xff0c;大部分的查询优化是有据可循的&#xff0c;从而使得整个查询优化的过程更有逻辑性。下图展示了 MySQL 执行查询的过程&#xff1a; 客户端…

Van-Nav:新年,将自己学习的项目地址统一整理搭建自己的私人导航站,供自己后续查阅使用,做技术的同学应该都有一个自己网站的梦想

嗨&#xff0c;大家好&#xff0c;我是小华同学&#xff0c;关注我们获得“最新、最全、最优质”开源项目和高效工作学习方法 Van-Nav是一个基于Vue.js开发的导航组件库&#xff0c;它提供了多种预设的样式和灵活的配置选项&#xff0c;使得开发者可以轻松地定制出符合项目需求…

VSCode+Continue实现AI辅助编程

Continue是一款功能强大的AI辅助编程插件&#xff0c;可连接多种大模型&#xff0c;支持代码设计优化、错误修正、自动补全、注释编写等功能&#xff0c;助力开发人员提高工作效率与代码质量。以下是其安装和使用方法&#xff1a; 一、安装VSCode 参见&#xff1a; vscode安…

【hot100】刷题记录(6)-轮转数组

题目描述&#xff1a; 给定一个整数数组 nums&#xff0c;将数组中的元素向右轮转 k 个位置&#xff0c;其中 k 是非负数。 示例 1: 输入: nums [1,2,3,4,5,6,7], k 3 输出: [5,6,7,1,2,3,4] 解释: 向右轮转 1 步: [7,1,2,3,4,5,6] 向右轮转 2 步: [6,7,1,2,3,4,5] 向右轮转…

FPGA 使用 CLOCK_DEDICATED_ROUTE 约束

使用 CLOCK_DEDICATED_ROUTE 约束 CLOCK_DEDICATED_ROUTE 约束通常在从一个时钟区域中的时钟缓存驱动到另一个时钟区域中的 MMCM 或 PLL 时使 用。默认情况下&#xff0c; CLOCK_DEDICATED_ROUTE 约束设置为 TRUE &#xff0c;并且缓存 /MMCM 或 PLL 对必须布局在相同…

阿里:基于路由和规划的多agent系统

&#x1f4d6;标题&#xff1a;Talk to Right Specialists: Routing and Planning in Multi-agent System for Question Answering &#x1f310;来源&#xff1a;arXiv, 2501.07813 &#x1f31f;摘要 &#x1f538;利用大型语言模型&#xff08;LLM&#xff09;&#xff0c…

【Unity3D】实现2D角色/怪物死亡消散粒子效果

核心&#xff1a;这是一个Unity粒子系统自带的一种功能&#xff0c;可将粒子生成控制在一个Texture图片网格范围内&#xff0c;并且粒子颜色会自动采样图片的像素点颜色&#xff0c;之后则是粒子编辑出消散效果。 Particle System1物体&#xff08;爆发式随机速度扩散10000个粒…

Synology 群辉NAS安装(10)安装confluence

Synology 群辉NAS安装&#xff08;10&#xff09;安装confluence 写在前面本着一朝鲜吃遍天的原则&#xff0c;我又去了这个github的作者那里翻车的第一次尝试手工创建数据库制作一个新的docker-compose of confluence 不折腾但成功启动的版本 写在前面 在装完jira之后&#x…

万字长文总结前端开发知识---JavaScriptVue3Axios

JavaScript学习目录 一、JavaScript1. 引入方式1.1 内部脚本 (Inline Script)1.2 外部脚本 (External Script) 2. 基础语法2.1 声明变量2.2 声明常量2.3 输出信息 3. 数据类型3.1 基本数据类型3.2 模板字符串 4. 函数4.1 具名函数 (Named Function)4.2 匿名函数 (Anonymous Fun…

DeepSeek R1有什么不同

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…