V1.6.1性能优化:高频路径提速与代码精简

v1.6.1 针对 isSameQueryObject.freeze 两处高频执行路径进行优化,减少不必要的计算开销与重复代码

前言

v1.6.0 引入了 params 页面参数传递和查询参数增强方法,功能更加完整。但在实际使用中,路由状态管理存在两处可优化的细节:

  1. isSameQuery 缺少空对象快速路径 --- 每次导航、守卫执行、状态同步都会调用 isSameQuery,而空对象是常见场景
  2. Object.freeze 逻辑分散 --- metaqueryparams 的冻结逻辑分散在 setCurrentRoutecreateStartLocation 中,存在重复代码

v1.6.1 针对这两处进行优化,在不改变任何外部行为的前提下提升性能和可维护性。


一、isSameQuery 空对象快速路径

问题分析

isSameQuery 在路由器内部被高频调用:

  • setCurrentRoute 中判断 fromto 是否相同
  • syncCurrentRoute 中比较当前查询参数
  • isSameRouteLocation 中作为路由位置比较的一部分

原始实现无论查询参数是否为空对象,都会执行 Object.keys()every() 遍历:

typescript 复制代码
// 优化前
private isSameQuery(a: Record<string, string>, b: Record<string, string>): boolean {
    const keysA = Object.keys(a)
    const keysB = Object.keys(b)
    if (keysA.length !== keysB.length) return false
    return keysA.every(key => a[key] === b[key])
}

在空对象场景下(如首页导航、无参数跳转),Object.keys({}) 返回空数组,every 对空数组返回 true,虽然结果正确,但产生了不必要的函数调用开销。

优化方案

添加两层快速路径:

typescript 复制代码
// 优化后
private isSameQuery(a: Record<string, string>, b: Record<string, string>): boolean {
    if (a === b) return true              // 快速路径 1:引用相等
    const keysA = Object.keys(a)
    const keysB = Object.keys(b)
    if (keysA.length !== keysB.length) return false
    if (keysA.length === 0) return true   // 快速路径 2:双空对象
    return keysA.every(key => a[key] === b[key])
}

快速路径 1:引用相等(a === b

ab 是同一个对象引用时,直接返回 true。这种情况在路由状态未变化时(如重复导航检测)经常出现。

快速路径 2:双空对象(keysA.length === 0

keysA.length === keysB.lengthkeysA.length === 0 时,说明两者都是空对象,直接返回 true。避免了 every 对空数组的调用。

性能影响

场景 优化前 优化后
引用相等 Object.keys + every 直接返回 true
双空对象 Object.keys × 2 + every Object.keys × 2 + 长度判断
非空对象 不受影响 不受影响

对于高频调用的导航场景(特别是无参数跳转),减少了不必要的 Object.keysevery 开销。


二、Object.freeze 逻辑集中化

问题分析

v1.6.0 中,metaqueryparams 的冻结逻辑分散在两处:

  1. setCurrentRoute --- 手动冻结 metaquery
  2. createStartLocation --- 手动创建冻结的初始对象
typescript 复制代码
// 优化前:setCurrentRoute 中
function setCurrentRoute(route: RouteLocation): void {
	const from = currentRoute
	currentRoute = {
		path: route.path,
		name: route.name,
		meta: Object.freeze({ ...route.meta }), // 手动冻结
		query: Object.freeze({ ...route.query }), // 手动冻结
		params: Object.freeze({ ...route.params })
		// ...
	}
}

// 优化前:createStartLocation 中
export function createStartLocation(): RouteLocation {
	return {
		path: '/',
		meta: Object.freeze({}), // 手动冻结
		query: Object.freeze({}), // 手动冻结
		params: Object.freeze({}) // 手动冻结
		// ...
	}
}

这种分散存在两个问题:

  1. 重复代码 --- 冻结逻辑在多处重复,后续若需条件冻结(如开发模式跳过冻结),需改多处
  2. 不一致风险 --- 新增字段时容易遗漏冻结

优化方案

将冻结逻辑集中到 createRouteLocation 工厂函数中:

typescript 复制代码
// 优化后:createRouteLocation 中统一冻结
export function createRouteLocation(base: { path: string; name?: string; meta: RouteMeta; query: Record<string, string>; fullPath: string; params?: ParamObject; _synced?: boolean }): RouteLocation {
	const query = Object.freeze(base.query)
	const params: Readonly<ParamObject> = base.params ? Object.freeze({ ...base.params }) : Object.freeze({})
	return {
		path: base.path,
		name: base.name,
		meta: Object.freeze({ ...base.meta }),
		query,
		params
		// ...
	}
}

setCurrentRoutecreateStartLocation 不再手动冻结,统一委托给 createRouteLocation

typescript 复制代码
// 优化后:setCurrentRoute 中
function setCurrentRoute(route: RouteLocation): void {
	const from = currentRoute
	currentRoute = createRouteLocation({
		path: route.path,
		name: route.name,
		meta: { ...route.meta },
		query: { ...route.query },
		fullPath: route.fullPath,
		params: route.params,
		...(route._synced !== undefined && { _synced: route._synced })
	})
	// ...
}

// 优化后:createStartLocation 中
export function createStartLocation(): RouteLocation {
	return createRouteLocation({
		path: '/',
		meta: {},
		query: {},
		fullPath: '/'
	})
}

优化收益

维度 优化前 优化后
冻结逻辑位置 setCurrentRoute + createStartLocation createRouteLocation 一处
代码行数 分散在多处 集中在工厂函数
后续维护 改冻结策略需改多处 只需改 createRouteLocation
一致性 手动保证 工厂函数自动保证

升级指南

v1.6.1 是纯内部优化,完全向后兼容,无需修改任何现有代码即可升级。

本次优化不改变任何公共 API 的行为和签名,所有变更仅限于内部实现细节。如果你正在使用 v1.6.0,直接升级到 v1.6.1 即可享受性能提升。

相关推荐
CodeSheep2 分钟前
OpenJDK 全面禁止 AI 生成代码!
前端·后端·程序员
IT_陈寒29 分钟前
为什么我的Vue组件总是莫名其妙重渲染?
前端·人工智能·后端
乘风gg1 小时前
企业级 AI Coding 的 Harness 工程实战:8 个 Skill 串起全链路
前端·ai编程·claude
lhldsg1 小时前
AI零售系统实战指南:从架构设计到落地部署全解析
java·人工智能·小程序·uni-app·零售
染指11102 小时前
103.RAG-LLamaIndex后端rag问答-聊天接口
前端·javascript·vue.js·人工智能
东风破_10 小时前
danci 项目(三):从 JSON 数据到 AI Coding,真实项目里的数据清洗、Prompt 和工程规范
前端·后端·node.js
东风破_10 小时前
danci 项目(一):从需求到架构,一个单词学习系统为什么会这样设计
前端·后端·node.js
蒲公英eric10 小时前
从客户端到服务端:DVWA DOM 型 XSS 模块完整漏洞分析教程
前端·web安全·ai·xss·dvwa·ai安全
单线程_0110 小时前
从案例分析 Vue3 Tokenizer+Parser 源码三
前端·javascript·vue.js
顶点多余11 小时前
那些在算法中适合巩固的知识点---1
java·前端·算法