@
路径别名vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
// 引入path,node提供的模块,可以获取文件或文件夹的路径
import path from 'path'
export default defineConfig({
plugins: [vue()],
resolve: {
alias: {
'@': path.resolve('./src')
}
}
})
tsconfig.json
{
"compilerOptions": {
// 配置路径别名
"baseUrl": "./",
"paths": {
"@/*": ["src/*"]
}
}
}
SCSS
全局变量vite.config.ts
export default defineConfig({
// scss全局变量一个配置
css: {
preprocessorOptions: {
scss: {
javascriptEnabled: true,
additionalData: '@import "./src/styles/variable.scss";',
},
},
},
})
SVG
使用方式vite.config.ts
// 配置svg:引入插件
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'
export default defineConfig({
plugins: [
createSvgIconsPlugin({
// 配置svg:指定svg资源目录
iconDirs: [path.resolve(process.cwd(), 'src/asstes/icons')],
// 配置svg:指定svg资源name
symbolId: 'icon-[dir]-[name]'
})
]
}
main.ts
// svg插件需要配置代码
import 'virtual:svg-icons-register'
使用
SVG
全局组件
1、单独引入注册
main.ts
import SvgIcon from '@/components/SvgIcon/index.vue'
app.components('SvgIcon', SvgIcon)
2、插件注册,引入components
下组件遍历注册
@/components/index.ts
import SvgIcon from './SvgIcon/index.vue'
const allGloablComponent = { SvgIcon }
export default{
install(app){
Object.keys(allGloablComponent).forEach(key => {
app.component(key, allGloablComponent[key])
})
}
}
main.ts
//引入自定义插件对象:注册整个项目全局组件
import gloalComponent from '@/components'
//安装自定义插件
app.use(gloalComponent)
EL
全局图标@/components/index.ts
// 引入全部elmentPlus的图标
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
const allGloablComponent = { SvgIcon }
export default{
install(app){
// 将element-plus的图标全部注册
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
app.component(key, component)
}
}
}
main.ts
// 引入自定义插件对象:注册整个项目全局组件
import gloalComponent from '@/components'
// 安装自定义插件
app.use(gloalComponent)
使用方式
编程式导航
<script setup lang="ts">
import { useRouter } from 'vue-router';
const $router = useRouter()
const toRoutes = (path) => {
$router.push(path)
}
</script>
项目当中的各个路由在什么条件下可以访问,什么条件下不可以访问
element-plus
组件Menu
菜单折叠图标问题:在使用 el-menu
菜单的折叠功能时,因为自定义路由和Menu组件,导致图标没有正常显示
解决:将图标组件移出 template
外边
{{item.children[0].meta.title}}
{{item.meta.title}}
问题:使用 el-menu
菜单在页面刷新时,已展开的菜单会关闭,
解决:配置 el-menu
的 default-active
属性,通过 router
将页面路径赋值给他
备注: route
获取页面路径, router
页面跳转,现 $route
以改为宏函数,可以直接在 template
使用,无需引入,若想在 script
中使用,还是得引入
import { useRoute } from 'vue-router'
$route = useRoute()
defineEmits
vue3
内置 defineEmits
和 definProps
可无需引入直接使用
// son.vue
let $emit = defineEmits(['fn1', 'fn2', ...])
const updata = () => {
$emit('fn1', { name: '张三', age: '23' })
}
// father.vue
<son @fn1="fn1"></son>
const fn1 = (name='', age='') => { ... }
definProps
// father.vue
<son :name="name" :data="data"></son>
// son.vue
let props = defineProps({
name: {
type: String,
default: ''
},
data:{
type:Object,
default:() => ({ ... })
}
})
// 或
defineProps({
name:{
type:String,
default:''
},
data:{
type:Object,
default:() => ({ ... })
}
})
ref
// father.vue
<son ref="son"/>
let son = ref(null)
const fn = () => {
son.value.fnSon
}
// son.vue
const fnSon = () => {
// ...
}
defineExpose({ fnSon })
@/api/user/index.js
import request from '@/utils/request'
import type {
loginFormData,
loginResponseData,
userInfoReponseData,
} from './type'
enum API {
// 登录
LOGIN_URL = '/admin/acl/index/login',
// 用户信息
USERINFO_URL = '/admin/acl/index/info',
// 退出登录
LOGOUT_URL = '/admin/acl/index/logout',
}
// 登录接口
export const reqLogin = (data: loginFormData) =>
request.post<any, loginResponseData>(API.LOGIN_URL, data)
// 获取用户信息
export const reqUserInfo = () =>
request.get<any, userInfoReponseData>(API.USERINFO_URL)
// 退出登录
export const reqLogout = () => request.post<any, any>(API.LOGOUT_URL)
@/api/user/type.ts
// 请求携带参数类型
export interface loginFormData {
username: string,
password: string
}
// 基础接口返回数据类型
export interface Response {
code: number|string,
message?: string,
ok?: boolean
}
// 登录接口 返回数据类型
export interface loginResponseData extends Response {
data: string
}
// 用户信息接口 返回数据类型
export interface userInfoReponseData extends Response {
data: {
routes: string[]
buttons: string[]
roles: string[]
name: string
avatar: string
}
}
let objectsArray = [
{ a: 1, b: 'one' },
{ a: 2, b: 'two' },
{ a: 3, b: 'three' },
{ a: 2, b: 'anotherTwo' }
];
let valueToRemove = 2; // 这是你想从对象中过滤掉的属性 a 的值
objectsArray = objectsArray.filter(obj => obj.a !== valueToRemove);
console.log(objectsArray);
// 输出: [ { a: 1, b: 'one' }, { a: 3, b: 'three' } ]
imgList = res.data.map(item => {
return{
name: item.imgName,
url: item.imgUrl
}
})
Object.assign
Object.assign()
将所有可枚举的属性的值从一个或多个源对象复制到目标对象(第一个参数),具有相同属性的话,会按顺序进行覆盖,并返回目标对象
let a = reactive({ x: 1, y: 2 })
let b = { y: 3, z: 4 }
let c = { z: 3 }
let newA = Object.assign(a, b, c)
console.log(a, a===newA) // { x: 1, y: 3, z: 3 } true
// 在vue3中,如使用解构赋值的方法,会产生新的对象,会导致失去数据代理
a = {...a, ...b, ...c}
request.ts
@/utils/request.ts
import axios from 'axios'
import { ElMessage } from 'element-plus'
//引入用户相关的仓库
import useUserStore from '@/store/modules/user'
const request = axios.create({
//基础路径(在项目根目录下设置)
baseURL: import.meta.env.VITE_APP_BASE_API,
//超时的时间的设置
timeout: 5000,
})
// 请求拦截器
request.interceptors.request.use((config) => {
if(useUserStore().token){
config.headers.token = useUserStore().token
}
return config
})
// 响应拦截器
request.interceptors.response.use(
(response) => {
// 成功回调,简化数据
return response.data
},
(error) => {
// 失败回调:处理http网络错误
let message = ''
// http状态码
const status = error.response.status
switch (status) {
case 401:
message = 'TOKEN过期'
break
case 403:
message = '无权访问'
break
case 404:
message = '请求地址错误'
break
case 500:
message = '服务器出现问题'
break
default:
message = '网络出现问题'
break
}
//提示错误信息
ElMessage({
type: 'error',
message,
})
return Promise.reject(error)
},
)
export default request
左侧菜单缩放通过仓库变量(true/false)进行管理
刷新:通过v-if
、nextTick
、仓库
实现刷新(销毁重建)
全屏状态:通过document.fullscreenElement
设置全屏状态
自动刷新:window.location.reload()
,用户修改自身账号或密码之后,调用方法自动刷新
展示角色权限:例,后端返回全部权限,其中该角色拥有的权限的select:true
,修改时需要把新的权限对象给后端(父级的id和权限值 + 子级的id和权限值 + …),
提供获取选中的节点的数组,修改完调用刷新方法
一级 | 二级 | 三级 | 四级 |
---|---|---|---|
1、全部数据 | |||
1.1、权限管理 | |||
1.1.1、用户管理 | |||
1.1.1.1、添加用户 | |||
1.1.1.2、删除用户 | |||
1.1.1.3、修改用户 | |||
1.1.2、菜单管理 | |||
1.2、商品管理 |
{
"id": 1,
"name": "全部数据",
"level": 1,
"children": [
{
"id": 7,
"name": "权限管理",
"level": 2,
"children": [
{
"id": 8,
"name": "用户管理",
"level": 3,
"children": [
{
"id": 11,
"name": "添加用户",
"level": 4,
"children": [],
"select": false
},
{
"id": 12,
"name": "删除用户",
"level": 4,
"children": [],
"select": false
}
],
"select": false
},
{
"id": 10,
"name": "菜单管理",
"level": 3,
"children": [],
"select": false
}
],
"select": false
}
],
"select": true
}
const setPermisstion = async (id) => {
let result = await reqAllMenuList(id);
if (result.code == 200) {
// 全部权限
menuArr.value = result.data;
// 拥有的权限
selectArr.value = filterSelectArr(menuArr.value, []);
}
}
const filterSelectArr = (allData, initArr) => {
allData.forEach((item) => {
// 如最后一级的权限的是第四级(遍历完其最低级的权限,即可通过自动判断)
if (item.select && item.level == 4) {
initArr.push(item.id);
}
if (item.children && item.children.length > 0) {
filterSelectArr(item.children, initArr);
}
})
return initArr;
}
在平时写代码的时候,为实现某个功能,感觉自己写的代码很冗余,可以试试将代码交于 ai
,让其优化一下,说不定 JS官方
已经提供了便捷语法糖(如:ES6+新增的语法糖),或者 AI
有更加便捷的实现思路
背景图片
.contaiter{
background: url('@/xxx/xxx.jpg') no-repeat;
backgorund-size: cover;
}