当您调用export default sizes(); 时,您实际上是在评估size 函数。您的实用程序文件实际上与此相同:
const size = {
windowWidth: document.documentElement.clientWidth,
windowHeight: document.documentElement.clientHeight,
pageWidth: Math.min(document.body.scrollWidth, contentWidth),
pageHeight: document.body.scrollHeight,
screenWidth: window.screen.width,
screenHeight: window.screen.height,
pageX: document.body.getBoundingClientRect().x,
pageY: document.body.getBoundingClientRect().y,
screenX: -window.screenX,
screenY: -window.screenY - (window.outerHeight-window.innerHeight),
}
export default size;
现在,如果您希望该代码具有反应性,并在每次调用它们时计算变量,您可以使用一个简单的 Accessor Get Method (MDN),它会在您每次访问这些属性时为您评估这些变量:
const size = {
get windowWidth() {
return document.documentElement.clientWidth
},
get windowHeight() {
return document.documentElement.clientHeight
},
get pageWidth() {
let contentWidth = [...document.body.children].reduce(
(a, el) => Math.max(a, el.getBoundingClientRect().right), 0)
- document.body.getBoundingClientRect().x;
return Math.min(document.body.scrollWidth, contentWidth)
},
get pageHeight() {
return document.body.scrollHeight
},
get screenWidth() {
return window.screen.width
},
get screenHeight() {
return window.screen.height
},
get pageX() {
return document.body.getBoundingClientRect().x
},
get pageY() {
return document.body.getBoundingClientRect().y
},
get screenX() {
return -window.screenX
},
get screenY() {
return -window.screenY - (window.outerHeight - window.innerHeight)
},
}
export default size;
通过这样做,您无需在 utils 文件中绑定任何事件处理程序,只需将它们插入您需要的位置即可。
现在您的用户文件将是:
import size from "../../utilities/size";
window.addEventListener('resize', () => {
console.log(size.windowWidth);
})
每次调整窗口大小时,它都会记录一个更改的值!
进一步分析你的代码:
export default sizes();
// is actually the same as
const $tmp = sizes();
export default $tmp;
// Now take a look at what sizes does:
function sizes() {
...
// this evaluates instantly your object
return { windowWidth, ... }
// is the same as
const result = { windowWidth, ... }
return result
// if you now console.log one of those properties, they are fixed numbers
// and they will not be changed inside this function
}
// But, why the object is not changing when the window resizes?
// Every time you call the function, it returns a new instance of the object
function example() { return { } }
let A = size();
let B = size();
console.log(A == B) // false
// Now when you export the constant sizes() you actually
// referring (for example) to the object A
// When you bind the resize event to sizes, it will create another object B
// and change it:
window.addEventListener('resize', example);
// is the same as
window.addEventListener('resize', () => { return {} });
这个 sn-p 试图解释幕后发生的事情:
const btn = document.getElementById('resize');
let OBJECT_ID = 0;
let exportedObject = null;
// emulates sizes()
function makeMyObject() {
OBJECT_ID += 1;
const result = { id: OBJECT_ID };
// first time just print the export value
if (!exportedObject) {
console.log('exported ID:', result.id);
}
// the other times print exported value and current returned value
else {
console.log('exported ID:', exportedObject.id, 'returned ID:', result.id)
}
return result;
}
// emulates window.addEventListener('resize', sizes);
btn.addEventListener('click', makeMyObject);
// emulates export default sizes()
exportedObject = makeMyObject();
<p>Click the button to emulate the <code>winow.resize Event</code></p>
<button id="resize">Emulate</button>