【问题标题】:How to make router-link work with custom link component?如何使路由器链接与自定义链接组件一起使用?
【发布时间】:2018-11-14 21:26:32
【问题描述】:

<base-link>组件

我有一个 Vue 组件 <base-link>,每次我想要一个主播时都会使用它。它主要用于应用特定于链接的样式,以便整个页面上的所有链接在不应用全局样式的情况下看起来都一样。

使<router-link> 使用<base-link>

当使用<router-link> 组件创建链接时,我无法应用这些样式(<base-link> 样式是作用域的),除非<router-link> 使用我的<base-link> 组件来创建锚元素。

幸运的是<router-link> 提供了tag attribute,这似乎正是这样做的。不幸的是,我无法让它工作。我有两个问题:

  1. 我所有的组件都在本地注册(我使用带有 Webpack 的 ES6 模块并在每次需要时在本地导入组件)。 <router-link> 不知道 <base-link> 组件是什么并且无法渲染它。有没有办法注入一个本地组件供<router-link> 使用?

  2. 为了解决问题#1,我认为在全局声明<base-link> 组件就足够了。不幸的是,它仍然不起作用。这次<base-link> 组件被正确渲染,但仍然不能正常工作——对点击事件没有反应。在我看来,问题在于它的 href 属性根本没有设置。有没有办法让<router-link> 正确设置它? (无需手动设置)

问题

如何解决问题 #1 和 #2?我怀疑 #1 可能是不可能的,但我希望至少 #2 是。

代码示例

Here 是一支笔,下面的代码说明了这两个问题。

const router = new VueRouter({
  routes: [
    {
      path: "/",
      component: {
        template: '<p>Homepage template</p>'
      }
    },
    {
      path: "/subpage",
      component: {
        template: '<p>Subpage template</p>'
      }
    }
  ]
});

// Globally registered BaseLink.
Vue.component('BaseLinkGlobal', {
  props: {
    href: String
  },
  template: `
    <a
      :href="href"
      class="BaseLinkGlobal"
    >
      <slot />
    </a>
  `
})

const vue = new Vue({
  el: "#app",
  router,
  components: {
    // Locally registered BaseLink.
    BaseLinkLocal: {
      props: {
        href: String
      },
      template: `
        <a
          :href="href"
          class="BaseLinkLocal"
        >
          <slot />
        </a>
      `
    }
  },
  template: `
    <div>
      <!-- 2 router links. One uses locally registered BaseLink
        -- and the other one a globally registered one. -->
      <nav>
        <router-link
          to="/"
          tag="base-link-local"
        >
          Home
        </router-link>
        <router-link
          to="/subpage"
          tag="base-link-global"
        >
          Subpage
        </router-link>
      </nav>
      <router-view />
    </div>
  `
});

【问题讨论】:

    标签: javascript vue.js vue-component vue-router


    【解决方案1】:

    您可以创建一个基本链接组件,它可以根据需要兼作普通的a 标记或&lt;router-link&gt;

    //Base link
    
    <template>
      <component :is="type" :class="{'base': type === 'a'}" v-bind="$attrs">
        <slot></slot>
      </component>
    </template>
    
    <script>
    export default {
      props: {
        routerLink: {
          type: Boolean,
          default: false
        }
      },
      computed: {
        type() {
          return this.routerLink ? 'router-link' : 'a'
        }
      }
    }
    </script>
    
    <style scopex>
    .base {
      border: 1px solid red;
    }
    </style>
    

    用法

    当您想将其用作普通链接时,请不要提供 router-link 属性,如下所示:

    <base-link>This is a base a tag</base-link>
    

    要将其用作router-link,只需添加router-link 属性和to 属性即可:

    <base-link router-link to="/">This is router-link</base-link>
    

    base-link组件说明:

    • 我们使用 vuejs 提供的component 来渲染a 标签或router-link 基于routerLink 属性的真实性。
    • 如果是普通链接,则添加.base 类,即a
    • 我们绑定$attrs,这使我们可以使组件更加透明,即允许我们使用hrefto 等属性,而无需将它们作为道具传递。

      <base-link href="https://google.com">go to google</base-link>
      

    您可以查看here 以获取有关$attrs 用法的更多说明

    【讨论】:

    • 我认为这是一个非常优雅的解决方案,应该可以解决我的两个问题。如果可行,我将对其进行测试并接受它是一个答案。
    • 我在平板电脑上回答了这个问题,所以无法提供工作笔...请测试一下,如果有任何问题,请告诉我
    • 它有效,非常感谢。我仍然希望简单地将tag="base-link" 传递给&lt;router-link&gt; 会起作用,因为如果需要处理更多(和更复杂)的第三方组件,您的方法可能会失控,但在我目前的情况下,这是一个完美的解决方案.
    【解决方案2】:

    这是为了解决问题 #2

    全局组件不继承路由器链接的事件监听器。您可以通过将v-on="$listeners" 添加到全局组件来使其继承。

    // Globally registered BaseLink.
    Vue.component('BaseLinkGlobal', {
      props: {
        href: String
      },
      template: `
        <a
          :href="href"
          class="BaseLinkGlobal"
          v-on="$listeners"
        >
          <slot />
        </a>
      `
    })
    

    添加后链接有效:https://codepen.io/jacobgoh101/pen/YvqJxL?editors=0010

    【讨论】:

    • 是的,这应该可以解决点击问题。你知道如何在链接中添加href 属性以使其成为有效的锚点吗?
    • 不幸的是,router-link 似乎没有将 href 传递给组件。所以没有。
    猜你喜欢
    • 2019-04-11
    • 2013-10-15
    • 1970-01-01
    • 2021-10-09
    • 2020-06-17
    • 2020-06-20
    • 1970-01-01
    • 1970-01-01
    • 2018-02-26
    相关资源
    最近更新 更多