乐趣区

关于vue.js:在-Vue3中封装一个-routerlinks-支持内外链接都能跳转

作者:Written by Daniel Kelly
译者:前端小智
起源:vueschool

有幻想,有干货,微信搜寻 【大迁世界】 关注这个在凌晨还在刷碗的刷碗智。

本文 GitHub https://github.com/qq449245884/xiaozhi 已收录,有一线大厂面试残缺考点、材料以及我的系列文章。

<router-link> 标签是用于在 Vue 应用程序的不同页面之间跳转,但它不是跳转到内部链接,相同,咱们个别应用 <a> 标签。

兴许只有我这么认为,但很多时候,我无奈跟上这种差别。其余时候,链接可能是动静的,即来自数据库或用户提供的某个数据源。在这种状况下,你基本不晓得链接是内部的还是外部的,在每个可能应用链接的中央手动做一个 v-if 是如许苦楚。

如果只用一个组件来解决所有外部和内部的链接,那不是很好吗?

侥幸的是,扩大 <router-link> 组件非常简单,只需将它包装到咱们本人的定制组件中。Ok,咱们须要构建一个 AppLink 组件来解决链接,无论是内部的还是外部的。

AppLink组件

AppLink组件的 props 要蕴含 router-link 的所有 props。为什么?因为这样咱们组件的“接口”就能够模拟 Router Link 的接口,无需再记住另一个 API。咱们能够通过从 Vue Router 导入 RouterLink 并将其 props 解构到咱们的组件中,如下所示:

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

template 中,创立 router-link 并将 props 传递给它,咱们还须要传入slot,这个能够在 router-link 插入内容。

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

到目前为止,咱们曾经解决了所有外部链接,那内部链接呢?如前所述,内部链接应用 a 标签,因而咱们将其增加到 template 中。像 router link 一样,并将传入的 to 值赋值给 href

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

这样外部和内部链接都有了对应的解决,须要留神的是,以上内容仅实用于 Vue3,因为它蕴含多个根元素。

当初,咱们须要一个计算属性来通知 AppLink 应用哪种链接,咱们先取名为isExternal

首先,咱们查看 prop 的值是否为字符串。这是必须的,因为 to 属性可能是一个对象,例如有时传递到 router-link(即::to="{name:'RouteNameHere'}")。而后,咱们将查字符串是否以http 字符串结尾。如果这两个条件都成立,那么就判断是一个内部链接。

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

有了 isExternal 计算属性之后,咱们就能够应用 v-if 来进行操作,如下所示:

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

功败垂成,咱们能够这样来应用 AppLink 组件。

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

更高的灵活性

在新窗口中关上

咱们能够多增加一些罕用的性能。例如,咱们心愿内部链接都在新窗口中关上,这样很简略就能做到了,只有把 target="_blank" 增加到咱们的 a 标签中即可。

// AppLink.vue
<template>
  <a ... target="_blank"><slot/></a>
  ...
</template>

当然,有些内部链接不须要在新窗口中关上,咱们能够通过指定 target 来通知组件外部关上链接的形式,如下所示:

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

链接平安

当咱们应用 target="_blank" 属性链接到另一个站点上的页面时,最终可能使咱们的站点面临性能和安全性问题:

  • 链接到的页面最终能够在与页面雷同的过程上运行。依据所链接页面的最新状况,这可能会使您本人的页面变慢。
  • 另一个页面也能够通过 window.opener 属性拜访原始页面窗口,从而引起安全隐患。

解决此问题的办法是为所有内部链接标签增加 rel="noopener" 属性,因为咱们曾经封装成组件了,所以只须要在组件外部的 a 标签增加即可。

// AppLink.vue
<template>
  <a ... rel="noopener"><slot/></a>
  ...
</template>

内部链接的独特款式

我见过一些网站在他们的网站上设置的内部链接款式与在他们本人的网站上指向站内的链接有点不同。这能够帮忙用户更好地了解他们要跳转的是内部链接。

这个款式能够是任何货色,如,在第三方链接加个正告的图标,通知用户跳转的危险。在咱们的组件中实现这一点非常简单,只需在模板中的 a 标签中增加一个 external-link 类,而后应用 css 对其进行不同的款式化:

// 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>

这里就把 AppLink 思路讲完了,当然,大家须要新的需要能够自行扩大。

~ 完,我是小智,看海贼王去了,下期见!

编辑中可能存在的 bug 没法实时晓得,预先为了解决这些 bug, 花了大量的工夫进行 log 调试,这边顺便给大家举荐一个好用的 BUG 监控工具 Fundebug。

https://vueschol.io/articles/…

交换

文章每周继续更新,能够微信搜寻 【大迁世界】 第一工夫浏览,回复 【福利】 有多份前端视频等着你,本文 GitHub https://github.com/qq449245884/xiaozhi 曾经收录,欢送 Star。

退出移动版