当前位置: 首页 > news >正文

尚硅谷-硅谷甄选项目记录

一、Vue3

1 基础配置
1.1 @ 路径别名

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/*"]}}
}
1.2 SCSS 全局变量

vite.config.ts

export default defineConfig({// scss全局变量一个配置css: {preprocessorOptions: {scss: {javascriptEnabled: true,additionalData: '@import "./src/styles/variable.scss";',},},},
})
1.3 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资源namesymbolId: 'icon-[dir]-[name]'})]
}

main.ts

// svg插件需要配置代码
import 'virtual:svg-icons-register'

使用

<svg style="width:30px; height:30px"><use xlink:href="#icon-xxx" fill="red"></use>
</svg>
1.4 SVG 全局组件
<svg-icon name="home" color="pihk"></svg-icon>
<!-- @/components/SvgIcon/index.vue --><template><svg :style="{width, height}"><use :xlink:href="prefix + name"></use></svg>
</template><script setup>
import { ref } from 'vue';
const prefix = ref('#icon-')
defineProps({// 名字name: String,// 颜色color:{type: String,defaule: ''},// 宽高width: {type: String,default: '20px'},height: {type: String,default: '20px'}
})
</script>
  • 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)
    
1.5 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)

使用方式

<el-icon> </Edit> </el-icon><el-icon> <component is="Edit"> </el-icon>
2 vue-router路由
2.1 路由跳转
  • 编程式导航

    <script setup lang="ts">import { useRouter } from 'vue-router';const $router = useRouter()const toRoutes = (path) => {$router.push(path)}
    </script>
    
2.2 路由过度
<template><router-view v-slot="{ Component }"><transition name="fade"><component :is="Component" /></transition></router-view>
</template><script setup lang="ts"> </script><style lang="scss" scoped>
// 此为vue3写法,与vue2类名略有不同,根据需求自定义过渡动画
.fade-enter-from {opacity: 0;transform: scale(0);
}.fade-enter-active {transition: all .3s;
}.fade-enter-to {opacity: 1;transform: scale(1);
}
</style>
2.3 路由鉴权

项目当中的各个路由在什么条件下可以访问,什么条件下不可以访问

2.3 element-plus 组件
2.3.1 Menu 菜单折叠图标

问题:在使用 el-menu 菜单的折叠功能时,因为自定义路由和Menu组件,导致图标没有正常显示

解决:将图标组件移出 template 外边

<el-menu-item ><template #title><el-icon> <component :is="meta.icon"></component> </el-icon><span>{{item.children[0].meta.title}}</span></template>
</el-menu-item>
<el-menu-item ><el-icon> <component :is="item.meta.icon"></component> </el-icon><template #title><span>{{item.meta.title}}</span></template>
</el-menu-item>
2.3.2 Menu刷新默认菜单

问题:使用 el-menu 菜单在页面刷新时,已展开的菜单会关闭,

解决:配置 el-menudefault-active 属性,通过 router 将页面路径赋值给他

备注: route 获取页面路径, router 页面跳转,现 $route 以改为宏函数,可以直接在 template 使用,无需引入,若想在 script 中使用,还是得引入

<el-menu :default-active="$route.path"></el-menu>import { useRoute } from 'vue-router'
$route = useRoute()
3 父子组件交互
3.1 defineEmits

vue3 内置 defineEmitsdefinProps 可无需引入直接使用

// son.vue
let $emit = defineEmits(['fn1', 'fn2', ...])const updata = () => {$emit('fn1', { name: '张三', age: '23' })
}// father.vue
<son @fn1="fn1"></son>const fn1 = (name='', age='') => { ... }
3.2 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:() => ({ ... })}
})
3.3 ref
// father.vue
<son ref="son"/>let son = ref(null)
const fn = () => {son.value.fnSon
}// son.vue
const fnSon = () => {// ...
}
defineExpose({ fnSon })

二、TypeScript

1 类型定义
  • @/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: stringavatar: string}
    }
    

三、JavaScrpt

1 对象数组过滤对象
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' } ]
2 对象数组的对象的属性名修改
imgList = res.data.map(item => {return{name: item.imgName,url: item.imgUrl}
})
3 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}
4 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.statusswitch (status) {case 401:message = 'TOKEN过期'breakcase 403:message = '无权访问'breakcase 404:message = '请求地址错误'breakcase 500:message = '服务器出现问题'breakdefault:message = '网络出现问题'break}//提示错误信息ElMessage({type: 'error',message,})return Promise.reject(error)},
)export default request

四、业务实现

  • 左侧菜单缩放通过仓库变量(true/false)进行管理

  • 刷新:通过v-ifnextTick仓库 实现刷新(销毁重建)

  • 全屏状态:通过document.fullscreenElement设置全屏状态

  • 自动刷新:window.location.reload(),用户修改自身账号或密码之后,调用方法自动刷新

  • 展示角色权限:例,后端返回全部权限,其中该角色拥有的权限的select:true,修改时需要把新的权限对象给后端(父级的id和权限值 + 子级的id和权限值 + …), <el-tree> 提供获取选中的节点的数组,修改完调用刷新方法

    一级二级三级四级
    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) => {// 如最后一级的权限的是第四级(遍历完其最低级的权限,即可通过<el-tree>自动判断)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;
    }
    
http://www.xdnf.cn/news/325639.html

相关文章:

  • Facebook隐私设置详解:如何保护你的个人信息
  • 【漫话机器学习系列】245.权重衰减(Weight Decay)
  • SR触发器为什么能够消抖
  • Vue 项目中长按保存图片功能实现指南
  • AI大模型基础设施:NVIDIA GPU和AMD MI300系列的区别
  • android 记录应用内存
  • Scaffold-DbContext详解
  • 如何减少锁竞争并细化锁粒度以提高 Rust 多线程程序的性能?
  • 2025FIC初赛(手机)
  • JAVA中ArrayList的解析
  • Scala语法
  • 【Axure视频教程】中继器表格——未选、半选和全选
  • 代码随想录算法训练营第五十八天| 图论4—卡码网110. 字符串接龙,105. 有向图的完全联通
  • C# WPF 颜色拾取器
  • MySQL OCP 认证限时免费活动​ 7 月 31 日 前截止!!!
  • 多规格直线运动转换至非线性直线的转换方法
  • 【C++进阶】第1课—继承
  • C#管道通讯及传输信息丢失的原因
  • android中背压问题面试题及高质量回答范例
  • 前端面试测试题目(一)
  • 《Python星球日记》 第49天:特征工程与全流程建模
  • 认识tomcat(了解)
  • Android Studio开发安卓app 设置开机自启
  • RISC-V JTAG:开启MCU 芯片调试之旅
  • 鸿蒙知识总结
  • Promise 高频面试题
  • 证件阅读机在景区实名制应用场景的方案
  • 【数据库原理及安全实验】实验六 角色访问控制
  • 探索 C++ 语言标准演进:从 C++23 到 C++26 的飞跃
  • 轨迹预测笔记