使用Vue/Nuxt中的后退按钮关闭模式/菜单



当用户点击硬件后退按钮时,我想关闭全屏菜单或模式。我试过这个:

<script>
export default {
data(){
return{
isMenuOpen: false
}
},
methods:{
openMenu(){
this.isMenuOpen = true
document.addEventListener('backbutton', this.closeMenu, false)
},
closeMenu(){
this.isMenuOpen = false
document.removeEventListener('backbutton', this.closeMenu)
}
}
}
</script>

但这并不奏效。有人能帮我吗?

对于这种情况,我的代码与Cosimo的Answer相似,但方法不同

不同之处在于,我保留由数据属性(this.isMenuOpen(触发的模式

data(){
return {
isMenuOpen: false
}
}

所以你可以用它来绑定模态组件

<modal v-model="isMenuOpen" />

我添加了一个watch属性来监视查询

watch: {
$route(newVal, oldVal) {
this.isMenuOpen = newVal.query?.isMenuOpen || false
}
}

然后在你的openMenu方法中,你可以做这个

openMenu(){
this.isMenuOpen = true
this.$router.push({
name : "same-path",
query : {
isMenuOpen : true
}
})
}

但是,在关闭菜单中使用$router.replace而不是$router.push

closeMenu(){
this.isMenuOpen = false
this.$router.replace({
name : "same-path"
})
}



为什么我只对openModal使用$router.push?因为它保存了状态的历史记录,所以每当它打开模态时,它都会告诉浏览器新的状态,而你仍然可以使用返回按钮返回到以前的状态
按下后退按钮后,它将删除查询参数,并触发watch属性

为什么要在closeModal中使用$router.replace?因为它只会替换状态,所以当你按下后退按钮时,它会返回到上一个url页面,而不是打开模式

假设,您可以将模式的状态(打开/关闭(与路由器的属性绑定,也许是您的路由?isMenuOpen=[true/false]

点击[打开模式]而不是进行

this.isMenuOpen = true 

do:

this.$router.push({path:'same-path', query: {isMenuOpen: true}});

模态与绑定

<modal v-model="$router.query.isMenuOpen" />

我相信为vue 3的vue路由器合并的一个RFC包括对模式对话框的更好处理,但现在有一些替代方案可以很好地工作。

必须有一些东西来防止后退按钮的默认行为

这是通过推送一个新路由来完成的——您可以使用另一个答案中描述的查询参数来完成,也可以作为一个新的路由。我选择了使用一条新路线,而且效果很好。

安装@nuxtjs/router extra,并确保按照安装说明将其添加到buildModules中。然后,如果页面位于pages/a.vue,则创建文件pages/a/some-modal.vue(其中some-modal是路径名(:这将创建子路由。在这里,写下模态对话框的内容。在该组件中包括以下内容:

<router>
meta:
showModal: true
</router>

现在,在$route.meta的父页面(将承载模式对话框的页面(中添加一个观察程序。属性装饰器+TypeScript语法:

export default class Index extends Vue {
showModal = false;
@Watch('$route.meta', { immediate: true })
navigate(meta: { showModal?: boolean }) {
this.showModal = !!meta.showModal;
}
back() {
this.showModal = false;
if (window.history.length > 2) {
this.$router.back();
} else {
const pathPaths = this.$route.path.split('/');
pathPaths.pop();
this.$router.push(pathPaths.join('/'));
}
}
}

在您的模板中,包括:

<modal-component v-model="showModal" @close="back">
<NuxtChild :extra-props="extraProps" />
</modal-component>

打开模式对话框:

<nuxt-link to="some-modal" append>Open</nuxt-link>

这不会保留查询参数。然而,创建自定义逻辑来实现这一点应该不会太难。

简短的回答:不要让模态看起来像中的页面

较长的答案:很好的问题,我也有同样的问题,试着把答案通读一遍,这些都是很好的技巧。但每一次黑客攻击都会带来警告,在这种情况下,警告是历史州仍然保留了所有这些推送。因此,虽然你可以打开一个模式(路由器推送(并用后退按钮关闭它一次(使用路由器替换(,但当你打开一个模块并多次关闭它时,你会很快发现你现在必须多次按下后退按钮才能达到你想要的状态,这是因为历史状态现在有更多的状态。我试图找到一种"删除"状态的方法,但从我的发现来看,这是不可能的(甚至$router.go(-1)也有警告(

如果你的模态作为模态清晰可见(周围的透明背景(,这些都不是问题,我在平板电脑/桌面视图中就是这样。在手机上,我试着厚着脸皮,设置了一个与modal相匹配的背景色,它看起来像一个漂亮的齐平新页面,尽管它只是一个modal(像往常一样,右上方有关闭的"x"图标(。

我能想到的最好的解决方案是观察模式状态,如果打开,则添加一个beforeunload函数,该函数将提示用户是否确定要离开。

'modal.isOpen': {
immediate: true,
handler: function(newVal) {
if (newVal) {
window.onbeforeunload = this.beforeWindowUnload;
}
else {
window.onbeforeunload = null;
}
}
}

最新更新