在 vue-router 中静默更新 url 而不会触发路由
Posted
技术标签:
【中文标题】在 vue-router 中静默更新 url 而不会触发路由【英文标题】:Silently update url without triggering route in vue-router 【发布时间】:2018-12-22 13:13:28 【问题描述】:我需要更新 url 的哈希值,而不是真正触发 vue-router 去那个路由。类似的东西:
router.replace('my/new/path', silent:true)
这会将 url 更新为 .../#/my/new/path
,但路由器本身不会路由到该路径。
有没有优雅的方法来实现这一点?
【问题讨论】:
当你使用这段代码时会发生什么? 这可能是 xy 问题..? @C2486 此代码只是一个优雅解决方案的示例。不幸的是,替换函数中的第二个参数应该是一个onComplete
回调。
@Rainb,可能是。我需要在新应用程序的 iframe 中加载旧应用程序的某些页面。在此 iframe 中导航时,顶部窗口中的 url 哈希应该更新,这样历史记录才能正常工作。由于导航已经在 iframe 中完成,因此不应更新路线本身。一旦用户实际使用地址栏或使用后退/前进导航,应使用正确的 url 更新带有 iframe 的组件。我知道,那里有一些危险信号,但我需要使用 iframe 才能对旧应用程序进行沙箱处理。
【参考方案1】:
无需重新加载页面或刷新 dom,history.pushState
就可以完成这项工作。
在你的组件或其他地方添加这个方法来做到这一点:
addHashToLocation(params)
history.pushState(
,
null,
this.$route.path + '#' + encodeURIComponent(params)
)
因此,在组件中的任何位置,调用 addHashToLocation('/my/new/path')
以将当前位置与 window.history 堆栈中的查询参数一起推送。
要将查询参数添加到当前位置不推送新的历史记录条目,请改用history.replaceState
。
应该与 Vue 2.6.10 和 Nuxt 2.8.1 一起使用。
小心这种方法! Vue Router 不知道 url 发生了变化,所以 pushState 后没有反映 url。
【讨论】:
要将此方法与动态 URL 一起使用,您可以使用resolve()
方法:const href = this.$router.resolve(route); window.history.pushState(, null, href);
【参考方案2】:
Vue 路由器要么打开要么关闭,所以你不能“让它不检测某些 url”。也就是说,如果 Vue 不需要销毁组件并允许您为 url 起别名,它会重用组件。这允许您将 iframe 应用程序中的 url 作为路由中的别名,并在此期间保持相同的组件处于活动状态,从而防止您的 iframe 重新加载。
// router.js
import Comp1 from "./components/Comp1";
import Comp2 from "./components/Comp2";
export default [
path: "/route1",
component: Comp1,
alias: ["/route2", "/route3", "/route4"]
,
path: "/otherroute",
component: Comp2
];
// main.js
import Vue from "vue";
import App from "./App";
import VueRouter from "vue-router";
import routes from "./router";
Vue.config.productionTip = false;
Vue.use(VueRouter);
const router = new VueRouter(
routes
);
/* eslint-disable no-new */
new Vue(
el: "#app",
router,
components: App ,
template: "<App/>"
);
在此示例中,route1
、route2
、route3
和 route4
都将被视为必须加载 route1
,从而使您的组件 Comp1
保持活动状态。
【讨论】:
我不明白这是如何回答这个问题的。如果 iframe 内的 url 发生变化,则没有更新父窗口 url 的代码。如果父 windows url 发生变化,则没有更新 iframe 路由器的代码。 @jansolo OP想要的行为是:(1)父级的url更改,(2)vue路由器不应该更新视图。这里的解决方案是使用别名,以便 Vue 路由器将多个 url 视为同一路由。这个问题不是关于如何使用该信息更新子 iframe,而是如何避免在每次路由更改时重新加载该 iframe。【参考方案3】:如果您尝试更新 url 以显示页面状态(可能类似于 ?search=something
),那么您可以使用这样的技巧。关键思想是使用切换this.respondToRouteChanges
在您的代码更新网址时忽略更改。
更新路由时(例如,在组件中的 vue 方法中)
this.respondToRouteChanges = false;
this.$router.replace(query: search: this.search )
.finally(() =>
this.respondToRouteChanges = true;
);
以及在通常会监视/处理路由更改的组件代码中
setSearch()
if (!this.respondToRouteChanges)
// console.log('ignoring since route changes ignored')
return;
if (this.search !== this.querySearch)
this.search = this.querySearch;
,
watch:
// watch for changes in the url
'querySearch': 'setSearch',
注意respondToRouteChanges
只是在组件中定义为data()
的布尔值
data()
return
respondToRouteChanges: true,
...
querySearch
只是一个返回路由的计算值
querySearch()
return this.$route.query.search || '';
,
【讨论】:
this.$router.replace(query: search: this.search )
无论如何都不会触发重定向...似乎只是 URL 路径的变化。
@foobored - 没有重定向,这是关于 vue-router 的调用。 router.vuejs.org/guide/essentials/…
你是对的 - 感谢您指出这一点。这应该是公认的答案。也许将“在通常会监视/处理更改路由的组件代码中”替换为不那么通用,而更像一个路由器保护示例,例如“在 router.beforeEach / component.beforeRouteUpdate 中”
它当然可以是一个路由器保护,但是,因为这会覆盖默认行为,我认为将它添加到特定组件可能更安全(最不意外的原则)。如果您需要为许多组件执行此操作,那么将其放入路由器中会更有说服力。
另外,我不确定你是否想要一个组件来控制路由器中的一些“respondToRouteChanges”标志——这在状态/责任方面似乎有点混乱。【参考方案4】:
我找到了Silently update url
的方法,但无论如何都会触发路由(但这可能不是问题 - 取决于具体情况)。
在我的情况下,用户可以创建个人资料,例如通过 URL http://localhost:8080/#/user/create/
,提供一些个人资料信息,一旦单击“保存”,用户就会被重定向到他/她创建的个人资料,网址为 http://localhost:8080/#/FaFYhTW9gShk/
,其中用户可以继续编辑个人资料表单。
我该怎么做?
user/create/
页面 (ProfileCreate) 和 FaFYhTW9gShk/
页面 (ProfileDetails) 使用相同的 ProfileUser
组件。
// router.js
const routes = [
path: '/user/create',
component: Profile,
children: [
path: '',
name: 'ProfileCreate',
component: ProfileUser
]
path: '/:profileUrl',
component: Profile,
children: [
path: '',
name: 'ProfileDetails',
component: ProfileUser
]
]
-
在
router.beforeEach
中,我检查是否需要从后端加载数据,还是只需要更改 URL?
// router.js
router.beforeEach((to, from, next) =>
if (!('isProfileLoaded' in to.params))
// load profile from backend and update Vuex
next()
)
-
当点击“保存”按钮时,在
action
我发送数据到后端+调用router.push
// action.js
import router from '@/router'
// Here I send data to backend
// Some code
// Update-URL-Trick
router.push(
name: 'ProfileDetails',
params: profileUrl: profileUrl isProfileLoaded: true
)
就提供isProfileLoaded
而言,Vue 重复使用来自 Vuex 的配置文件数据 + 路由器 silently
更新 URL 重复使用相同的 ProfileUser
组件。
【讨论】:
以上是关于在 vue-router 中静默更新 url 而不会触发路由的主要内容,如果未能解决你的问题,请参考以下文章
vue-router 不渲染组件,但在 this.$router.push 上更改 url
如何在 React Router v5 中更新 URL 并替换历史状态而不重新渲染整个应用程序?