我试图通过VueJS中的scrollBehaviour进行滚动以锚定。
通常,我通过以下方式更改当前路由器:
this.$router.push({path : 'componentName', name: 'componentName', hash: "#" + this.jumpToSearchField})
我的VueRouter定义为:
const router = new VueRouter({
routes: routes,
base: '/base/',
mode: 'history',
scrollBehavior: function(to, from, savedPosition) {
let position = {}
if (to.hash) {
position = {
selector : to.hash
};
} else {
position = {x : 0 , y : 0}
}
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(position)
}, 10)
})
}
});
我的路线:
[
{
path: '/settings/:settingsId',
component: Settings,
children: [
{
path: '',
name: 'general',
components: {
default: General,
summary: Summary
}
},
{
path: 'tab1',
name: 'tab1',
components: {
default: tab1,
summary: Summary
}
},
{
path: 'tab2',
name: 'tab2',
components: {
default: tab2,
summary: Summary
}
},
{
path: 'tab3',
name: 'tab3',
components: {
default: tab3,
summary: Summary
}
}
]
},
{
path: '/*',
component: Invalid
}
];
假设我在 tab1 组件上,我想跳到在 tab3 组件上锚定<< strong> test ”
在 router.push()之后,我看到scrollBehavior被触发,组件从 tab1 切换到 tab3 ,并且URL也被更改(例如 http://localhost:8080/tab1 到 http://localhost:8080/tab3#test ),但窗口位置不在锚的位置,而只是在窗口顶部。
当然,我在tab3组件上有id =“ test”的文本区域
有什么问题吗?
答案 0 :(得分:6)
使用 {left: 0, top: 0}
而不是 {x: 0, y: 0}
就可以了。
我认为这是 Vue 文档中的一个错误,因为如果您在控制台上登录 savedPosition
,您将看到 {left: 0, top: 0}
,当您像这样更改 {x: 0, y: 0}
时,一切都会完美运行。< /p>
答案 1 :(得分:1)
这在 Vue 3 中对我有用:
const router = createRouter({
history: createWebHistory(process.env.BASE_URL),
routes,
scrollBehavior(to, from, SavedPosition) {
if (to.hash) {
const el = window.location.href.split("#")[1];
if (el.length) {
document.getElementById(el).scrollIntoView({ behavior: "smooth" });
}
} else if (SavedPosition) {
return SavedPosition;
} else {
document.getElementById("app").scrollIntoView({ behavior: "smooth" });
}
},
});
答案 2 :(得分:1)
好吧,我参加聚会有点晚了,但最近偶然发现了一个相当相似的问题。我无法使我的 scrollBehavior
与锚一起工作。我终于找到了根本原因:我的 <router-view>
被包裹在一个 <transition>
中,从而延迟了锚点的渲染/安装,如下所示:
<Transition name="fade-transition" mode="out-in">
<RouterView />
</Transition>
发生的事情是:
<router-view>
过渡开始。新内容尚未安装<router-view>
已正确安装/渲染没有转换,scrollBehavior return {selector: to.hash}
工作正常,因为内容立即安装,并且锚点存在于页面中。
因为我不想删除过渡,所以我制定了一个解决方法,它会定期尝试获取锚元素,并在呈现/找到后滚动到它。它看起来像这样:
function wait(duration) {
return new Promise((resolve) => setTimeout(resolve, duration));
}
async function tryScrollToAnchor(hash, timeout = 1000, delay = 100) {
while (timeout > 0) {
const el = document.querySelector(hash);
if (el) {
el.scrollIntoView({ behavior: "smooth" });
break;
}
await wait(delay);
timeout = timeout - delay;
}
}
scrollBehavior(to, from, savedPosition) {
if (to.hash) {
// Required because our <RouterView> is wrapped in a <Transition>
// So elements are mounted after a delay
tryScrollToAnchor(to.hash, 1000, 100);
} else if (savedPosition) {
return savedPosition;
} else {
return { x: 0, y: 0 };
}
}
答案 3 :(得分:0)
查看此功能的vue-router支持:
https://router.vuejs.org/guide/advanced/scroll-behavior.html
scrollBehavior (to, from, savedPosition) {
if (to.hash) {
return {
selector: to.hash
// , offset: { x: 0, y: 10 }
}
}
}
答案 4 :(得分:0)
我无法获得与此工作相关的任何git解决方案,这实在令人沮丧。
最终为我工作的是以下内容:
const router = new Router({
mode: 'history',
routes: [...],
scrollBehavior() {
document.getElementById('app').scrollIntoView();
}
})
我将VueJs应用程序安装到#app,因此可以确定它可以选择。
答案 5 :(得分:0)
如果jQuery可用,这也可以工作:
scrollBehavior (to, from, savedPosition) {
$('#selector-in-element-with-scroll').scrollTop(0)
}
答案 6 :(得分:0)
我有一个类似的问题,这是由于我在网上找到了一些例子而引起的。在我的情况下,问题在于该项目尚未渲染。我正在进行过渡的离开后事件,尽管它没有引发任何错误,但它没有滚动到该元素。我将其更改为过渡的enter事件,现在可以使用。
我知道问题没有提到过渡,因此在这种情况下,您可以尝试使用nextTick而不是setTimeout来确保元素已呈现。
答案 7 :(得分:0)
对于正在寻求有效解决方案的任何人,我将为此问题分享2美分。接听Sweet Chilly Philly的答案,这是唯一对我有用的方法,我添加了相关代码以使URL哈希也能正常工作:
scrollBehavior: (to, from, savedPosition) => {
if (to.hash) {
Vue.nextTick(() => {
document.getElementById(to.hash.substring(1)).scrollIntoView();
})
//Does not work but it's the vue way
return {selector: to.hash}
}
if (savedPosition) {
//Did not test this but maybe it also does not work
return savedPosition
}
document.getElementById('app').scrollIntoView();
//Does not work but it's the vue way
return {x: 0, y: 0}
}
我不会对Vue.nextTick进行详细介绍(您可以阅读更多关于here的信息),但是当路由已经更改并且该元素所引用的元素下一次DOM更新后,它会运行代码。哈希已经准备好,可以通过document.getElementById()进行访问。
答案 8 :(得分:0)
以上建议都不适合我:
我发现并且非常适合我的情况是这样的:
App.vue
<transition @before-enter="scrollTop" mode="out-in" appear>
<router-view></router-view>
</transition>
methods: {
scrollTop(){
document.getElementById('app').scrollIntoView();
},
}
答案 9 :(得分:0)
如果默认滚动查看不起作用,您可以通过以下方式获得相同的结果:
// src/rouer/index.js
[ //routes
{
path: '/name',
name: 'Name',
component: () => import('../component')
},
.
.
.
]
createRouter({
history: createWebHistory(process.env.BASE_URL),
routes,
scrollBehavior (to, from, SavedPosition) {
if (to.hash) {
const el = window.location.href.split('#')[1]
if (el.length) {
document.getElementById(el).scrollIntoView({ behavior: 'smooth' })
}
} else if (SavedPosition) {
return SavedPosition
} else {
document.getElementById('app').scrollIntoView({ behavior: 'smooth' })
}
}
})
答案 10 :(得分:0)
你为什么要返回一个承诺?
文档只返回位置:https://router.vuejs.org/guide/advanced/scroll-behavior.html
所以应该改为:
scrollBehavior: function(to, from, savedPosition) {
let position = {}
if (to.hash) {
position = {
selector : to.hash
};
} else {
position = {x : 0 , y : 0}
}
return position;
}
我没有调试 to.hash
是否按您的预期工作,但这里的函数调用本身似乎不正确。