老后台里还有一堆用 window.open 打开详情页的代码,Chrome 升级之后新窗口被拦,用户要点两次才出来。
签名是 window.open(url, target, features, replace)。features 是一个逗号分隔的字符串,不是对象,多写一个空格就可能让整段失效。
常用 features
- width、height:新窗口内容区宽高,不含地址栏和边框。
- left、top:距屏幕左上角的位置,用来把窗口摆到中间。
- noopener、noreferrer:挡住新页面通过 window.opener 反向操作原页面,防止钓鱼式的跳转篡改。
- popup:配合宽高,让浏览器按独立窗口处理,而不是塞进新标签页。
旧代码里的 menubar=no、toolbar=no、location=no 现在大多被忽略,现代浏览器统一按标签页渲染,写了也不生效。
被拦截的真正原因
浏览器只允许在用户手势的同步调用栈里开窗。写在 setTimeout、promise.then 或者 ajax 回调里,一律算非用户触发。常见写法是先请求接口拿到地址再打开窗口,这种必然被拦。
绕法是先同步开一个空窗口拿到句柄,等接口回来再改它的 location:
const w = window.open('', '_blank'); fetch(url).then(r => r.json()).then(d => { w.location = d.url; });记得给 w 判空。用户手动禁了弹窗、或者浏览器策略直接拒绝时,它可能是 null,后面再访问就报错。
更省事的替代
单纯新窗口打开详情页,用 a 标签加 target=_blank 和 rel=noopener noreferrer,不写 JS,也不会被拦。window.open 只在需要控制窗口尺寸、或者需要拿到句柄和子页面通信时才值得用。
至于第四参数 replace,只在 target 指向已有窗口时才有意义,用来决定是否替换历史记录,日常基本用不上。