原本我们只支持浏览器路由,所以我们的代码中有很多代码是通过直接操作window.location来进行路由跳转的,现在我们增加了使用内存路由的嵌入模式,在这个场景中,直接操作window.location到使浏览器的地址改变不再是我们期望的行为。我们希望在不修改代码的情况下使用它。我们希望以嵌入模式重写window.location,而不需要修改代码中的大量调用。
我目前使用的代码如下:
export const proxyLocation = (location: Location) => {
const newLocation = {
get pathname() {
return location.pathname;
},
set pathname(value) {
push(value);
},
get href() {
return patchUrl(location.pathname + location.search);
},
set href(value) {
push(value);
},
get origin() {
return backendServer.url;
},
get search() {
return location.search;
},
replace: function (url) {
replace(url);
},
reload: function () {
replace(window.location.href);
},
};
Object.defineProperty(window, 'location', {
value: newLocation,
writable: false,
configurable: true,
enumerable: true,
});
}
但是这段代码运行时会报错:
TypeError:无法重新定义属性:位置 在Function.defineProperty()
这个问题有解决办法吗?
如果您可以在构建时或使用脚本自动向 JS 文件添加页眉和页脚,您可以定义本地
window
变量,该变量可以是 Proxy
到 globalThis
。这样你就可以覆盖任何你想要的东西。代理可以是全局变量之前包含的一些全局变量,例如:
请注意,代码应包装到 IIFE 或块中
globalThis._$windowProxy = new Proxy(globalThis, {
get(window, prop){
if(prop === 'location') return newLocation;
return Reflect(...arguments);
}
});
const newLocation = {
get pathname() {
return location.pathname;
},
set pathname(value) {
push(value);
},
get href() {
return patchUrl(location.pathname + location.search);
},
set href(value) {
push(value);
},
get origin() {
return backendServer.url;
},
get search() {
console.log('search');
return location.search;
},
replace: function (url) {
replace(url);
},
reload: function () {
replace(window.location.href);
},
};
// the header
(() => {
const window = globalThis._$windowProxy;
const location = window.location
// the code
location.search;
window.location.search;
// the footer
})();
<script type="module">
</script>