【B站 heima】小兔鲜Vue3 项目学习笔记Day02

【B站 heima】小兔鲜Vue3 项目学习笔记Day02

码农世界 2024-05-22 前端 64 次浏览 0个评论

文章目录

    • Pinia
      • 1.使用
      • 2. pinia-计数器案例
      • 3. getters实现
      • 4. 异步action
      • 5. storeToRefsx 数据解构保持响应式
      • 6. pinia 调试
      • 项目起步
        • 1.项目初始化和git管理
        • 2. 使用ElementPlus
        • 3. ElementPlus 主题色定制
        • 4. axios 基础配置
        • 5. 路由设计
        • 6. 静态资源初始化和 Error lens安装
        • 7.scss自动导入
        • 8. Layout静态模板结构搭建
        • 9. Layout字体图标引入
        • 10.Layout一级导航渲染
        • 11. layout - 吸顶导航
        • 12. layout - Pinia优化重复请求
        • 小结

          Pinia

          1.使用

          vue专属状态管理库,vuex的替代

          优势:

          • 提供了更简单的API ,去掉了mutation
          • 提供了组合式API
          • 去掉了modules,每个store都是独立的模块
          • 搭配TS一起使用提供可靠的类型判断

            Pinia添加到vue项目中:

            • 创建一个新vue项目: create init vue@latest,装依赖,项目跑起来
            • 打开pinia官方文档,是个小菠萝。点击开始,有个安装选项
              • 我是使用npm安装:npm install pinia
                • 按照文档使用 pinia

                • 在项目中实际应用(记不住看文档使用即可

                  2. pinia-计数器案例

                  看官方文档的基础实例学习如何使用

                  找和vue3语法相似的语法进行使用

                  • 创建一个 store( state+action )

                    在src添加一个stores文件夹,新建文件counter.js

                    //counter.js
                    // 导入一个方法 defineStore
                    import { defineStore } from 'pinia'
                    import {ref} form 'vue'
                    // 参数:标识 回调函数
                    //!!变量名字需保持规范:use+函数名 
                    //useCounterStore是一个方法,需执行才能得到真是store实例对象
                    export const useCounterStore = defineStore('counter', () => {
                        //1.定义数据state
                        const count = ref(0)
                        // 2.定义修改数据的方法(action 同步+异步)
                        const increment = () => {
                            count.value++
                        }
                        // 3.以对象的方式return供组件使用
                        return {
                            count,
                            increment
                        }
                    })
                    
                    • 组件使用 store
                      
                      
                      

                      3. getters实现

                      pinia中的getters直接使用computed函数进行模拟

                      //counter.js
                      // 导入一个方法 defineStore
                      import { defineStore } from 'pinia'
                      import { computed, ref } from 'vue'
                      //定义并暴露一个函数useCounterStore 参数:标识 回调函数
                      export const useCounterStore = defineStore('counter', () => {
                          //1.定义数据state
                          const count = ref(0)
                          // 2.定义修改数据的方法(action 同步+异步)
                          const increment = () => {
                              count.value++
                          }
                          // --  --  getters实现  --   --
                          const doubleCount = computed(() => count.value * 2)
                          // 3.以对象的方式return供组件使用
                          return {
                              count,
                              increment,
                              doubleCount
                          }
                      })
                      

                      这时useCountStore中就有了doubleCount这个方法了

                      
                      
                      

                      4. 异步action

                      action中实现异步和组件中定义数据和方法的风格完全一致

                      安装axios: npm install axios

                      举个获取数据列表 的栗子,获取数据接口地址:http://geek.itheima.net/v1_0/channels

                      //counter.js
                      const list = ref([])  //存放列表数据
                      //异步action
                          const getList = async () => {
                              const res = await axios.get('http://geek.itheima.net/v1_0/channels');
                          }
                          
                       //返回,让组件可以拿到
                          return{
                              list,
                              getList
                          }
                      
                      
                      

                      看一下网页的网络

                      给list赋值

                      //异步action
                          const getList = async () => {
                              const res = await axios.get('http://geek.itheima.net/v1_0/channels');
                              list.value = res.data.data.channels
                          }
                      

                      渲染在页面上,使用v-for

                      
                      

                      效果:

                      5. storeToRefsx 数据解构保持响应式

                      辅助保持数据(state+getter)的响应式解构

                      方法可以正常解构赋值哈

                      const {count,doubleCount} = counterStore

                      这样解构是不可以的,会造成响应式丢失,也就是数据变化页面不会更新。

                      我们可以这样写:

                      const {count,doubleCount} = storeToRefs(counterStore);
                      

                      6. pinia 调试

                      使用之前使用的devtools调试工具

                      项目起步

                      1.项目初始化和git管理

                      创建并打开,将项目运行起来(按照绿色的来做):

                      这样说明成功

                      下面我们看一下 小兔鲜 需要哪些基础目录,

                      我们按照下面的图片在刚创建好的项目中创建文件夹。

                      componsables组合函数文件夹:存放通用的函数

                      使用git管理项目,手动初始化

                      执行命令并完成手动提交

                      git init
                      git add .
                      git commit -m "init"
                      

                      配置别名路径联想提示

                      编写代码,一旦输入@/,vscode会立刻联想出src所有的子目录和文件,统一文件路径,不容易出错。

                      步骤:1.根目录新增jsconfig.json文件

                      ​ 2.添加配置项

                      2. 使用ElementPlus

                      我们在这个项目中使用了通用性组件,由ElementPlus提供

                      步骤:安装 - 按需引入 - 测试组件

                      看文档

                      安装elementPlus:npm install element-plus --save

                      安装两个插件:npm install -D unplugin-vue-components unplugin-auto-import

                      安装之后我们来依照文档配置这两个插件

                      //vite.config.js
                      //按需导入element Plus插件
                      import AutoImport from 'unplugin-auto-import/vite'
                      import Components from 'unplugin-vue-components/vite'
                      import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
                      // https://vitejs.dev/config/
                      export default defineConfig({
                        plugins: [  //插件配置文件
                          vue(),
                          //elementPlus插件
                          AutoImport({
                            resolvers: [ElementPlusResolver()],
                          }),
                          Components({
                            resolvers: [ElementPlusResolver()],
                          }),
                        ],
                      

                      配置文件写好后,重启项目

                      做个测试,看看组件能不能使用

                      
                      

                      生效就OK

                      3. ElementPlus 主题色定制

                      小免鲜主题色和elementPlus默认的主题色存在冲突

                      通过定制主题让elementPlus的主题色和小兔鲜项目保持一致

                      步骤:

                      • 安装sass:npm i sass -D

                      • 准备定制文件 :styles/element/index.scss

                        /* 只需要重写你需要的即可 */
                        @forward 'element-plus/theme-chalk/src/common/var.scss' with (
                          $colors: (
                            'primary': (
                              // 主色
                              'base': #27ba9b,
                            ),
                            'success': (
                              // 成功色
                              'base': #1dc779,
                            ),
                            'warning': (
                              // 警告色
                              'base': #ffb302,
                            ),
                            'danger': (
                              // 危险色
                              'base': #e26237,
                            ),
                            'error': (
                              // 错误色
                              'base': #cf4444,
                            ),
                          )
                        )
                        
                        • 对ElementPlus样式进行覆盖:通知Element使用scss语言,自动导入定制的scss文件覆盖。
                          //vite.config.js
                          import { fileURLToPath, URL } from 'node:url'
                          import { defineConfig } from 'vite'
                          import vue from '@vitejs/plugin-vue'
                          //按需导入element Plus插件
                          import AutoImport from 'unplugin-auto-import/vite'
                          import Components from 'unplugin-vue-components/vite'
                          import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
                          // https://vitejs.dev/config/
                          export default defineConfig({
                            plugins: [  //插件配置文件
                              vue(),
                              //elementPlus插件
                              AutoImport({
                                // 1.配置elementPlus采用sass样式配色系统
                                resolvers: [ElementPlusResolver()],
                              }),
                              Components({
                                resolvers: [ElementPlusResolver({ importStyle: 'sass' })],
                              }),
                            ],
                            resolve: {
                              alias: {
                                '@': fileURLToPath(new URL('./src', import.meta.url))
                              }
                            },
                            css: {
                              preprocessorOptions: {
                                scss: {
                                  //2.自动导入定制化样式文件进行样式覆盖
                                  additionalData: `@use "@/styles/element/index.scss" as *;`
                                }
                              }
                            }
                          })
                          

                          4. axios 基础配置

                          安装:npm i axios

                          配置基础实例(统一接口实例)

                          在utils创建一个http.js

                          //axios基础封装
                          import axios from "axios";
                          const httpInstance = axios.create({
                              baseURL: 'http://pcapi-xiaotuxian-front-devtest.itheima.net',
                              timeout: '5000'           //5s
                          })
                          //拦截器,默认先这样写着,后面有需求再配置
                          // axios请求拦截器
                          instance.interceptors.request.use(config => {
                              return config
                          }, e => Promise.reject(e))
                          // axios响应式拦截器
                          instance.interceptors.response.use(res => res.data, e => {
                              return Promise.reject(e)
                          })
                          export default httpInstance
                          

                          扩展:如果项目里面不同的业务模块需要的接口基地址不同,该如何来做?

                          答:axios.create()方法可以执行多次,每次执行就会生成一个新

                          的实例

                          const http1 = axios.create({baseURL:'url1'})
                          const http1 = axios.create({baseURL:'url2'})
                          

                          5. 路由设计

                          • 设计首页和登录页的路由(一级路由)

                            路由设计规则:找内容切换的区域,如果是页面整体切换,则为一级路由

                            eslintrc.cjs配置,避免命名报错:

                            /* eslint-env node */
                            module.exports = {
                              root: true,
                              'extends': [
                                'plugin:vue/vue3-essential',
                                'eslint:recommended'
                              ],
                              parserOptions: {
                                ecmaVersion: 'latest'
                              },
                              rules: {
                                'vue/multi-word-component-names':0, //不再强制要求组件命名
                              }
                            }
                            

                            删除views文件夹下的组件,创建两个新文件夹Login和Layout,分别创建一个index.vue文件,写入一些代码。

                            
                            

                            打开router文件夹的index.js,删掉默认的代码。导入login和layout组件,在routes中配置path、component属性

                            import { createRouter, createWebHistory } from 'vue-router'
                            import Login from '@/views/Login/index.vue'
                            import Layout from '@/views/Layout/index.vue'
                            // createRouter:创建router实例对象
                            // createWebHistory:创建history模式的路由
                            const router = createRouter({
                              history: createWebHistory(import.meta.env.BASE_URL),
                              routes: [
                                {
                                  path: '/',
                                  component: Layout
                                },
                                {
                                  path: '
                            

                            App.vue中写入一级路由出口组件

                            
                            
                            

                            项目运行效果:

                            • 设计分类页和默认Home页路由(二级路由)

                              路由设计原则:找内容切换的区域,如果是在一级路由页的内部切换,则为二级路由

                              和上面一样,在views新增两个文件夹,一个Home,一个Category,分别创建一个index.vue,随便写点内容

                              //router index.js
                              import { createRouter, createWebHistory } from 'vue-router'
                              import Login from '@/views/Login/index.vue'
                              import Layout from '@/views/Layout/index.vue'
                              import Home from '@/views/Home/index.vue'
                              import Category from '@/views/Category/index.vue'
                              // createRouter:创建router实例对象
                              // createWebHistory:创建history模式的路由
                              const router = createRouter({
                                history: createWebHistory(import.meta.env.BASE_URL),
                                routes: [
                                  {
                                    path: '/',
                                    component: Layout,
                                    children: [
                                      {
                                        path: '',
                                        component: Home
                                      },
                                      {
                                        path: 'category',
                                        component: Category
                                      }
                                    ]
                                  },
                                  {
                                    path: '/login',
                                    component: Login
                                  }
                                ]
                              })
                              export default router
                              

                              这两个二级路由要在Layout组件里给准备路由出口

                              
                              
                              

                              效果:

                              6. 静态资源初始化和 Error lens安装

                              图片资源 - 把images文件夹放到assets目录下

                              样式资源 - 把common.scss文件放到styles目录下(这个文件在资源里面,自己拿)。

                              在main.js中引入common.scss

                              //main.js
                              //引入初始化样式文件
                              import '@/styles/common.scss'
                              

                              error lens是一个实时提供错误警告信息的VScode插件,方便开发,在扩展程序里搜索然后安装就可以了。

                              7.scss自动导入

                              在项目里一些组件共享的色值会以scss变量的方式统一放到一个名为var.scss 的文件中。

                              正常组件中使用,需要先导入scss文件,再使用内部的变量,比较繁琐,自动导入可以免去手动导入的步骤,直接使用内部的变量。

                              配置步骤:

                              • 新增一个var.scss文件,存入色值变量
                                $xtxColor: #27ba9b;
                                $helpColor: #e26237;
                                $sucColor: #1dc779;
                                $warnColor: #ffb302;
                                $priceColor: #cf4444;
                                
                                • 通过vite.config.js配置自动导入文件
                                   css: {
                                      preprocessorOptions: {
                                        scss: {
                                          //2.自动导入定制化样式文件进行样式覆盖
                                          additionalData: `
                                          @use "@/styles/element/index.scss" as *;
                                          @use "@/styles/var.scss" as *;
                                          `,
                                        }
                                      }
                                    }
                                  

                                  8. Layout静态模板结构搭建

                                  Layout文件夹创建一个components文件夹,创建LayoutFooter.vue、LayoutHeader.vue、LayoutNav.vue组件。

                                  
                                  
                                  
                                  
                                  
                                  
                                  
                                  
                                  
                                  
                                  
                                  
                                  
                                  

                                  修改一下Layout的index.vue

                                  
                                  
                                  

                                  效果:

                                  9. Layout字体图标引入

                                  这里的图标没有引入,我们使用的是阿里的字体图标库,使用 font-class 引用的方式

                                  将这个加入到index.html文件中

                                    
                                  

                                  效果:

                                  看下面这个周杰伦旁边的小人儿

                                  它对应的代码如下

                                  10.Layout一级导航渲染

                                  静态结构已经全部搭建好了,我们要使用后端接口渲染 渲染一级导航路由,也就是这:

                                  实现步骤:

                                  • 根据接口文档封装接口函数
                                  • 发生请求获取数据列表
                                  • v-for渲染页面

                                    在apis文件夹下创建layout.js文件,封装接口

                                    import httpInstance from '@/utils/http.js'
                                    //获取目录
                                    export function getCategoryAPI() {
                                        return httpInstance({
                                            url: '/home/category/head'
                                        })
                                    }
                                    

                                    来到LayoutHeader组件,引入接口

                                    封装一个函数getCategory,返回的是promise对象,使用async/await。

                                    在挂载完成之后(onMounted)调用函数getCategory。

                                    打印res看一下请求的数据,定义一个响应式空数组categoryList接收后台传入的数据。

                                    将 请求 封装进 函数 中是因为方便书写请求前后的逻辑

                                    
                                    

                                    获取数据成功之后,使用v-for渲染数据

                                    • {{ item.name }}

                                    效果:

                                    11. layout - 吸顶导航

                                    需求:浏览器上下滚动过程中,如果距离顶部的滚动距离大于78px,吸顶导航显示,小于78px隐藏

                                    步骤:

                                    • 准备吸顶导航组件
                                    • 获取滚动距离
                                    • 滚动距离作判断条件控制组件盒子展示或隐藏

                                      吸顶导航组件

                                      
                                      
                                      
                                      

                                      在Layout文件夹下的index.vue中引入这个组件,使用起来

                                      
                                      
                                      

                                      关键样式(LayoutFixed中):

                                      .app-header-sticky {
                                          width: 100%;
                                          height: 80px;
                                          position: fixed;
                                          left: 0;
                                          top: 0;   //置顶
                                          z-index: 999;
                                          background-color: #fff;
                                          border-bottom: 1px solid #e4e4e4;
                                          
                                          // 此处为关键样式!!!
                                          // 状态一:往上平移自身高度 + 完全透明
                                          transform: translateY(-100%);   //平移出页面
                                          opacity: 0;  //透明度为0
                                          // 状态二:移除平移 + 完全不透明
                                          //想让组件显示出来只需要加上class = "show" 即可
                                          &.show {   
                                              transition: all 0.3s linear;
                                              transform: none;
                                              opacity: 1;  //完全不透明
                                          }
                                      

                                      获取滚动距离,不自己写了,使用一个vueUse插件,安装一下

                                      安装:npm i @vueuse/core

                                      滚动使用的是useScroll,解构的这个y就是垂直方向滚动的距离。

                                      import { useScroll } from '@vueuse/core'
                                      const { y } = useScroll(window)
                                      

                                      当y>78时,show生效,我们使用 vue 的动态类实现方式

                                       

                                      12. layout - Pinia优化重复请求

                                      我们要把 吸顶导航 组件也转化成数据动态获取的,修改完后我们发现请求了两次数据

                                      
                                      
                                      
                                      
                                      
                                      
                                      
                                      
                                      
                                      

                                      stores新增category.js

                                      import { ref } from 'vue'
                                      import { defineStore } from 'pinia'
                                      import { getCategoryAPI } from '@/apis/layout'
                                      export const useCategoryStore = defineStore('category', () => {
                                        // 导航列表的数据管理
                                        // state 导航列表数据
                                        const categoryList = ref([])
                                        // action 获取导航数据的方法
                                        const getCategory = async () => {
                                          const res = await getCategoryAPI()
                                          categoryList.value = res.result
                                        }
                                        return {
                                          categoryList,
                                          getCategory
                                        }
                                      })
                                      

                                      使用:

                                      Login文件夹的index.vue

                                      
                                      

                                      删掉(注释)LoginFixed和LoginHeader中相关的代码

                                      
                                      
                                      
                                      
                                      
                                      
                                      

                                      OK,没问题

                                      小结

                                      本篇文章,主要学习了Pinia管理数据,以及Layout的相关知识

                                      私密马赛,图片有亿点糊,我是在typra上面写的,截到csdn上就糊掉了呜呜

                                      祝大家学习顺利!!

转载请注明来自码农世界,本文标题:《【B站 heima】小兔鲜Vue3 项目学习笔记Day02》

百度分享代码,如果开启HTTPS请参考李洋个人博客
每一天,每一秒,你所做的决定都会改变你的人生!

发表评论

快捷回复:

评论列表 (暂无评论,64人围观)参与讨论

还没有评论,来说两句吧...

Top