【前端开发学习笔记15】Vue_8
手动添加Pinia到Vue项目: 在实际开发中,Pinia配置可在项目创建时自动添加。初次学习从零开始:
1. 用Vite创建空的Vue3项目,命令为npm create vue@latest。
2. 按官方文档将pinia安装到项目中。
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
const pinia = createPinia() // 创建Pinia实例
const app = createApp(App) // 创建根实例
app.use(pinia) // pinia插件的安装配置
app.mount('#app') // 视图的挂载
Pinia的基本语法
counter.js:
import { defineStore } from 'pinia'
import { computed, ref } from 'vue'
// 定义store
// defineStore(仓库的唯一标识, () => { ... })
// 导出函数 以函数的形式调用这个仓库
export const useCounterStore = defineStore('counter', () => {
// 声明数据 原本用 state 改为了 count
const count = ref(100)
// 声明操作数据的方法 action (普通函数)
const addCount = () => count.value++
const subCount = () => count.value--
// 声明基于数据派生的计算属性 getters (computed)
const double = computed(() => count.value * 2)
// 声明数据 state -- msg
const msg = ref('hello pinia')
return {
// 必须暴露出去,才能使用
count,
double,
addCount,
subCount,
msg
}
})
Son1Com.vue:
<script setup>
import { useCounterStore } from '@/store/counter'
const counterStore = useCounterStore()
</script>
<template>
<div>
我是Son1.vue - {{ counterStore.count }} - {{ counterStore.double }}
<button @click="counterStore.addCount">+</button>
</div>
</template>
<style scoped>
</style>
Pinia_action异步写法
App.vue:
<script setup>
import Son1Com from '@/components/Son1Com.vue'
import Son2Com from '@/components/Son2Com.vue'
// 导入函数
import { useCounterStore } from '@/store/counter'
import { useChannelStore } from '@/store/channel'
const counterStore = useCounterStore()
const channelStore = useChannelStore()
</script>
<template>
<div>
<h3>
App.vue根组件
- {{ counterStore.count }}
- {{ counterStore.msg }}
</h3>
<Son1Com></Son1Com>
<Son2Com></Son2Com>
<hr>
<button @click="channelStore.getList">获取频道数据</button>
<ul>
<li v-for="item in channelStore.channelList" :key="item.id">{{ item.name }}</li>
</ul>
</div>
</template>
<style scoped>
</style>
channel.js:
import { defineStore } from 'pinia'
import { ref } from 'vue'
import axios from 'axios'
export const useChannelStore = defineStore('channel', () => {
// 声明数据
const channelList = ref([])
// 声明操作数据的方法
const getList = async () => {
// 支持异步
const { data: { data } } = await axios.get('http://geek.itheima.net/v1_0/channels')
channelList.value = data.channels
console.log(data.channels)
}
// 声明getters相关
return {
channelList,
getList
}
})
storeToRefs解构数据不会丢失响应式
<script setup>
import { storeToRefs } from 'pinia'
import Son1Com from '@/components/Son1Com.vue'
import Son2Com from '@/components/Son2Com.vue'
// 导入函数
import { useCounterStore } from '@/store/counter'
import { useChannelStore } from '@/store/channel'
const counterStore = useCounterStore()
const channelStore = useChannelStore()
// 直接解构,不处理,数据会丢失响应式
// const { count, msg } = (counterStore)
// 使用storeToRefs数据不会丢失响应式
const { count, msg } = storeToRefs(counterStore)
// 方法可以直接被结构
const { getList } = channelStore
</script>
<template>
<div>
<h3>
App.vue根组件
- {{ count }}
- {{ msg }}
</h3>
<Son1Com></Son1Com>
<Son2Com></Son2Com>
<hr>
<button @click="getList">获取频道数据</button>
<ul>
<li v-for="item in channelStore.channelList" :key="item.id">{{ item.name }}</li>
</ul>
</div>
</template>
<style scoped>
</style>
Pinia持久化(本地化存储)
main.js:
import { createApp } from 'vue'
import { createPinia } from 'pinia'
// 1.装包:
// npm i pinia-plugin-persistedstate
// 2.导入持久化插件
import Persist from 'pinia-plugin-persistedstate'
import App from './App.vue'
const pinia = createPinia() // 创建Pinia实例
const app = createApp(App) // 创建根实例
// 2.
app.use(pinia.use(Persist)) // pinia插件的安装配置
app.mount('#app') // 视图的挂载
counter.js:
import { defineStore } from 'pinia'
import { computed, ref } from 'vue'
// 定义store
// defineStore(仓库的唯一标识, () => { ... })
// 导出函数 以函数的形式调用这个仓库
export const useCounterStore = defineStore('counter', () => {
// 声明数据 原本用 state 改为了 count
const count = ref(100)
// 声明操作数据的方法 action (普通函数)
const addCount = () => count.value++
const subCount = () => count.value--
// 声明基于数据派生的计算属性 getters (computed)
const double = computed(() => count.value * 2)
// 声明数据 state -- msg
const msg = ref('hello pinia')
return {
// 必须暴露出去,才能使用
count,
double,
addCount,
subCount,
msg
}
}, {
// 3.
// store.$id 是本地存储的默认 key ,这里是counter
// persist: true // 开启当前模块的持久化
// 可修改key(本地存储的唯一标识)
// pick可指定需要本地化存储的数据
persist: {
key: 'hm-counter',
pick: ['count']
}
})
pnpm 包管理器 - 创建项目:
优势:比同类工具快 2 倍左右、节省磁盘空间等(网址:pnpm - 速度快、节省磁盘空间的软件包管理器 | pnpm中文文档 | pnpm中文网)
安装方式:npm install -g pnpm
创建项目:pnpm create vue
装包:pnpm install
运行:pnpm dev
eslint.config.js:
import js from '@eslint/js'
import pluginVue from 'eslint-plugin-vue'
import skipFormatting from '@vue/eslint-config-prettier/skip-formatting'
import eslintPluginPrettier from 'eslint-plugin-prettier/recommended'
export default [
{
name: 'app/files-to-lint',
files: ['**/*.{js,mjs,jsx,vue}'],
},
{
name: 'app/files-to-ignore',
ignores: ['**/dist/**', '**/dist-ssr/**', '**/coverage/**'],
},
js.configs.recommended,
...pluginVue.configs['flat/essential'],
skipFormatting,
eslintPluginPrettier,
{
rules: {
// prettier专注于代码的美观度(格式化工具)
// 前置:
// 1. 禁用格式化插件 prettier format on save 关闭
// 2. 安装Eslint插件,并配置保存时自动修复
'prettier/prettier': [
'warn',
{
singleQuote: true, // 单引号
semi: false, // 无分号
printWidth: 80, // 每行宽度至多80字符
trailingComma: 'none', // 不加对象|数组最后逗号
endOfLine: 'auto' // 换行符号不限制(win mac 不一致)
}
],
// EsLint关注于规范,如果不符合规范,报错
'vue/multi-word-component-names': [
'warn',
{
ignores: ['index'] // vue组件名称多单词组成(忽略index.vue)
}
],
'vue/no-setup-props-destructure': ['off'], // 关闭props解构的校验(props解构丢失响应式)
// 添加未定义变量错误提示,create-vue@3.6.3 关闭,这里加上是为了支持下一个章节演示。
'no-undef': 'error'
}
}
]
提交前做代码检查:
1. 初始化git仓库,执行git init即可。
2. 初始化husky工具配置,执行pnpm dlx husky-init && pnpm install即可。 https://typicode.github.io/husky/
3. 修改.husky/pre-commit文件。
暂存区eslint校验:
1. 安装lint - staged包:pnpm i lint - staged -D。
2. 在package.json配置lint - staged命令。


3. 修改.husky/pre - commit文件。
目录调整: 默认生成目录结构不满足开发需求,需做自定义改动,主要工作如下:
1. 删除一些初始化的默认文件。
2. 修改剩余代码内容。
3. 新增调整所需的目录结构。
4. 拷贝全局样式和图片,安装预处理 器支持。
路由初始化:
1. 创建路由实例由createRouter实现。
2. 路由模式:
- history模式使用createWebHistory()。
- hash模式使用createWebHashHistory()。
- 参数是基础路径,默认/。

按需引入Element Plus:
1. 安装:pnpm add element - plus。
pnpm add -D unplugin-vue-components unplugin-auto-import
2. 配置按需导入,官方文档:https://element - plus.org/zh - CN/guide/quickstart.html。

3. 直接使用组件。
Pinia构建用户仓库和持久化流程:
状态管理(Pinia)→用户仓库(User)→持久化(pinia - plugin - persistedstate)→统一管理

数据交互 - 请求工具设计
axios配置:
- 创建axios实例:设置基准地址、超时时间。
- 请求拦截器:携带token。
- 响应拦截器:业务失败处理,摘取核心响应数据,401处理。
import axios from 'axios'
import { useUserStore } from '@/stores'
import { ElMessage } from 'element - plus'
import router from '@/router'
const baseURL = 'http://big - event - vue - api.itheima.net'
const instance = axios.create({
// TODO 1. 基础地址,超时时间
baseURL,
timeout: 10000
})
// 请求拦截器
instance.interceptors.request.use(
(config) => {
// TODO 2. 携带token
const useStore = useUserStore()
if (useStore.token) {
config.headers.Authorization = useStore.token
}
return config
},
(err) => Promise.reject(err)
)
// 响应拦截器
instance.interceptors.response.use(
(res) => {
// TODO 4. 摘取核心响应数据
if (res.data.code === 0) {
return res
}
// TODO 3. 处理业务失败
// 处理业务失败,给错误提示,抛出错误
ElMessage.error(res.data.message || '服务异常')
return Promise.reject(res.data)
},
(err) => {
// TODO 5. 处理401错误
// 错误的特殊情况 => 401 权限不足 或 token 过期 => 拦截到登录
if (err.response?.status === 401) {
router.push('/login')
}
ElMessage.error(err.response.data.message || '服务异常')
return Promise.reject(err)
}
)
export default instance
export { baseURL }
路由的设计和配置
import { createRouter, createWebHistory } from 'vue-router'
// createRouter 创建路由实例
// 配置 history 模式
// 1. history模式:createWebHistory 地址栏不带 #
// 2. hash模式:createWebHashHistory 地址栏带 #
const router = createRouter({
// vite 中的环境变量 import.meta.env.BASE_URL
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
{
path: '/login', component: () => import('@/views/login/LoginPage.vue') // 登录页
},
{
path: '/',
component: () => import('@/views/layout/LayoutContainer.vue'),
redirect: '/article/manage',
children: [
{
path: '/article/manage',
component: () => import('views/article/ArticleManage.vue')
},
{
path: '/article/channel',
component: () => import('@/views/article/ArticleChannel.vue')
},
{
path: '/user/profile',
component: () => import('@/views/user/UserProfile.vue')
},
{
path: '/user/avatar',
component: () => import('@/views/user/UserAvatar.vue')
},
{
path: '/user/password',
component: () => import('@/views/user/UserPassword.vue')
}
]
}
]
})
export default router
登录注册页面:使用element - plus表单&表单校验 功能需求说明:
1. 注册登录静态结构&基本切换
2. 注册功能(校验+注册)
3. 登录功能(校验+登录+存token)
首页layout架子:使用element - plus菜单组件 功能需求说明:
1. 基本架子拆解(菜单组件的使用)
2. 登录访问拦截
3. 用户基本信息获取&渲染
4. 退出功能(element - plus确认框)
相关文章:
【前端开发学习笔记15】Vue_8
手动添加Pinia到Vue项目: 在实际开发中,Pinia配置可在项目创建时自动添加。初次学习从零开始: 1. 用Vite创建空的Vue3项目,命令为npm create vuelatest。 2. 按官方文档将pinia安装到项目中。 import { createApp } from vue im…...
deepin linux UOS AI 使用 deepseek-r1 30B
我们用 ollama 下载 deepseek-r1 3B 执行命令: $ ollama pull models/unsloth/DeepSeek-R1-Distill-Qwen-32B-GGUF 下载完成后 我们就要重新更改目录和文件了 deepseek-r1/gguf (这是目录结构) 然后我把 gguf文件 更名成 DeepSeek-R1.gguf (就是目录下最大的那个文件) …...
通过docker启用rabbitmq插件
创建文件,docker-compose.yml services:rabbitmq:image: rabbitmq:4.0-managementports:- "5672:5672"- "15672:15672"volumes:- ./data/rabbitmq/data:/var/lib/rabbitmq # 持久化数据- ./data/rabbitmq/plugins/rabbitmq_delayed_message_ex…...
对比 LVS 负载均衡群集的 NAT 模式和 DR 模式,比较其各自的优势 与基于 openEuler 构建 LVS-DR 群集
一、 对比 LVS 负载均衡群集的 NAT 模式和 DR 模式,比较其各自的优势 NAT 模式 部署简单:NAT 模式下,所有的服务器节点只需要连接到同一个局域网内,通过负载均衡器进行网络地址转换,就可以实现负载均衡功能。不需要对…...
C++17 中 std::lcm:从入门到精通
文章目录 一、引言二、std::lcm 的基本概念三、入门示例四、计算多个整数的最小公倍数五、std::lcm 的实现原理六、在实际项目中的应用七、注意事项八、总结 一、引言 在 C 编程中,处理数学运算时,计算最小公倍数(Least Common Multiple&…...
html 点击弹出视频弹窗
一、效果: 点击视频按钮后,弹出弹窗 播放视频 二、代码 <div class="index_change_video" data-video-src="</...
docker安装mongo,导入、导出数据
1、docker安装mongo docker pull mongo docker run -d -p 27017:27017 --name mongodb mongodocker update mongodb --restartalways ## 开机自启动-d:表示以后台模式运行容器。 -p 27017:27017:将容器内部的 MongoDB 默认端口 27017 映射到宿主机的 27…...
代码随想录算法【Day44】
Day44 1143.最长公共子序列 class Solution { public:int longestCommonSubsequence(string text1, string text2) {vector<vector<int>> dp(text1.size() 1, vector<int>(text2.size() 1, 0));for (int i 1; i < text1.size(); i) {for (int j 1; …...
项目总结:java agent的使用
测试团队会做java agent的事,实现测试模拟,各种数据采集等等工作,而这些不需要开发改代码来做到,只需要挂载下agent。 目录 javaagent认识和例子代码例子:java.lang.instrument自定义实现一个javaagentagent jar测试 回…...
使用 LangChain 对接硅基流动(SiliconFlow)API:构建一个智能对话系统
文章目录 什么是硅基流动(SiliconFlow)?LangChain 简介在 LangChain 中对接硅基流动步骤 1:安装必要的库步骤 2:设置 API 密钥步骤 3:编写代码代码解析步骤 4:运行代码如何扩展和改进总结 在现代…...
如何借助NoETL指标平台实现数据分析、决策的提效?
通常,企业通过明确分析目标、定位所需分析的数据,再通过多渠道汇集销售数据、客户反馈、市场调研等信息,经过数据清洗、缺失值处理及格式标准化等手段,运用描述性统计、回归分析、聚类分析及关联规则挖掘等多样分析方法࿰…...
Java--IO流详解 (上)--字符流
目录 IO流的概念 字符流 输入流 Reader核心方法 1.close() 2.mark(int readAheadLimit) 3.markSupported() 4.read() 5.read(char[] cbuf) 6.read(char[] cbuf, int off, int len) 7.read(CharBuffer target) 8.ready() 9.reset() 10.skip(long n) Reader 的常用…...
大模型语言简介
大模型语言能做什么 信息提取 将长段文字中的信息抽取出来并且以结构化的方式输出。相比起传统NLP的方式,大模型在泛化能力上有非常大的提升,并且开发成本要低2个数量级。应用场景包括:论文论点论据提取、用户画像提取、舆情分析、病例结构…...
手动配置IP
手动配置IP,需要考虑四个配置项: 四个配置项 IP地址、子网掩码、默认网关、DNS服务器 IP地址:格式表现为点分十进制,如192.168.254.1 子网掩码:用于区分网络位和主机位 【子网掩码的二进制表达式一定是连续的&#…...
Golang 进阶训练营
一、Golang 的 slice、map、channel 1.1 slice vs array a : make([]int, 100) //切片 b : [100]int{} //数组array需指明长度,长度为常量且不可改变 array长度为其类型中的组成部分(给参数为长度100的数组的方法传长度为101的会报错) array在…...
2-使用wifidog实现portal
wifidog是openwrt上面实现portal认证的一个开源工具,从网关端到服务器都帮你搭建好,通过学习wifidog的原理,后面就可以改造成自己需要的逻辑。 1. openwrt安装wifidog 添加源 vim 14.07/feeds.conf.defaultsrc-git wifidog https://github.c…...
Spring Boot + ShardingSphere 踩坑记
最近在准备秋招,偷了个轮子项目之后想改个分表,于是有了这篇文章。 省流:请使用shardingsphere-jdbc 5.5.2,并根据官方5.5.2版本文档进行配置,不要使用starter。此外,如果希望使用INTERVAL分片算法&#x…...
AI时代前端开发的创造力:解放还是束缚?
在人工智能(AI)快速发展的时代,AI技术的影响已经渗透到各个领域,从医疗保健到金融服务,再到创意产业。AI工具的出现,为前端开发带来了前所未有的效率提升,但也引发了人们对创造力的担忧…...
有哪些免费的SEO软件优化工具
随着2025年互联网的不断发展,越来越多的企业意识到在数字营销中,网站的曝光度和排名至关重要。无论是想要提高品牌知名度,还是想要通过在线销售增加收益,SEO(搜索引擎优化)都是一项不可忽视的关键策略。而要…...
FastExcel + Java:打造高效灵活的Excel数据导入导出解决方案
作者:后端小肥肠 🍇 我写过的文章中的相关代码放到了gitee,地址:xfc-fdw-cloud: 公共解决方案 🍊 有疑问可私信或评论区联系我。 🥑 创作不易未经允许严禁转载。 姊妹篇: 基于AOP的数据字典实现…...
在Vue中,JavaScript数组常用方法,添加,插入,查找,删除等整理
在Vue中,JavaScript数组常用,添加,插入,查找,删除等整理 1.splice()方法可以直接修改原数组,通过指定要删除元素的索引来删除它。 例: let index // 要删除的元素的索引; this.array.splice(i…...
vue知识点2
1.methods和mounted的区别 methods是定义方法,不涉及到调用 mounted涉及到操作 所以methods后面是:,mounted后面是() 2.介绍一下emit的用法 如果子控件要调用父页面的方法,在父页面的子控件引用处&…...
node.js + html调用ChatGPTApi实现Ai网站demo(带源码)
文章目录 前言一、demo演示二、node.js 使用步骤1.引入库2.引入包 前端HTML调用接口和UI所有文件总结 前言 关注博主,学习每天一个小demo 今天是Ai对话网站 又到了每天一个小demo的时候咯,前面我写了多人实时对话demo、和视频转换demo,今天…...
14.Python生成器、迭代器、闭包、装饰器、元类、垃圾回收、内建函数
在 Python 中,生成器、迭代器、闭包、装饰器、元类、垃圾回收和内建函数是一些重要的概念和功能,它们对于编写高效、灵活的代码非常重要。下面我们逐一详细介绍这些概念及其用法。 1. 生成器(Generator) 生成器是一个函数&#…...
STM32+Proteus+DS18B20数码管仿真实验
1. 实验准备 硬件方面: 了解 STM32 单片机的基本原理和使用方法,本实验可选用常见的 STM32F103 系列。熟悉 DS18B20 温度传感器的工作原理和通信协议(单总线协议)。数码管可选用共阴极或共阳极数码管,用于显示温度值。…...
Vulhub靶机 ActiveMQ 反序列化漏洞(CVE-2015-5254)(渗透测试详解)
一、开启vulhub环境 docker-compose up -d 启动 docker ps 查看开放的端口 漏洞版本:Apache ActiveMQ 5.x ~ Apache ActiveMQ 5.13.0 二、访问靶机IP 8161端口 默认账户密码 admin/admin,登录 此时qucues事件为空 1、使用jmet-0.1.0-all.jar工具将…...
ConcurrentHashMap扩容
目录 一、tryPreSize方法-初始化数组 二、tryPreSize方法-扩容标识戳 三、transfer方法-构建新数组 四、transfer方法-迁移数据 五、transfer方法-lastRun机制 六、helpTransfer方法-协助扩容 三种触发方式 达到了扩容的阈值 一、tryPreSize方法-初始化数组 // 扩容前…...
2025年二级建造师报名流程图解
2025年二级建造师报名时间!附报名流程! ⏰️已公布25年二建考试时间的省份如下: ️4月19日、20日考试的城市有:贵州 ️5月10日、11日考试的城市有:湖北、陕西、宁夏、甘肃、福建、浙江、江西、黑龙江、河南、湖南、…...
【自学笔记】人工智能基础知识点总览-持续更新
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 人工智能重点知识点总览一、基础概念与原理1.1 人工智能定义与发展1.2 算法与数据结构1.3 数学基础 二、机器学习2.1 监督学习2.2 无监督学习2.3 强化学习 三、深度…...
hexo 魔改 | 修改卡片透明度
hexo 魔改 | 修改卡片透明度 ** 博客食物用更佳 博客地址 ** 这是笔者自己瞎倒腾的。作为前端菜鸡一枚,大佬们随便看看就好~ 我用的主题是 butterfly 4.12.0 分析 通过开发者工具可以看出来卡片的背景和 --card-bg 变量有关 再在 sources 下的 css 文件夹下的…...
