阅读 1288

在Vue 3中扩展Vue Router链接

<router-link> 标签是一个很好的工具,可以在你的Vue应用程序的不同页面之间进行导航,但当导航到一个外部链接时,它不是一个工具,为此,你应该使用一个普通的<a> 标签。也许这只是我的问题,但很多时候,我都懒得去理会这其中的差别。其他时候,链接可能是动态的,也就是说,来自数据库或一些用户提供的数据源。在这种情况下,你根本不知道这个链接是外部的还是内部的,而且在每个可能使用这个链接的地方手动做V-if是多么痛苦的事情。

如果只是用一个单一的组件来处理所有的内部和外部链接,那不是很好吗?如果你和我一样,你现在就会这样做。

https://media.giphy.com/media/fH64u5y85GaibsUOvQ/giphy.gif

值得庆幸的是,扩展<router-link> 组件是非常简单的,只需将其包装在你自己的自定义组件中。让我们开始吧!让我们建立一个AppLink 组件,它可以处理任何链接,无论是外部还是内部。

AppLink组件

我们应该做的第一件事是让我们的AppLink组件接受所有与路由器链接相同的道具。为什么?这样我们的组件的 "接口 "就可以模仿Router Link的接口,我们就不会有另一个API需要记住。我们可以通过从Vue Router中导入RouterLink,并将它的props分散到我们组件的props选项中来实现。

// AppLink.vue
<script>
import {RouterLink} from 'vue-router'
export default{
  props:{ ...RouterLink.props }
}
</script>
复制代码

在模板区,我们现在可以创建一个路由器链接标签,并将我们组件的所有道具绑定到它。我们还需要传入插槽,以便标签之间提供的文本和标记将出现在路由器链接中。

// AppLink.vue
<template>
  <router-link v-bind="$props"><slot /></router-link>
</template>
复制代码

就像现在这样,我们已经处理了所有的内部链接。那么,外部链接呢?如前所述,外部链接使用a 标签,所以让我们把它添加到我们的模板中。像路由器链接一样,我们应该传递槽。让我们也把href 绑定到to 属性。

// AppLink.vue
<template>
  <a :href="to"><slot/></a>
  <router-link v-bind="$props"><slot/></router-link>
</template>
复制代码

酷,这就说明了内部链接和外部链接!在这一点上,可能值得注意的是,上述方法只适用于Vue 3,因为它包含了超过1个根元素)。

现在,我们只需要一个条件来告诉我们提供给AppLink的是什么类型的链接。我们可以创建一个名为isExternal 的计算属性来确定这一点。首先,我们要检查我们的to道具的值是否是一个字符串。这是必要的,因为to 道具可能是一个对象,比如有时传递给router-link (即:to="{name:'RouteNameHere'}" )。然后,我们将检查该字符串是否以http 的字符串开始。如果这两个条件都是真的,那么我们就有了自己的一个外部链接。

// AppLink.vue
<script>
export default{
   //...
  computed:{
    isExternal(){
      return typeof this.to === 'string' && this.to.startsWith('http')
    }
  }
}
</script>
复制代码

router-link在模板区,我们现在可以在一个v-if中使用isExternal 计算的道具,当它是a ,否则就显示true

// AppLink.vue
<template>
  <a v-if="isExternal" :href="to"><slot/></a>
  <router-link v-else v-bind="$props"><slot/></router-link>
</template>
复制代码

Learn Vue.js 3 With Vue School

就这样了!我们完成了!在你的应用程序中全局注册该组件后,你现在可以像这样使用它。

// Anywhere in your app
<AppLink :to="[external-or-internal-link]">Click Me</AppLink>
复制代码

Extending Router Links Demo GIF

进一步的灵活性

在新标签页中打开

让我们把AppLink 组件变得更加有用。比方说,我们希望所有的外部链接总是在新的标签页中打开。很简单。只要在组件中的<a> 标签上添加一个target="_blank" ,整个网站的所有外部链接现在都在新标签中打开。

// AppLink.vue
<template>
  <a ... target="_blank"><slot/></a>
  ...
</template>
复制代码

这是你可能希望适用于你网站上大多数外部链接的规则,但如果你希望任何特定的外部链接在同一标签中打开,你可以用html目标属性告诉该链接实例这样做。

<AppLink :to="https://vueschool.io" target="_self">Vue School</AppLink>
复制代码

链接安全

当你使用target="_blank" 属性链接到另一个网站上的一个页面时,你最终会使你的网站暴露在性能和安全问题中。

  • 被链接的页面可能最终与你的页面在同一进程中运行。根据被链接页面的情况,这可能会降低你自己页面的速度。
  • 另一个页面也可以通过window.opener 属性访问原始页面window ,造成安全问题。

关于这个问题的更多细节,请看这个信息性的帖子

解决这个问题的办法是为你所有的外部链接标签提供一个rel="noopener" 属性。但要记住这样做是多么痛苦啊......哦,等等......我们不需要这样做。我们可以在我们的AppLink 组件中添加一次,就可以了。

// AppLink.vue
<template>
  <a ... rel="noopener"><slot/></a>
  ...
</template>
复制代码

外部链接的独特风格

我看到一些网站在其网站上的外部链接的样式与通往他们自己网站上其他地方的链接有点不同。这可以帮助用户更好地了解他们是如何在一个他们原本没有访问过的网站上结束的。它可以是任何东西,从链接旁边的一个微妙的 "外部链接 "图标到链接下面的一个小警告,比如说 "链接到第三方网站"。在我们的组件中实现这一点很简单,只要在我们的模板中的a 标签上添加一个external-link 类,然后用css来改变它的风格,或者添加一个:after sudo-element。你甚至可以为外部链接添加全新的元素,比如一个字体超赞的图标。

// AppLink.vue
// (must have font awesome font included in project)
<template>
  <a ... class="external-link">
    <slot/> <i class="fas fa-external-link-alt"></i>
  </a>
  ...
</template>

<style scoped>
.external-link i {
  font-size: 0.8em;
  opacity: 0.7;
}
</style>
复制代码

External LInk Styled

总结

这只是你可以扩展router-link以适应常见和特殊情况下的需求的一个尝试。另外,由于你的所有链接都被封装在一个单一的组件中,你可以很容易地更新你所有链接的不同方面。你能想到任何其他有用的方法来改进我们的AppLink 组件吗?你是否在你的应用程序中使用类似的方法,并有一些智慧可以分享?请在下面的评论中分享你在扩展Vue Router链接方面的技巧和窍门!

想了解更多关于Vue Router 4的信息,请继续关注我们的免费Vue Router 4课程!注册后,我们会在课程发布后立即通知您!

Learn Vue.js 3 With Vue School

«选择初级Vue.js课程时从哪里开始? 什么是Vue.js的商店?»

文章分类
前端
文章标签