【前端开发学习笔记15】Vue_8

news2025/2/19 10:48:59

手动添加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确认框)

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

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

相关文章

通过docker启用rabbitmq插件

创建文件&#xff0c;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 模式&#xff0c;比较其各自的优势 NAT 模式 部署简单&#xff1a;NAT 模式下&#xff0c;所有的服务器节点只需要连接到同一个局域网内&#xff0c;通过负载均衡器进行网络地址转换&#xff0c;就可以实现负载均衡功能。不需要对…

C++17 中 std::lcm:从入门到精通

文章目录 一、引言二、std::lcm 的基本概念三、入门示例四、计算多个整数的最小公倍数五、std::lcm 的实现原理六、在实际项目中的应用七、注意事项八、总结 一、引言 在 C 编程中&#xff0c;处理数学运算时&#xff0c;计算最小公倍数&#xff08;Least Common Multiple&…

html 点击弹出视频弹窗

一、效果: 点击视频按钮后,弹出弹窗 播放视频 二、代码 <div class="index_change_video" data-video-src="</

代码随想录算法【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的事&#xff0c;实现测试模拟&#xff0c;各种数据采集等等工作&#xff0c;而这些不需要开发改代码来做到&#xff0c;只需要挂载下agent。 目录 javaagent认识和例子代码例子&#xff1a;java.lang.instrument自定义实现一个javaagentagent jar测试 回…

如何借助NoETL指标平台实现数据分析、决策的提效?

通常&#xff0c;企业通过明确分析目标、定位所需分析的数据&#xff0c;再通过多渠道汇集销售数据、客户反馈、市场调研等信息&#xff0c;经过数据清洗、缺失值处理及格式标准化等手段&#xff0c;运用描述性统计、回归分析、聚类分析及关联规则挖掘等多样分析方法&#xff0…

大模型语言简介

大模型语言能做什么 信息提取 将长段文字中的信息抽取出来并且以结构化的方式输出。相比起传统NLP的方式&#xff0c;大模型在泛化能力上有非常大的提升&#xff0c;并且开发成本要低2个数量级。应用场景包括&#xff1a;论文论点论据提取、用户画像提取、舆情分析、病例结构…

手动配置IP

手动配置IP&#xff0c;需要考虑四个配置项&#xff1a; 四个配置项 IP地址、子网掩码、默认网关、DNS服务器 IP地址&#xff1a;格式表现为点分十进制&#xff0c;如192.168.254.1 子网掩码&#xff1a;用于区分网络位和主机位 【子网掩码的二进制表达式一定是连续的&#…

Golang 进阶训练营

一、Golang 的 slice、map、channel 1.1 slice vs array a : make([]int, 100) //切片 b : [100]int{} //数组array需指明长度&#xff0c;长度为常量且不可改变 array长度为其类型中的组成部分&#xff08;给参数为长度100的数组的方法传长度为101的会报错&#xff09; array在…

2-使用wifidog实现portal

wifidog是openwrt上面实现portal认证的一个开源工具&#xff0c;从网关端到服务器都帮你搭建好&#xff0c;通过学习wifidog的原理&#xff0c;后面就可以改造成自己需要的逻辑。 1. openwrt安装wifidog 添加源 vim 14.07/feeds.conf.defaultsrc-git wifidog https://github.c…

AI时代前端开发的创造力:解放还是束缚?

在人工智能&#xff08;AI&#xff09;快速发展的时代&#xff0c;AI技术的影响已经渗透到各个领域&#xff0c;从医疗保健到金融服务&#xff0c;再到创意产业。AI工具的出现&#xff0c;为前端开发带来了前所未有的效率提升&#xff0c;但也引发了人们对创造力的担忧&#xf…

有哪些免费的SEO软件优化工具

随着2025年互联网的不断发展&#xff0c;越来越多的企业意识到在数字营销中&#xff0c;网站的曝光度和排名至关重要。无论是想要提高品牌知名度&#xff0c;还是想要通过在线销售增加收益&#xff0c;SEO&#xff08;搜索引擎优化&#xff09;都是一项不可忽视的关键策略。而要…

FastExcel + Java:打造高效灵活的Excel数据导入导出解决方案

作者&#xff1a;后端小肥肠 &#x1f347; 我写过的文章中的相关代码放到了gitee&#xff0c;地址&#xff1a;xfc-fdw-cloud: 公共解决方案 &#x1f34a; 有疑问可私信或评论区联系我。 &#x1f951; 创作不易未经允许严禁转载。 姊妹篇&#xff1a; 基于AOP的数据字典实现…

node.js + html调用ChatGPTApi实现Ai网站demo(带源码)

文章目录 前言一、demo演示二、node.js 使用步骤1.引入库2.引入包 前端HTML调用接口和UI所有文件总结 前言 关注博主&#xff0c;学习每天一个小demo 今天是Ai对话网站 又到了每天一个小demo的时候咯&#xff0c;前面我写了多人实时对话demo、和视频转换demo&#xff0c;今天…

STM32+Proteus+DS18B20数码管仿真实验

1. 实验准备 硬件方面&#xff1a; 了解 STM32 单片机的基本原理和使用方法&#xff0c;本实验可选用常见的 STM32F103 系列。熟悉 DS18B20 温度传感器的工作原理和通信协议&#xff08;单总线协议&#xff09;。数码管可选用共阴极或共阳极数码管&#xff0c;用于显示温度值。…

Vulhub靶机 ActiveMQ 反序列化漏洞(CVE-2015-5254)(渗透测试详解)

一、开启vulhub环境 docker-compose up -d 启动 docker ps 查看开放的端口 漏洞版本&#xff1a;Apache ActiveMQ 5.x ~ Apache ActiveMQ 5.13.0 二、访问靶机IP 8161端口 默认账户密码 admin/admin&#xff0c;登录 此时qucues事件为空 1、使用jmet-0.1.0-all.jar工具将…

2025年二级建造师报名流程图解

2025年二级建造师报名时间&#xff01;附报名流程&#xff01; ⏰️已公布25年二建考试时间的省份如下&#xff1a; ️4月19日、20日考试的城市有&#xff1a;贵州 ️5月10日、11日考试的城市有&#xff1a;湖北、陕西、宁夏、甘肃、福建、浙江、江西、黑龙江、河南、湖南、…

hexo 魔改 | 修改卡片透明度

hexo 魔改 | 修改卡片透明度 ** 博客食物用更佳 博客地址 ** 这是笔者自己瞎倒腾的。作为前端菜鸡一枚&#xff0c;大佬们随便看看就好~ 我用的主题是 butterfly 4.12.0 分析 通过开发者工具可以看出来卡片的背景和 --card-bg 变量有关 再在 sources 下的 css 文件夹下的…

Golang的并发编程案例详解

Golang的并发编程案例详解 一、并发编程概述 并发编程是指程序中有多个独立的执行线索&#xff0c;并且这些线索在时间上是重叠的。在 Golang 中&#xff0c;并发是其核心特性之一&#xff0c;通过 goroutine 和 channel 来支持并发编程&#xff0c;使得程序可以更高效地利用计…