【发布时间】:2019-08-13 15:40:35
【问题描述】:
我想在 url (myapp.com#somevalue) 中传递一个值作为哈希值,并在页面加载时让页面滚动到该项目 - 这正是自互联网开始以来使用哈希片段的行为。我尝试使用 scrollIntoView 但在 iOS 上失败了。然后我尝试取消设置/设置 window.location.hash 但似乎存在竞争条件。仅在延迟超过 600ms 时有效。
我想要一个更可靠的解决方案,并且不想引入不必要的延迟。当延迟太短时,它似乎滚动到所需的项目,但随后滚动到页面顶部。您不会在此演示中看到效果,但它发生在我的实际应用程序 https://codesandbox.io/s/pjok544nrx 第 75 行
componentDidMount() {
let self = this;
let updateSearchControl = hash => {
let selectedOption = self.state.searchOptions.filter(
option => option.value === hash
)[0];
if (selectedOption) {
// this doesn't work with Safari on iOS
// document.getElementById(hash).scrollIntoView(true);
// this works if delay is 900 but not 500 ms
setTimeout(() => {
// unset and set the hash to trigger scrolling to target
window.location.hash = null;
window.location.hash = hash;
// scroll back by the height of the Search box
window.scrollBy(
0,
-document.getElementsByClassName("heading")[0].clientHeight
);
}, 900);
} else if (hash) {
this.searchRef.current.select.focus();
}
};
// Get the hash
// I want this to work as a Google Apps Script too which runs in
// an iframe and has a special way to get the hash
if (!!window["google"]) {
let updateHash = location => {
updateSearchControl(location.hash);
};
eval("google.script.url.getLocation(updateHash)");
} else {
let hash = window.location.hash.slice(1);
updateSearchControl(hash);
}
}
编辑:我追踪了重新渲染页面的 React 行,因此在它已经滚动到我告诉它进入 componentDidMount() 的位置后重置了滚动位置。这是this one。
style[styleName] = styleValue; 在重新渲染页面时,它正在设置反应选择框组件的输入框组件的宽度样式属性。执行此操作之前的堆栈跟踪看起来像
(anonymous) @ VM38319:1
setValueForStyles @ react-dom.development.js:6426
updateDOMProperties @ react-dom.development.js:7587
updateProperties @ react-dom.development.js:7953
commitUpdate @ react-dom.development.js:8797
commitWork @ react-dom.development.js:17915
commitAllHostEffects @ react-dom.development.js:18634
callCallback @ react-dom.development.js:149
invokeGuardedCallbackDev @ react-dom.development.js:199
invokeGuardedCallback @ react-dom.development.js:256
commitRoot @ react-dom.development.js:18867
(anonymous) @ react-dom.development.js:20372
unstable_runWithPriority @ scheduler.development.js:255
completeRoot @ react-dom.development.js:20371
performWorkOnRoot @ react-dom.development.js:20300
performWork @ react-dom.development.js:20208
performSyncWork @ react-dom.development.js:20182
requestWork @ react-dom.development.js:20051
scheduleWork @ react-dom.development.js:19865
scheduleRootUpdate @ react-dom.development.js:20526
updateContainerAtExpirationTime @ react-dom.development.js:20554
updateContainer @ react-dom.development.js:20611
ReactRoot.render @ react-dom.development.js:20907
(anonymous) @ react-dom.development.js:21044
unbatchedUpdates @ react-dom.development.js:20413
legacyRenderSubtreeIntoContainer @ react-dom.development.js:21040
render @ react-dom.development.js:21109
(anonymous) @ questionsPageIndex.jsx:10
./src/client/questionsPageIndex.jsx @ index.html:673
__webpack_require__ @ index.html:32
(anonymous) @ index.html:96
(anonymous) @ index.html:99
我不知道将滚动页面的指令移到哪里。它必须在设置这些样式之后发生,这发生在 componentDidMount() 之后。
编辑:我需要更好地澄清我需要这样做。很抱歉之前没有这样做。
必备
这必须适用于所有常见的桌面和移动设备。
当页面加载时,可能会出现三种情况,具体取决于 #: 后 url 中提供的查询:
- 1) 未提供查询 - 没有任何反应
- 2) 提供了有效查询 - 页面立即滚动到所需的锚点,并且页面标题更改为选项标签
- 3) 提供了无效的查询 - 查询被输入到搜索框中,搜索框被聚焦并且菜单打开,其中的选项受所提供的查询限制,就好像它们已被输入一样。光标位于查询末尾的搜索框,以便用户修改查询。
有效的查询是与其中一个选项的值匹配的查询。无效查询是无效查询。
浏览器的后退和前进按钮应该相应地移动滚动位置。
每当从搜索框中选择一个选项时,页面应立即滚动到该锚点,查询应清除返回占位符“搜索...”,网址应更新,文档标题应更改为选项的标签。
可选但会很棒
选择后,菜单关闭,查询返回“搜索...”,然后
- “搜索”框保留焦点,以便用户可以开始键入另一个查询。下一次单击时,菜单打开,并且选择之前的搜索框查询、菜单的过滤器和菜单滚动位置被恢复(最优选),或者
- 搜索框失去焦点。下一次聚焦时,菜单打开,搜索框查询从选择之前、菜单的过滤器和菜单滚动位置恢复(首选),或
- “搜索”框保留焦点,以便用户可以开始键入另一个查询。先前的查询和菜单滚动位置丢失。
【问题讨论】:
-
可能的解决方案 - stackoverflow.com/questions/3163615/…
-
也许 useEffect 值得一试。据我了解,useEffect 将在渲染提交到屏幕后运行,此时元素已准备好滚动到
标签: reactjs react-select