简体   繁体   English

如何禁用 vuejs 路由器链接?

[英]How to disable a vuejs router-link?

I have a single-page app that i've created using vue, and the nav links are all done using router-link tags.我有一个使用 vue 创建的单页应用程序,导航链接都是使用router-link标签完成的。 There are a couple of items in the nav that my boss wants to have in the nav but disabled so that people can get a glimpse of some features that will be coming soon.导航中有几项我的老板希望在导航中具有但已禁用,以便人们可以瞥见即将推出的一些功能。 However I can't figure out how to completely disable a router-link!但是我不知道如何完全禁用路由器链接!

preventDefault does nothing, @click.native.prevent="stopClick()" does nothing (i tried sending it to a function to see if that would prevent the click but it just calls the function and routes anyway despite the prevent), adding a disabled class and setting a css rule of pointer-events: none; preventDefault什么都不做, @click.native.prevent="stopClick()"什么都不做(我尝试将其发送到 function 以查看是否会阻止点击,但它只是调用 function 并尽管阻止但仍然路由),添加disabled class 并设置pointer-events: none; does nothing.什么也没做。 I'm not sure what else to try, is the only way around this to make the disabled links normal text and not router-links?我不确定还有什么可以尝试的,这是使禁用链接成为正常文本而不是路由器链接的唯一方法吗?

You can use您可以使用

<router-link 
  :is="isDisabled ? 'span' : 'router-link'"
  to="/link"
>
  /link
</router-link>

There is still no native solution today.今天仍然没有本地解决方案。 But there is an open PR for this on the vue-router repo: https://github.com/vuejs/vue-router/pull/2098 .但是在 vue-router repo 上有一个公开的 PR: https://github.com/vuejs/vue-router/pull/2098

A workaround is to use:一种解决方法是使用:

<router-link 
  :disabled="!whateverActivatesThisLink" 
  :event="whateverActivatesThisLink ? 'click' : ''"
  to="/link"
>
  /link
</router-link>

There is nothing built in, and probably won't ever be .没有内置任何东西,而且可能永远不会 That said, what worked great for me is to use CSS.也就是说,对我有用的是使用 CSS。

<router-link to="/my-route" :class="{ disabled: someBoolean }" />
.disabled {
    opacity: 0.5;
    pointer-events: none;
}

The opacity makes it look disabled, and the pointer-events: none;不透明度使它看起来被禁用,并且pointer-events: none; makes it so you don't need to also handle :hover styles, or set the cursor style.这样你就不需要处理:hover styles,或者设置cursor样式。

I don't think there's a suitable solution for this problem since router links do not have the disabled attribute, but one trick would be using tag="button" in order to add the required attribute as follows:我认为这个问题没有合适的解决方案,因为路由器链接没有disabled属性,但一个技巧是使用tag="button"来添加所需的属性,如下所示:

<router-link 
     to="/link"
     tag="button"
     :disabled="true"
>
  Link
</router-link>

Method 1: Prevent the click event方法一:防止点击事件

The trick is to handle an event on a capture phase and stop it from propagating up top.诀窍是在捕获阶段处理事件并阻止它向上传播。

<router-link 
  to="/path"
  @click.native.capture.stop
>
  Go to page
</router-link>

Or imperatively:或者命令式:

<router-link 
  to="/path"
  @click.native.capture="handleClick"
>
  Go to page
</router-link>
function handleClick(event) {
  if (passesSomeCheck) event.stopPropagation();
}

This might be very useful if you want to get the resolved path from Vue Router to force a page load without SPA navigation.如果您想从 Vue Router 获取解析的路径以在没有 SPA 导航的情况下强制页面加载,这可能非常有用。

function handleClick(event) {
  if (loadWithoutSpa) {
    event.stopPropagation();
    window.location.href = event.currentTarget.href;
  };
}

Method 2: Change default event to an empty string方法 2:将默认事件更改为空字符串

<router-link 
  to="/path"
  event
>
  Go to page
</router-link>

Method 3: Use an <a> tag方法 3:使用<a>标签

<a :href="$router.resolve(route).href">
  Go to page
</a>

Where route can be exactly the same thing you pass to a to prop on router-link .其中 route 可以与您传递给 a to prop on router-link的东西完全相同。

Just set to="" then the link doesn't go anywhere.只需设置to="" ,则链接不会 go 任何地方。

You can try:你可以试试:

  <router-link
   :event="whateverActivatesThisLink ? 'click' : ''"
  >
  Go to page
  </router-link>

Or write a cleaner code with computed:或者使用计算编写更清晰的代码:

  <router-link
  :event="handleWhatEverEvent"
  >
  Go to page
  </router-link>

computed: {
  handleWhatEverEvent() {
    return this.whateverActivatesThisLink ? 'click' : '';
  }
}

As I had to use <router-link> with custom attribute (and added custom meta to routes), I was able to solve it like this:由于我必须将<router-link>与自定义属性一起使用(并将自定义元添加到路由),因此我能够像这样解决它:

<router-link :to="route.path"
                  custom
                  v-slot="{href, route, navigate, isActive, isExactActive}">
                <a v-bind="$attrs"
                :href="href"
                @click="checkClick($event, navigate, route.meta)">
                ...
                <slot></slot>
            </a>
</router-link>

an then the function然后是 function

checkClick(event: any, navigate: any, meta: { enabled: boolean }) {
            if (meta.enabled) {
                navigate(event);
                return;
            }
            event.preventDefault();
        },

To prevent a click you can directly access to event property of the router-link element like this (and you can use native click to do something else):为了防止点击,您可以像这样直接访问 router-link 元素的事件属性(并且您可以使用原生点击来做其他事情):

<router-link 
:event="clickable ? 'click' : ''" 
@click.native="!clickable ? doOtherThing : ''" > Link </router-link>

You can set route guard per-route您可以为每个路由设置路由保护

const router = new VueRouter({
  routes: [
    {
      path: '/foo',
      component: Foo,
      beforeEnter: (to, from, next) => {
        //here you can set if condition 
        if (conditionTrue) {
          //redirect to other route
          next({path: '/bar'});
        } else {
          next();
        }
      }          
    }
  ]
})

Or you can set globally或者你可以全局设置

routes: [
  {path: '/foo', component: Foo, meta:{conditionalRoute: true}}
]; 

router.beforeEach((to, from, next) => { 
    if (to.matched.some(record => record.meta.conditionalRoute)) { 
        // this route requires condition/permission to be accessed
        if (!checkCondition ) { 
            //check condition is false
            next({ path: '/'});
        } else { 
            //check condition is true
            next();
        } 
    } else { 
        next(); // Don't forget next
    } 
})

For more info: https://router.vuejs.org/guide/advanced/navigation-guards.html#global-before-guards更多信息: https://router.vuejs.org/guide/advanced/navigation-guards.html#global-before-guards

NuxtLink (Vue Router v4) NuxtLink (Vue 路由器 v4)

To me what worked like a charm was the code below.对我来说,像魅力一样起作用的是下面的代码。 This is a real code that I'm using in my application with nuxt and tailwind .这是我在nuxttailwind的应用程序中使用的真实代码。

              <nuxt-link
                v-slot="{ navigate }"
                :to="`lesson/${lesson.lesson_id}`"
                append
                custom
              >
                <button
                  class="focus:outline-none"
                  :class="{
                    'text-gray-500 cursor-default': !lesson.released,
                  }"
                  :disabled="!lesson.released"
                  @click="navigate"
                >
                  {{ lesson.title }}
                </button>
              </nuxt-link>

Idk why nobody tried replace to prop like this:不知道为什么没有人to像这样替换道具:

<router-link :to="disabled ? '' : '/link'">
  Link
</router-link>

But it's 100% work with any version of Vue and vue-router.但它可以 100% 使用任何版本的 Vue 和 vue-router。 Another answers are not working for me with Vue 3 and vue-router 4另一个答案不适用于 Vue 3 和 vue-router 4

Vue Router 4 Vue 路由器 4

You can disable the default behavior of <router-link> which is to route between the different routes of your project's views by adding @click.capture.prevent as shown in the example below:您可以禁用<router-link>的默认行为,即通过添加@click.capture.prevent在项目视图的不同路由之间进行路由,如下例所示:

PaginationComponent.vue分页组件.vue

<template>

  <nav class="mt-4" aria-label="Page navigation sample">
   <ul class="pagination justify-content-center">

    <li v-for="( page, index ) in [1,2,3,4,5]" :key="index" class="page-item">
    
      <router-link :to="{ path: route.path, query: { page: page } }"
                   class="page-link"
                   @click.capture.prevent="changePage(page)"
      >
        <span> {{ page }} </span>
      </router-link>

    </li>

   </ul>
  </nav>

</template>

<script>
import {useRoute} from "vue-router";

export default {
  name: "PaginationComponent"
}

</script>

<script setup>

const route = useRoute();

const changePage = (page) => {
      /**
       * Do whatever you want to do in order update your data, state management or 
       * push to another view.
       */
    
       /* Update the 'page' query parameter silently (without need to refresh the 
          page or update your view).
       */
       window.history.pushState(null, '', `?page=${page}`);

};

</script>

<style>
</style>

Update for Router v4:路由器 v4 更新:

Using a boolean variable status to determine if the link is active or not and passing the link ( ctalink ) as a variable as well.使用boolean变量status来确定链接是否处于活动状态,并将链接 ( ctalink ) 作为变量传递。

Stumbled in here coming from nuxt-link implementation that broke with the update, so from experience this works likewise.在这里偶然发现了与更新中断的nuxt-link实现,因此根据经验,这同样适用。

    <router-link
      v-slot="{ navigate }"
      :to="ctalink"
      custom
    >
      <div @click="status ? navigate(ctalink) : null">
        <div :class="status ? 'text-green' : 'text-gray'"> 
          Click me when active 
        </div>
      </div>
    </router-link>

Source: https://next.router.vuejs.org/api/#router-link-sv-slot来源: https://next.router.vuejs.org/api/#router-link-sv-slot

use div element or span element instead of in combination with @click event使用 div 元素或 span 元素,而不是与 @click 事件结合使用

<div @click="handleRouteNavigation">
your content..
</div>

in script methods define在脚本方法中定义

handleRouteNavigation(){

  if(conditionSatisfied){
      this.$router.push('/mylink')
   }

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM