Starting again myself 03
1.vue中路由传参
query传参(项目管理系统使用,path路径跳转)
可以解决页面刷新数据参数丢失问题
//普通子项目
path = '/proMg/home/projectSubset'
this.$router.push({path,query: { proInfo: row,index:1},
})
//接受参数
this.$route.query.proInfo params传参(路由参数占位符,name跳转)
params 参数在刷新页面后会丢失,而 query 参数会保留
首先修改路由配置(添加参数占位符)
// 路由配置文件
const routes = [{path: '/proMg/home/projectSubset/:proInfo/:index', // 定义params参数name: 'ProjectSubset', // 必须定义路由名称component: ProjectSubsetComponent}
]修改跳转代码(使用name跳转)
// 使用params传参
this.$router.push({name: 'ProjectSubset', // 必须使用name跳转,不能用pathparams: { proInfo: JSON.stringify(row), // 对象需要序列化index: 1 }
})接受参数
// 目标组件中
mounted() {// 接收简单参数const index = this.$route.params.index;// 接收对象参数(需要反序列化)const proInfo = JSON.parse(this.$route.params.proInfo);
}2.vue路由的hash模式与history模式区别
对比(hash-# history刷新404)
hash路由地址有#,history没有
回车刷新,hash会加载对应页面,history会报404错误
history有历史记录,h5新增可修改历史记录
总结(hash兼容性高 historySEO好)
hash 模式:适合兼容性要求高、无需服务器配置、对 URL 美观性和 SEO 无要求的场景(如内部系统、工具应用)。
history 模式:适合面向公众、注重 URL 美观性和 SEO、需要高级路由功能的场景(如官网、电商平台),但需后端配合配置服务器以避免 404 错误。
3.路由拦截
beforeEach(全局守卫)-登录校验,权限过滤,全局导航控制
应用场景:
登录状态校验:需要登录才能访问的页面,统一拦截未登录用户并跳转到登录页。
router.beforeEach((to, from, next) => {// 所有标记了requiresAuth的路由都需要登录验证if (to.meta.requiresAuth && !isLogin()) {next(`/login?redirect=${to.fullPath}`); // 记录目标路径,登录后可跳转回来} else {next();}
});权限过滤:基于用户角色(如普通用户 / 管理员)限制所有路由的访问权限。
router.beforeEach((to, from, next) => {const userRole = getUserRole(); // 获取当前用户角色// 路由元信息中定义了允许访问的角色列表if (to.meta.allowedRoles && !to.meta.allowedRoles.includes(userRole)) {next('/forbidden'); // 无权限时跳转到禁止访问页} else {next();}
});全局导航行为控制:网站维护时拦截所有路由跳转到维护页,或记录所有路由跳转日志用于分析。
router.beforeEach((to, from, next) => {// 网站维护模式if (isMaintenanceMode() && to.path !== '/maintenance') {next('/maintenance');} else {// 记录导航日志logNavigation(from.path, to.path);next();}
});beforeEnter(路由独享守卫)-特定路由需要强化验证
某些路由(如管理员后台)需要额外的权限验证,与其他路由的校验规则不同。
const routes = [{path: '/admin/settings',component: AdminSettings,// 仅对当前路由生效的守卫beforeEnter: (to, from, next) => {// 不仅需要管理员角色,还需要“系统设置”权限if (userRole === 'admin' && hasPermission('system:settings')) {next();} else {next('/no-permission');}}}
];beforeRouteEnter(组件内守卫)-项目管理中进入查看器-存入组件来源返回上一步
beforeRouteEnter(to, from, next) {next(vm => {if (to?.query?.proInfo && 0 < from.fullPath.length) {// 传入参数'proInfo'表示项目入口进入vm.fromPath = from.fullPathsessionStorage.setItem("viewProjectFromPathSession", from.fullPath);}else{vm.fromPath = sessionStorage.getItem("viewProjectFromPathSession");}})},4.动态路由
配置meta属性扩展权限
路由配置中设置meat属性,扩展权限相关字段,用户登录后返回该用户的权限列表,前端根据返回权限动态添加对应的路由。
// 登录成功后,根据权限动态添加路由
const userPermissions = ['user:view', 'product:edit']; // 后端返回的权限
const authRoutes = [{ path: '/admin/user', component: UserList, meta: { permission: 'user:view' } },{ path: '/admin/product/edit', component: ProductEdit, meta: { permission: 'product:edit' } },{ path: '/admin/order/delete', component: OrderDelete, meta: { permission: 'order:delete' } }
];// 筛选出用户有权限的路由,动态添加
authRoutes.forEach(route => {if (userPermissions.includes(route.meta.permission)) {router.addRoute('admin', route); // 添加到“admin”父路由下}
});5.vuex数据刷新丢失
Vuex 的状态存储在内存中,而页面刷新会导致 JavaScript 环境重新初始化导致数据丢失。
利用 localStorage/sessionStorage 持久化存储
Vuex 状态变化时将数据保存到本地存储,在应用初始化时从本地存储恢复状态。
vuex-persistedstate 插件
解决 Vuex 状态持久化的插件,简化了手动操作本地存储的过程。
6.computed(计算属性)与watch(监听属性)区别
| 特性 | computed | watch |
|---|---|---|
| 用途 | 计算派生数据 | 监听数据变化执行副作用 |
| 缓存机制 | 有缓存,依赖不变则不重新计算 | 无缓存,数据变化即触发 |
| 返回值 | 必须有返回值(用于模板渲染) | 无返回值,注重过程 |
| 适用场景 | 简单的同步计算(如拼接、过滤) | 复杂逻辑(如异步请求、耗时操作 |
7.vuex的使用场景以及属性方法
使用场景:存储登录用户信息(用户名、权限、Token),在不同组件间传递和修改数据
| 属性 | 核心作用 | 操作方式 |
|---|---|---|
| State | 存储共享状态变量 | this.$store.state 访问 |
| Getters | state的计算属性(带缓存) | this.$store.getters 访问 |
| Mutations | 提交更新数据方法 | store.commit('方法名') 调用 |
| Actions | 处理异步 / 复杂逻辑 | store.dispatch('方法名') 调用 |
| Modules | 模块化 | 在模块内部定义,通过命名空间访问 |
8.常用的遍历以及使用场景
数组 for循环 forEach map filter find findIndex some every for....of
基础的for循环
const arr = [1, 2, 3, 4];
for (let i = 0; i < arr.length; i++) {console.log(arr[i]);
}forEach(简洁)
arr.forEach((item, index, array) => {console.log(`索引${index}的值是${item}`);
});map(返回新的数组 不改变原数组)
const newArr = arr.map(item => item * 2);
// [2, 4, 6, 8]filter(筛选符合条件的元素)
const evenNumbers = arr.filter(item => item % 2 === 0);
// [2, 4]findIndex(返回第一个符合条件的索引)
const firstEvenIndex = arr.findIndex(item => item % 2 === 0);
// 1some(检查是否有符合条件元素 返回布尔值)
const hasEven = arr.some(item => item % 2 === 0);
// trueevery(检查是否所有元素符合条件 返回布尔值)
const allEven = arr.every(item => item % 2 === 0);
// falsefor...of(es6 可中断遍历)
for (const item of arr) {if (item > 3) break;console.log(item); // 1, 2, 3
}对象遍历 for....in
for...in(遍历对象可枚举属性)
const obj = { name: '张三', age: 20 };
for (const key in obj) {if (obj.hasOwnProperty(key)) { // 过滤原型链属性console.log(`${key}: ${obj[key]}`);}
}总结
需返回新数组:
map需筛选元素:
filter需判断是否存在符合条件元素:
some/every需累计计算:
reduce需中断遍历:
for/for...of对象遍历 for...in
9.过滤器(字母大小写 格式化数字价格 日期)filters
本地过滤器(局部过滤器) 是定义在组件内部的过滤器.
组件选项中定义filters
filters选项声明本地过滤器,对象,键为过滤器名称,值为处理函数
export default {data() {return {message: "hello world",price: 99.9,date: 1697271000000 // 时间戳};},// 定义本地过滤器filters: {// 首字母大写capitalize(value) {if (!value) return "";return value.charAt(0).toUpperCase() + value.slice(1);},// 保留两位小数toFixed2(value) {return Number(value).toFixed(2);},// 格式化日期(简化版)formatDate(timestamp) {const date = new Date(timestamp);return `${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()}`;}}
};模板中使用
通过管道符 | 调用本地过滤器,语法与全局过滤器一致
<template><div><p>原始文本:{{ message }}</p><p>首字母大写:{{ message | capitalize }}</p> <!-- 输出 "Hello world" --><p>原始价格:{{ price }}</p><p>格式化价格:{{ price | toFixed2 }}</p> <!-- 输出 "99.90" --><p>原始时间戳:{{ date }}</p><p>格式化日期:{{ date | formatDate }}</p> <!-- 输出类似 "2023-10-14" --></div>
</template>10.vue强制刷新
应用场景:在某些场景情况下数据更新后视图未及时刷新同步,需要手动触发组件的重新渲染
this.$forceUpdate()
Vue 实例提供的方法,调用后强制当前组件重新渲染(触发beforeUpdate和updated钩子)
// 在组件方法中调用
methods: {handleForceUpdate() {this.$forceUpdate();}
}key属性触发
利用 Vue 的虚拟 DOM diff 算法特性,当组件的key值发生变化时,会销毁旧组件并创建新组件
<template><div :key="componentKey"><!-- 组件内容 --></div>
</template><script>
export default {data() {return {componentKey: 0}},methods: {handleRefresh() {this.componentKey++; // 改变key值,触发重新渲染}}
}
</script>11.git相关命令操作
拉取代码:git pull '远程仓库地址'
查看状态:git status
提交本地缓存区:git add .
提交到本地仓库:git comiit -m '修改描述'
提交到远程仓库:git push '仓库地址' master
创建分支:git branch -b xxx
合并分支:git marge '合并分支的名字'
12.h5新特性以及css3新特性
h5新特性
语义化标签 header footer等
表单增强:email tel number等
多媒体支持:音视频 video audio
canvas与svg:画布与图片
浏览器存储:localstorage sessionstorage
等等
css3新特性
选择器加强:伪类选择器与伪元素选择器
边框背景:边框圆角 阴影等
文本效果:文本阴影以及溢出处理等
多列布局:colums
媒体查询,flex与grid布局,flex: 1 最常见的场景是让子元素 “填充剩余空间”
13.es6的解构赋值
数组的解构赋值-const [a, ...rest] = [1, 2, 3, 4];
// 解构赋值
const [a, ...rest] = [1, 2, 3, 4];
console.log(a); // 1,rest = [2, 3, 4]对象的解构赋值-const { name: uName, ...rest } = user;
// 1. 基本用法:按属性名提取值
const user = {name: '张三',age: 25,gender: '男'
};
const { name: uName, ...rest } = user;
console.log(uName); // 输出: "张三"
console.log(rest); // 输出: { age: 25, gender: '男' }14.es6扩展运算符
扩展运算符数组的复制-const arr3 = [...arr1];
数组是引用类型,直接赋值会导致两个变量指向同一个数组(修改一个会影响另一个)。扩展运算符可以创建数组的浅拷贝(新数组),避免这种问题。
// 原数组
const arr1 = [1, 2, 3];// 直接赋值(引用传递,不是复制)
const arr2 = arr1;
arr2.push(4);
console.log(arr1); // [1, 2, 3, 4](原数组被修改)// 扩展运算符复制(创建新数组)
const arr3 = [...arr1];
arr3.push(5);
console.log(arr1); // [1, 2, 3, 4](原数组不受影响)
console.log(arr3); // [1, 2, 3, 4, 5](新数组独立)扩展运算符数组合并-const mergedArr = [...arr1, ...arr2, 6, ...arr3];
const arr1 = [1, 2];
const arr2 = [3, 4];
const arr3 = [5];// 合并数组
const mergedArr = [...arr1, ...arr2, 6, ...arr3];
console.log(mergedArr); // [1, 2, 3, 4, 6, 5]15.es6中map与set
map-有序键值对
有序数据的遍历展示-复杂键名存储、有序键值对、频繁增删查询
Map会按插入顺序保存键值对,适合需要固定顺序展示的列表(如操作历史、步骤流程)
<ul><li v-for="([time, action], index) in actionLog" :key="index">{{ time }}: {{ action }}</li>
</ul>
export default {data() {return {logEntries: [] // 存储 [timestamp, action] 数组}},computed: {actionLog() {return new Map(this.logEntries) // 保持插入顺序}},methods: {addActionLog(action) {const timestamp = new Date().toISOString()this.logEntries.push([timestamp, action])}}
}set-唯一标识管理,去重操作
利用Set的唯一性特性,快速处理重复数据(如标签、选中项、筛选条件)。
<div v-for="tag in allTags" :key="tag"@click="toggleTag(tag)":class="{ 'selected': tagSet.has(tag) }"
>{{ tag }}
</div>
export default {data() {return {selectedTags: [] // 用数组模拟Set,确保响应式}},methods: {toggleTag(tag) {const index = this.selectedTags.indexOf(tag)if (index === -1) {this.selectedTags.push(tag) // 添加新标签} else {this.selectedTags.splice(index, 1) // 移除标签}}},computed: {// 转为Set方便判断是否包含tagSet() {return new Set(this.selectedTags)}}
} 在数据量大或操作频繁的场景下,其性能优势和代码简洁性会非常明显。项目迁移到 Vue 3,可直接使用reactive原生支持这些数据结构,使用会更便捷。
