others - Javascript - 如何在不增加历史记录的情况下推送到vue-router?

我有以下顺序发生:

  • 主屏幕

  • 加载屏幕

  • 结果屏幕

在首页,当有人点击按钮时,加载屏幕,通过:

this.$router.push({path:"/loading"});

一旦任务完成,它们就被发送到结果屏幕,通过:

this.$router.push({path:"/results/xxxx"});

问题是,通常他们希望从结果返回主屏幕,但是当他们单击返回时,将被发送到再次加载,然后又将发送回结果,因此陷入了无限死循环,; 无法返回主屏幕。

怎么解决这个问题?

this.$router.push({path:"/loading", addToHistory: false});

将它们发送到路由而不将它添加到历史记录中。

时间:

有一个完美的方法来处理这种情况

你可以使用组件保护控制颗粒级别的route

在代码中进行以下更改

在主屏幕组件中

将这个beofreRoute留在组件选项中,在进入“结果屏幕”之前,将路由设置为仅通过加载屏幕,


beforeRouteLeave(to, from, next) {


 if (to.path =="/result") {


 next('/loading')


 }


 next();


 }, 



加载屏幕组件时

如果路由从结果返回到加载,直接跳到主屏幕,


beforeRouteEnter(to, from, next) {


 if (from.path =="/result") {


 next('/main')


 }


 next();


 },



在加载屏幕中,beforeRouteEnter保护器没有访问这个的权限,因为在确认导航之前,这个新的输入组件尚未创建。 因此,利用这个方法,你将不会从结果屏幕路由触发无限调用,

在结果屏幕组件中

如果你返回,那么它在加载中,直接就跳到主屏幕,


beforeRouteLeave(to, from, next) {


 if (to.path =="/loading") {


 next('/')


 }


 next();


 },




import { Vue, Component, Watch, Prop } from"vue-property-decorator";



@Component<RouteLoader>({


 render(h){


 const rv = (this.$slots.default || [])


 .find(


 child => child.componentOptions


 //@ts-ignore 


 && child.componentOptions.Ctor.extendedOptions.name ==="RouterView"


 )


 if(rv === undefined) 


 throw new Error("RouterView is missing - add <router-view> to default slot")



 const loader = (this.$slots.default || [])


 .find(


 child => child.componentOptions


 //@ts-ignore 


 && child.componentOptions.Ctor.extendedOptions.name === this.loader


 )


 if(loader === undefined) 


 throw new Error("LoaderView is missing - add <loader-view> to default slot")


 const _vm = this 


 const loaderNode = loader.componentOptions && h(


 loader.componentOptions.Ctor,


 {


 on: {


 //"load:start": () => this.loading = true,


"load:stop": () => _vm.loading = false


 },


 props: loader.componentOptions.propsData,


 //@ts-ignore


 attrs: loader.data.attrs


 }


 )


 return this.loading && loaderNode || rv


 }


})


export default class RouteLoader extends Vue {


 loading: boolean = false


 @Prop({default:"LoaderView"}) readonly loader!: string


 @Watch("$route")


 loads(nRoute: string, oRoute: string){


 this.loading = true


 }


}



@Component<Loader>({


 name:"LoaderView",


 async mounted(){



 await console.log("async call")


 this.$emit("load:stop")


 // this.$destroy()


 }


})


export class Loader extends Vue {}



我建议重新考虑这个加载路由。

应用


<shell>


 <router-view></router-view>


</shell>



const routes = [


 { path: '/', component: Main },


 { path: '/results', component: Results }


]



const router = new VueRouter({


 routes,


})



const app = new Vue({


 router


}).$mount('#app')



shell


<div>


 <header>


 <nav>...</nav>


 </header>


 <main>


 <slot></slot>


 </main>


</div>



主页


<section>


 <form>...</form>


</section>



{


 methods: {


 onSubmit() {


 // ...



 this.$router.push('/results')


 }


 }


}



结果页


<section>


 <error v-if="error" :error="error" />


 <results v-if="!error" :loading="loading" :results="results" />


 <loading v-if="loading" :percentage="loadingPercentage" />


</section>



{


 components: {


 error: Error,


 results: Results,


 },


 data() {


 return {


 loading: false,


 error: null,


 results: null,


 }


 },


 created () {


 this.fetchData()


 },


 watch: {


 '$route': 'fetchData'


 },


 methods: {


 fetchData () {


 this.error = this.results = null


 this.loading = true



 getResults((err, results) => {


 this.loading = false



 if (err) {


 this.error = err.toString()


 } else {


 this.results = results


 }


 })


 }


 }


}



这可以通过路由器的beforeEach hook完成。

你需要做的是,当数据加载(在重定向到results组件之前)时,必须全局保存变量或在loading组件中保存变量:


export default {


 name:"results",


 ...


 importantTask() {


 // do the important work...


 localStorage.setItem('DATA_LOADED', JSON.stringify(true));


 this.$router.push({path:"/results/xxxx"});


 }


}



然后应在beforeEach钩子中检查此变量,然后跳到正确的组件:


// router.js...


router.beforeEach((to, from, next) => {


 const dataLoaded = JSON.parse(localStorage.getItem('DATA_LOADED'));


 if (to.name ==="loading" && dataLoaded)


 {


 if (from.name ==="results")


 {


 next({ name:"main"} );


 }


 if (from.name ==="main")


 {


 next({ name:"results"} );


 }


 }


 next();


});



此外,当查询按钮被单击时,请记住将值重置为false组件的:


export default {


 name:"main",


 ...


 queryButtonClicked() {


 localStorage.setItem('DATA_LOADED', JSON.stringify(false));


 this.$router.push({path:"/loading"});


 }


}



另一种选择是使用 History API 。

在结果屏幕中,你可以使用replaceState替换浏览器历史记录中的URL 。

...