前言
抽空整理練手項(xiàng)目升級后的一些坑點(diǎn); 各位項(xiàng)目中有問題遇到困難也可以留言;我會(huì)盡快回復(fù)! 后續(xù)還會(huì)繼續(xù)更新問題點(diǎn)!
1. 預(yù)處理器
安裝sass以及配置全局scss
npm install node-sass
npm install sass-loader
node 版本不能過高; 目前成功版本為10.15.0
; 可通過安裝"n"來管理node版本
配置全局mixin.scss
根目錄找到vite.config.js
// vite.config.js
import{defineConfig}from'vite';
importvuefrom'@vitejs/plugin-vue';
import{resolve}from'path';
// https://vitejs.dev
/config/exportdefaultdefineConfig({
plugins:[vue(),],
resolve:{
// 配置別名
alias:[{find:'@',replacement:resolve(__dirname,'./src')},
{find:'views',replacement:resolve(__dirname,'./src/views')},],},
css:{
// 添加全局
mixin.scsspreprocessorOptions:{scss:{additionalData:'@import "@/style/libs.scss";',},},},});
css參與計(jì)算 (內(nèi)置模塊)
原來的寫法直接計(jì)算是不行的, 需要使用內(nèi)置模塊math.div()方法參與計(jì)算
libs.scss
使用math 需要先聲明使用; 添加在文件頂部@use"sass:math"
原來的寫法border-width:$w/2;
新寫法border-width:math.div($w/2)
新寫法; 切記math需要聲明使用(https://sass-lang.com/documentation/modules); 不然就會(huì)提示:
Error: There is no module with the namespace "math".
2. require 使用
問題: 想引入某個(gè)目錄下的所有文件?
constfile=require.context('@/views/',true,/\.vue$/)
結(jié)果提示找不到名稱“require”
宣旱。是否需要為節(jié)點(diǎn)安裝類型定義? 請嘗試使用npm i --save-dev @types/node
盛杰,然后將 “node” 添加到類型字段聂薪。
解決辦法:
按照提示安裝庫
npm i --save-dev @types/node
然后在tsconfig.jsontypes
字段中添加node; 然后重啟一下; 就行了
// tsconfig.json{"compilerOptions":{"target":"esnext","module":"esnext","strict":false,"jsx":"preserve","moduleResolution":"node","types":["vite/client","node",],...}}}
3.別名配置
問題: 當(dāng)你使用別名@, 你會(huì)發(fā)現(xiàn)別名框架并沒有配置 會(huì)出現(xiàn)提示找不到模塊“@/router/index
”或其相應(yīng)的類型聲明
import router from '@/router/index';
解決辦法:
在vite.config.js
配置別名
// vite.config.js import{defineConfig}from'vite';importvuefrom'@vitejs/plugin-vue';import{resolve}from'path';// https://vitejs.dev/config/exportdefaultdefineConfig({plugins:[vue(),],resolve:{// 配置別名alias:[{find:'@',replacement:resolve(__dirname,'./src')},{find:'views',replacement:resolve(__dirname,'./src/views')},],},css:{// 添加全局mixin.scsspreprocessorOptions:{scss:{additionalData:'@import "@/style/libs.scss";',},},},});
很多人以為這樣就結(jié)束了;在js 文件中確實(shí)就已經(jīng)可以用了; 但是在.vue 文件中還是不行,其實(shí)還需要在tsconfig.json里面配置對應(yīng)的別名; 詳情見http://www.reibang.com/p/1477b68b2d69
// tsconfig.json {"compilerOptions":{..."paths":{"@/*":["./src/*"],"views/*":["./src/views/*"],}}}
4.動(dòng)態(tài)路由
問題:Invalid route component at extractComponentsGuards
?這個(gè)問題不陌生吧!! 有倆個(gè)因素;
1. 如果你用JSON.stringify()
轉(zhuǎn)為string
后存儲(chǔ); 因?yàn)?code>JSON.stringify()在序列化的過程中function
晚胡、undefined
喂链、symbol
這幾種類型是不可枚舉屬性; 序列化后這個(gè)鍵值對會(huì)消失;addRoute()
的時(shí)候就會(huì)發(fā)現(xiàn)沒有這個(gè)component.
2. 使用component:()=>import('views/Order/index.vue')
懶加載方式引入;也會(huì)提示Invalid route component
;
tips: 調(diào)試路由時(shí)可通過router.getRoutes(); 查看動(dòng)態(tài)路由是否已經(jīng)完整注入進(jìn)去
解決辦法1. 使用Glob Import
動(dòng)態(tài)導(dǎo)入
// src/mockjs/mock.routes.tsexportdefaultroutes=[{path:'/',name:'home',component:'views/Home/index.vue',meta:{// 頁面標(biāo)題title:'首頁',// 身份認(rèn)證userAuth:false,},},]
// src/router/index.ts
importroutesfrom"@/mockjs/mock.routes"
// 路由元信息
constmodules=import.meta.golb("../views/**/**.vue")
//使用golb ++
routes.forEach(item=>{router.addRoute("home",{path:item.path,name:item.name,meta:...item.meta,component:
//本地能使用添谊,上生產(chǎn)直接GG//
()=>import(/* @vite-ignore */ `/@views/${itemRouter.component}`),
//使用modulesmodules
[/* @vite-ignore */`../views/${item.component}`],})})
解決辦法2 : 在聲明路由數(shù)據(jù)時(shí)使用 RouteRecordRaw; 下面是
RouteRecordRaw`的注解
當(dāng)用戶通過routes option或者router.addRoute()來添加路由時(shí),可以得到路由記錄侄榴。 有三種不同的路由記錄:
單一視圖記錄:有一個(gè) component 配置
多視圖記錄 (命名視圖) :有一個(gè) components 配置
重定向記錄:沒有 component
或components
配置,因?yàn)橹囟ㄏ蛴涗浻肋h(yuǎn)不會(huì)到達(dá)网沾。
// src/mockjs/mock.routes.ts
exportdefaultroutes:RouteRecordRaw[]=[{
path:'/',
name:'home',
component:component:()=>import("views/Home/index.vue"),
meta:{
// 頁面標(biāo)題
title:'首頁',
// 身份認(rèn)證
userAuth:false,
},
},
]
// src/router/index.ts importroutesfrom"@/mockjs/mock.routes"
// 路由元信息 確保自己的地址是否正確
routes.forEach(item=>{router.addRoute(item})})
5.pinia 使用以及動(dòng)態(tài)路由持續(xù)存儲(chǔ)踩坑
注釋: pinia
跟vuex
一樣也是一個(gè)基于vue的狀態(tài)管理庫; 使用pinia
時(shí),可以理解為它每一個(gè)store
都是動(dòng)態(tài)的癞蚕、獨(dú)立的; 不像vuex
一樣可嵌套,因?yàn)闆]有modules!
pinia 使用:
npm install pinia
or
yarn add pinia
// src/store/index.ts
import{createPinia}from"pinia"
constpinia=createPinia()exportdefaultpinia
//main.ts ....importpiniafrom"./store/index"
createApp(App).use(router).use(pinia).mount('#app')
定義單個(gè)store
// src/store/createRouteInfo.ts
import{defineStore}from"pinia"importrouterfrom"
@/router/index"
// 封裝的路由
// defineStore的第一個(gè)參數(shù)是應(yīng)用程序中 store 的唯一id;這些注解官網(wǎng)都有
constuseStore=defineStore('useStore',{state:()=>({
routeModules:[],menu:[].....
}),
getterL:{routeModules:state=>
state.routeModules,menu:state=>
state.menu},
// 上面那倆個(gè)參數(shù)沒變; 沒有mutations!! actions類似于組件中methods,也可以定義一些業(yè)務(wù)邏輯;
actions:{addAsyncRoutes(routes){
// 業(yè)務(wù)邏輯
//設(shè)置動(dòng)態(tài)路由
routes.forEach(el=>{router.addRoute(el)})}}})exportdefaultuseStore
使用useStore
// src/components/menu.vue
<scriptlang="ts"setup>
import useStore from "@/store/createRouteInfo"
import {storeToRefs} from "pinia"
const store = useStore()
// 使參數(shù)變?yōu)轫憫?yīng)式
const {routeModules,menu} = storeToRefs(store)
onMounted(()=>{ getMenu() })
const getMenu = ()=>{ let result = getMenuData(params)
// set store value
store.$patch(state=>{ state.menu = result.data.menu }) }
</script>
<template>
<divclass="menu">
<ul><liv-for="li in menu":key="li.id">{{li.text}}</li></ul>
</div>
</template>
動(dòng)態(tài)路由權(quán)限踩坑
很多人做動(dòng)態(tài)路由時(shí) 數(shù)據(jù)存在store;頁面刷新后頁面空白或者進(jìn)入404
頁面; 并且使用router.getRoutes()
查看新增的路由已經(jīng)消失; 是因?yàn)閟tore是存在瀏覽器的堆棧內(nèi)存里面; 刷新后頁面數(shù)據(jù)被釋放掉; 那么如何解決呢? 想一想 頁面刷新后我們的框架是會(huì)重新掛載的! so! main.js
? 試試就試試!!!!
// src/store/asyncRoute.ts importroutesfrom"@/mockjs/mock.routes"
// 路由元信息
import useStorefrom"@/store/createRouteInfo"
// 封裝的路由
conststore=useStore()const{role}=localStorage.getItem('user')||{}
// 是否已經(jīng)登陸, 初級判斷 可增加路由權(quán)限判斷
if(role==='admin'){
// 此方法在 上面“定義單個(gè)store” createRouteInfo.ts 文件中定義了
store.addAsyncRoutes(routes)
}
// main.js.....import"./store/asyncRoute".....
createApp(App).use(router).use(pinia).mount('#app')
頁面更新后提示報(bào)錯(cuò)信息:
問題: Uncaught Error: [??]: getActivePinia was called with no active Pinia. Did you forget to install pinia
?
什么意思呢? 你當(dāng)前正在使用pinia; 但是pinia 還沒有掛載成功!!!! what? 我使用vuex就不會(huì)這樣呀!!!! 戲精
解決方案:
無意間在廖雪峰的官網(wǎng)看到過一句評論!!所謂的對象、函數(shù)在瀏覽器內(nèi)存中就是一個(gè)地址;找個(gè)地址只想某個(gè)函數(shù)或者對象或者方法辉哥、誰拿到這個(gè)地址就擁有操作的權(quán)利; 所謂的函數(shù)作為參數(shù)傳入別的函數(shù); 其實(shí)就是把地址給了它; 讓它擁有的操作的權(quán)利! 我覺得挺精辟!!
使用時(shí)引入pinia
// src/store/index.ts
import{createPinia}from"pinia"
constpinia=createPinia()exportdefaultpinia
//_______________分割線__________________ //
//src/store/asyncRoute.ts
importroutesfrom"@/mockjs/mock.routes"
// 路由元信息
importuseStorefrom"@/store/createRouteInfo"
// 封裝的路由 importpiniafrom"./index"
// 引入pinia
conststore=useStore(pinia)
// 把pinia 傳進(jìn)去 就可以任意任意使用里面的屬性了
const{role}=localStorage.getItem('user')||{}
// 是否已經(jīng)登陸, 初級判斷 可增加路由權(quán)限判斷
if(role==='admin'){
// 此方法在 上面“定義單個(gè)store” createRouteInfo.ts 文件中定義了
store.addAsyncRoutes(routes)}