如何在Vue 3中扩展Vue Router链接详解

前言

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

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

值得庆幸的是,扩展<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" rel="external nofollow"  rel="external nofollow" ><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" rel="external nofollow"  rel="external nofollow" ><slot/></a>
  <router-link v-else v-bind="$props"><slot/></router-link>
</template>

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

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

进一步的灵活性

在新标签页中打开

让我们把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>

总结

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

到此这篇关于如何在Vue 3中扩展Vue Router链接的文章就介绍到这了,更多相关Vue3扩展Vue Router链接内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • vue3使用vue-router的完整步骤记录

    前言 对于大多数单页应用程序而言,管理路由是一项必不可少的功能.随着新版本的Vue Router处于Alpha阶段,我们已经可以开始查看下一个版本的Vue中它是如何工作的. Vue3中的许多更改都会稍微改变我们访问插件和库的方式,其中包括Vue Router. 一.第一步:安装vue-router npm install vue-router@4.0.0-beta.13 二.第二步:main.js 先来对比一下vue2和vue3中main.js的区别:(第一张为vue2,第二张为vue3) 可以

  • vue3.0+vue-router+element-plus初实践

    Vue3中文文档 Vue3.0对比Vue2.x优势 框架内部做了大量的性能优化,包括:虚拟dom,编译模板,Proxy的新数据监听,更小的打包文件等. 新增的组合式API(即Composition API),更适合大型项目的编写方式. 对TypeScript支持更好,去掉this操作,更强大的类型推导. 初始化项目 安装@vue/cli npm install @vue/cli -g 或 yarn global add @vue/cli 创建项目 vue create 项目名 可以选择Vue3的

  • 如何在Vue 3中扩展Vue Router链接详解

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

  • vue框架中props的typescript用法详解

    什么是typescript typescript 为 javaScript的超集,这意味着它支持所有都JavaScript都语法.它很像JavaScript都强类型版本,除此之外,它还有一些扩展的语法,如interface/module等. typescript 在编译期会去掉类型和特有语法,生成纯粹的JavaScript. Typescript 5年内的热度随时间变化的趋势,整体呈现一个上升的趋势.也说明ts越来越️受大家的关注了. 在vue中使用typescript时,需要引入vue-pro

  • Vue 项目中Echarts 5使用方法详解

    目录 前言 创建项目 基本使用 安装 使用方法 柱状图 动态排序柱状图 前言 Echarts 是一个纯JavaScript的图表库,兼容绝大部分的浏览器,底层依赖轻量级的canvas类库ZRender,提供直观,生动,可交互,可高度个性化定制的数据可视化图表. 创建项目 先使用vue-cli创建一个新的项目,配置按照自己的需要选择,默认的也可 vue create vue_echarts cd vue_echarts npm run serve 基本使用 安装 首先安装echarts npm i

  • 如何在Vue.js中实现标签页组件详解

    前言 标签页组件,即实现选项卡切换,常用于平级内容的收纳与展示. 因为每个标签页的内容是由使用组件的父级控制的,即这部分内容为一个 slot.所以一般的设计方案是,在 slot 中定义多个 div,然后在接到切换消息时,再显示或隐藏相关的 div.这里面就把相关的交互逻辑也编写进来了,我们希望在组件中处理这些交互逻辑,slot 只单纯处理业务逻辑.这可以通过再定义一个 pane 组件来实现,pane 组件嵌在 tabs 组件中. 1 基础版 因为 tabs 组件中的标题是在 pane 组件中定义

  • vue项目中main.js使用方法详解

    目录 第一部分:main.js文件解析 第二部分:Vue.use的作用以及什么时候使用 Vue.use是什么?(官方文档) Vue.use()什么时候使用? 补充:关于main.js方便小技巧 总结 第一部分:main.js文件解析 src/main.js是入口文件,主要作用是初始化vue实例并使用需要的插件 在main.js文件中定义了一个vue对象,其中el为实例提供挂载元素 //基础配置 import Vue from 'vue' import App from './App.vue' /

  • Vue.js中数组变动的检测详解

    前言 最近在尝试用Vue.js重构公司的现有业务代码,组件化的设计思路和MVVM的思想让我深深沉迷于其中.但是是踩到了不少坑,就比如这篇文章介绍的数组绑定后的更新检测. 相信大家都知道Observer,Watcher,vm 可谓 Vue 中比较重要的部分,检测数据变动后视图更新的重要环节.在 vue.js中$watch的用法示例 中,我们讨论了如何实现基本的 watch . 接下来,我们来看看如何实现数组变动检测. 例子: // 创建 vm let vm = new Vue({ data: {

  • vue项目中引入vue-datepicker插件的详解

    项目需求中有一个日期选择限制的功能点:今天之前不可选,周末不可选. 传统的input type='date无法做到,所以使用了这个插件来实现功能. 1.引入vue-datepicker loader:npm install vue-datepicker 2.引入moment loader:npm install moment --save 因为vue-datepicker是依赖vue和moment的,所以也应提前 引入moment: 3.在用到该插件的地方引入: import myDatepic

  • Vue配置文件中的proxy配置方式详解

    1. 这里以axios发请求为例 axios.get("/abc/def"); axios.get("/abc/ghi"); axios.post("/abc/jkm"); axios发送的请求是本地的服务器地址拼接上发送的请求,如 http://localhost:8080/abc/def 2. 如果发送的请求都以 /abc 开头,那么我们就可以在proxy中进行服务器代理配置. devServer: { proxy: { "/abc

  • 如何在js代码中消灭for循环实例详解

    前言 这篇文章基于我在公司内部分享会整理而成.欢迎探讨补充. 补充一:看来很多人没看完文章就评论了.我在文章末尾说了,是不写 for 循环,不是不用 for 循环.简单陈述不写 for 循环的理由:for 循环易读性差,而且鼓励写指令式代码和执行副作用.更多参考这篇文章 补充二:回应大家的一些反对意见.本来准备专门写文章回应的,但是没时间,就简短回复,直接扔链接了. 1.for 循环性能最好.回应:微观层面的代码性能优化,不是你应该关注的.我在文章中演示了,对百万级数据的操作,reduce 只比

  • 如何在spring boot中进行参数校验示例详解

    上文我们讨论了spring-boot如何去获取前端传递过来的参数,那传递过来总不能直接使用,需要对这些参数进行校验,符合程序的要求才会进行下一步的处理,所以本篇文章我们主要讨论spring-boot中如何进行参数校验. lombok使用介绍 在介绍参数校验之前,先来了解一下lombok的使用,因为在接下来的实例中或有不少的对象创建,但是又不想写那么多的getter和setter,所以先介绍一下这个很强大的工具的使用. Lombok 是一个可以通过简单的注解形式来帮助我们简化消除一些必须有但显得很

随机推荐