Aurelia中repeat.for绑定if.bind在IE/Edge失效问题排查
问题原因与解决方案
1. 核心原因:IE/Edge中repeat.for与if.bind的绑定执行顺序差异
在Aurelia模板里,当你把repeat.for和if.bind放在同一个DOM元素上时,IE和Edge的JS引擎会优先执行if.bind的表达式——此时repeat.for还没完成对当前route变量的上下文绑定,导致传递给showNav的参数直接是undefined。而Chrome/Opera这类现代浏览器的引擎处理顺序更合理,会确保repeat.for先完成变量赋值,再执行if.bind的判断逻辑。
2. 次要但致命的兼容问题:IE不支持Array.prototype.includes
就算第一个问题解决了,你的showNav函数里用到的row.config.role.includes(currentUser)方法,在IE浏览器中根本没有实现,这会直接触发JS错误,进而中断导航菜单的渲染流程。
解决方案
方案一:将过滤逻辑移到TS代码中(推荐)
在ViewModel里提前过滤router.navigation数组,生成仅包含需要显示的路由的新数组,模板直接遍历这个预处理后的数组即可:
// 在你的TS文件中添加过滤后的导航属性 get filteredNavigation() { const currentUserRole = localStorage.getItem("token_role"); return this.router.navigation.filter(route => { // 无角色配置的路由直接显示 if (!route.config.role) { return true; } // 用indexOf替代includes,兼容所有浏览器 return route.config.role.indexOf(currentUserRole) !== -1; }); }
然后修改模板:
<li repeat.for="route of filteredNavigation" style="border: 0px;"> <a href.bind="route.href" if.bind="!route.settings.nav"> ${route.title} </a> <a href="javascript:;" if.bind="route.settings.nav"> ${route.title} </a> <ul if.bind="route.settings.nav" class="dropdown-menu"> <li repeat.for="menu of route.settings.nav" class="ul-menu"> <a href.bind="menu.href">${menu.title}</a> </li> </ul> </li>
这种方式彻底规避了模板绑定顺序的问题,同时让逻辑更集中,便于后续维护。
方案二:用Aurelia的filter管道替代if.bind
如果想保留模板中的过滤逻辑,可以使用Aurelia内置的filter管道,它会确保迭代每个元素时正确传递参数:
<li repeat.for="route of router.navigation | filter:showNav" style="border: 0px;"> <!-- 其余代码保持不变 --> </li>
同时修改showNav函数,替换includes为兼容IE的写法:
showNav(row) { if (!row.config.role) { return true; } const currentUserRole = localStorage.getItem("token_role"); // 用indexOf替代includes,兼容IE return row.config.role.indexOf(currentUserRole) !== -1; }
方案三:为IE添加Array.prototype.includes的Polyfill
如果坚持使用includes方法,可以在项目入口文件中添加Polyfill,让IE支持这个ES6方法:
// 在main.ts或项目入口文件中添加 if (!Array.prototype.includes) { Object.defineProperty(Array.prototype, 'includes', { value: function(searchElement, fromIndex) { if (this == null) { throw new TypeError('"this" is null or not defined'); } const o = Object(this); const len = o.length >>> 0; if (len === 0) { return false; } const n = fromIndex | 0; let k = Math.max(n >= 0 ? n : len - Math.abs(n), 0); function sameValueZero(x, y) { return x === y || (typeof x === 'number' && typeof y === 'number' && isNaN(x) && isNaN(y)); } while (k < len) { if (sameValueZero(o[k], searchElement)) { return true; } k++; } return false; } }); }
内容的提问来源于stack exchange,提问作者Natalija P
相关产品推荐
相关产品推荐

