好问题。我喜欢在我的商店中有一个 ui 部分。其减速器可能如下所示:
const initialState = {
screenWidth: typeof window === 'object' ? window.innerWidth : null
};
function uiReducer(state = initialState, action) {
switch (action.type) {
case SCREEN_RESIZE:
return Object.assign({}, state, {
screenWidth: action.screenWidth
});
}
return state;
}
其中的动作非常样板。 (SCREEN_RESIZE 是一个常量字符串。)
function screenResize(width) {
return {
type: SCREEN_RESIZE,
screenWidth: width
};
}
最后你将它与一个事件监听器连接在一起。我会将以下代码放在您初始化 store 变量的位置。
window.addEventListener('resize', () => {
store.dispatch(screenResize(window.innerWidth));
});
媒体查询
如果您的应用采用更二元化的屏幕尺寸视图(例如大/小),您可能更愿意使用媒体查询。例如
const mediaQuery = window.matchMedia('(min-width: 650px)');
if (mediaQuery.matches) {
store.dispatch(setLargeScreen());
} else {
store.dispatch(setSmallScreen());
}
mediaQuery.addListener((mq) => {
if (mq.matches) {
store.dispatch(setLargeScreen());
} else {
store.dispatch(setSmallScreen());
}
});
(这次我将省略 action 和 reducer 代码。它们的外观相当明显。)
这种方法的一个缺点是可能会使用错误的值初始化存储,并且我们依赖媒体查询在存储初始化后设置正确的值。没有将媒体查询推入减速器文件本身,我不知道解决这个问题的最佳方法。欢迎反馈。
更新
现在我考虑了一下,您可能可以通过执行以下操作来解决此问题。 (但请注意,我没有对此进行测试。)
const mediaQuery = window.matchMedia('(min-width: 650px)');
const store = createStore(reducer, {
ui: {
largeScreen: mediaQuery.matches
}
});
mediaQuery.addListener((mq) => {
if (mq.matches) {
store.dispatch(setLargeScreen());
} else {
store.dispatch(setSmallScreen());
}
});
更新二:最后一种方法的缺点是ui 对象将替换整个ui 状态,而不仅仅是largeScreen 字段。初始ui 状态的任何其他内容都会丢失。