11 个高级 Vue 编码技巧

发表于 3年以前  | 总阅读数:857 次

今天,我为你带来了一个系列精选的知识,以帮助你更快地构建 Vue 应用程序,同时,使它们更高效、更易于大规模管理。

这些高级技巧从何而来?

  • 从我五年的 Vue开发中。
  • 从我用 Vue 2 和 Vue 3 中构建的 20 多个大型客户端项目中。
  • 从有影响力的 Vue 开发人员的平时开发技巧总结中。

虽然,高级 Vue 开发人员会发现这些概念非常有用,但我已经详细概述了如何完成每个概念,因此不会让初学者掉队!

如果你需要任何进一步的解释,请在留言区给我留言,我将很乐意为你提供帮助。如果你有自己的好方法?也可以随时分享这些!

好的,让我们深入了解好东西。

1、动态 SVG 组件

如果你像我一样,喜欢手工制作你的应用程序 — 选择独特的 SVG 图标更适合你的风格指南,并将它们与自定义动画和样式配对。

这样做的问题是要更改 SVG 图像填充的颜色fill,你需要访问模板中内联的 SVG 代码。根据 SVG 的大小,即使只有一两个矢量图像,这也会使你的模板代码快速膨胀。

我已经测试了多种方法和包来访问fill属性,而不会炸毁我的模板,结果证明,添加hover或active CSS 状态以更改 fill SVG 中的一个或多个填充属性的最佳方法,实际上最有效的显而易见的方法——让它成为一个组件!

所以,当我们需要这种功能时,而不是使用这个:

<img src="@/assets/images/myImg.svg" />

相反,我们将在 VSCode 中打开 .svg 图像,然后复制图像的 <svg~ 代码: 旁注:为了确保正在查看正确的图像代码,我建议安装一个名为 Svg Preview 的 VSCode 扩展(如上所示)。这将打开图像的侧面板预览,如果更改 SVG 代码,该预览也会更新。 现在,我们将此代码粘贴到新组件的模板中。我建议将所有 SVG 图标组件放入一个新文件夹中,并相应地命名它们 (components/SVG/IconMoon.vue) 以保持组织有序。一旦我们把它作为一个组件,我们就可以使用 把它放到我们应用程序的任何其他组件或页面中:在上面的示例中,当我将鼠标悬停在 SVG 上时,我只是在要更改的部分上设置一个类(此处称为 .inner),但我也可以直接访问所有 SVG 的属性,因此选项是无穷无尽的,可以使用此方法同时保持其他组件没有 SVG 代码膨胀。如果需要上述的一些扩展功能,你只需要创建一个自定义 SVG 组件。否则,可以像往常一样简单地使用它们,就在图像的 src 中。除了动态图标样式和动画之外,还可以传递道具来更改 SVG 的大小和其他方面(就像任何其他组件一样)。如果你还不熟悉,Vue 文档有一个很好的例子说明如何使用图标来做到这一点。

2、使用 Vue-Router 数据实现更智能的导航链接

你可能没有意识到,但是 Vue-Router 可以像任何其他数据存储一样使用。可以访问应用程序的所有可用路由,添加元数据以使逻辑更智能,甚至可以自动填充导航栏、页面面包屑等内容!然而,这乍一看并不明显,也不能像我们通常访问路由的方式直接访问。这是我们将添加到模板中的基本代码:

v-for="(route, idx) in $router.options.routes.filter(
  (routeItem) => routeItem.name === $route.matched[0].name
)"

使用此 v-for,您可以直接在模板中访问路由器树的所有子路由和单个路由元数据。我最近在一个项目中使用它来生成动态侧边栏导航组件。我在路由器中的某些路由上设置了一个 showInSidebar 元数据属性,我想隐藏在侧边栏中。我还能够自动生成所有侧边栏链接,而无需对每个链接进行编码。以下是我设置路由器路由的方法:

客户端还有一个额外的要求,他们不仅需要从路由器生成这些侧边栏路由,还需要从他们的 API 数据生成这些侧边栏路由。上述方法也以一种干净且可管理的方式解决了这个任务。我能够控制如何直接从路由器显示本地路由以及是否使用 API 提供的路由。我还用它来制作自动面包屑以显示用户的路线历史。在此下方(此处未显示)我还有一个单独的部分,允许侧边栏切换到使用从 API 发送的一组路由。为了触发它,我简单地使用了一个a v-if,如果它们存在就使用它们,否则它将恢复使用来自 vue-router 的路由。

在我的 SideNavbar 组件模板中:

你可能已经注意到了exact-active-class代码:

有了这个,如果路由器链接的目的地与当前路由匹配,Vue 会自动设置一个活动类。这是一个很好的技巧,可以绕过我们用来实现这一点的典型逻辑,并将其缩短为exact-active-class=”className”。我经常将它用于导航栏链接——它既减少了模板大小,又使事情变得更干净。

3、从子组件访问父数据

有时,我们想从父级访问数据,但又不想经历传递 props 的麻烦。如果你只需要从a 的数据对象中快速获取一个值,你可以简单地通过引用parent的数据对象中快速获取一个值,你可以简单地通过引用parent 来完成:

// In parent 
data() {
  return {
    message: 'This is my message'
  }
}

// In child template
<div>{{ $parent.message }}</div> // <-- results in 'This is my message'

如果你想要在组件之间传递数据的更多好方法,Erik Hanchett 有一个很棒的视频,地址:https://www.youtube.com/watch?v=rKWSj3zfBAs&t=46s,你可以去了解一下,还有一些其他选项。

4、简化你的 :class 和 v-if 与逻辑.includes()

凭借 v-directives 的所有功能,很容易忘记我们仍然可以在我们的模板中访问纯 JavaScript 的高级功能。例如,假设你想设置一个类,但仅当用户位于三个特定路线中的任何一个时。当你第一次编写此逻辑时,它可能如下所示:

:class="
  $route.name === 'Home'
  || $route.name === 'Gallery' 
  || $route.name === 'Profile' 
  ? 'classOnlyOnThesePages' 
  : ''
"

然后,你可能会学会像这样缩短它:

:class="{ 
  'classOnlyOnThesePages' : 
  $route.name === 'Home'
  || $route.name === 'Gallery' 
  || $route.name === 'Profile'
}"

但最好的写法绝对是这样的:

:class="{ 
  'classOnlyOnThesePages' : 
  ['Home', 'Gallery', 'Profile'].includes($route.name)
}"

这不仅更具可读性,而且以后也更容易扩展。

5、路线更改时滚动到顶部

当更改路线ni时,Vue 会保持在页面上的当前位置。这有时很有用,但主要是麻烦。如果向下滚动一个长列表,然后转到另一个页面,滚动条将位于新页面的底部,而不是期望的顶部。解决这个问题很简单。只需在 app.js 文件中添加一个 watch: 在每次路由更改后触发滚动到顶部:

// In App.vue
watch: {
    $route() {
      window.scrollTo(0, 0)
    }
  },

6、对 DRYer 代码使用全局实用方法

几乎每个 Vue 项目都有在应用程序的多个地方重用的逻辑。为了保持我们的代码 DRY(不要重复自己)和可管理,我们应该创建一个单独的 utils.js 文件来保存这个重用的逻辑并且可以从任何地方访问。注意:你可能认为 Vuex 非常适合这种情况,但是除非,你想将实用程序方法的结果值存储在 state 中,否则它真的不适合这种情况。在这种情况下,你只想从全局函数返回一个值,单独的 utils.js 文件是与 Vue.prototype 配对的键(如下所示)。但是,如果你仍然想在实用程序中访问 Vuex 状态,可以这样做:import store from '../store',然后执行 store.getters或store.state访问你的 Vuex 状态的属性。 所以,首先我们要设置我们的 utils.jsfile 并添加一个全局方法来将文本复制到用户的剪贴板:

// import store from '../store' <-- To access your Vuex store
import Vue from 'vue' // <-- used for vue-toastification

class Utils {
  // Copy a string to user's clipboard
  copyToClipboard(text) {
    let copyText = document.createElement('input')
    document.body.appendChild(copyText)
    copyText.value = text
    copyText.select()
    document.execCommand('copy')
    document.body.removeChild(copyText)

    // Show toast on copy success
    // (using the vue-toastification package here)
    Vue.$toast.success('Copied address to clipboard: ' + text, {
      position: 'top-right',
      timeout: 3000
    })
  }
}

export default new Utils()

现在,我们有了我们的实用程序方法,我们只需要让它在整个应用程序中都可以访问。我们可以将它们导入到一个组件中并以这种方式使用它们,但我发现让它们在全球范围内可用会产生更清晰、更易读的代码,同时使事情更容易访问。为了使这些函数全局可用,我们将编辑我们的 main.js 文件。Vue 2 和 Vue 3 的设置略有不同,因此,请相应地选择你的风格。在 Vue2 中

// Utils
import Utils from './utils/utils.js'

// Init Global Utils
Vue.prototype.$utils = Utils

在 Vue3 中

// Utils
import Utils from './utils/utils.js'   // <-- import file
const app = createApp(App)
 // Init Global Utils
 app.config.globalProperties.$utils = Utils   // <-- set globally
app.mount('#app')

现在我们可以通过简单地使用以下内容在任何地方访问我们的实用程序方法:

// In template
$utils.copyToClipboard(text)
// In methods
this.$utils.copyToClipboard(text)

7、检测用户是在桌面还是移动设备上

检测用户在哪个平台上的方法经常变化。在评估了你可以执行此操作的多种方法后,我决定使用一个做得很好的包,并且会在这些因素发生变化时保持更新。使用 npm i vue-mobile-detection --save 安装 vue-mobile-detection。在你的 App.vue 文件中,添加一个 mount() 钩子来在你的 Vuex 商店中存储用户的平台。

async mounted() {
    // Detect if user is on Desktop or Mobile platform, then save to store
    this.$isMobile()
      ? this.$store.commit('setPlatform', 'mobile')
      : this.$store.commit('setPlatform', 'desktop')
  },

如果你使用 Vuex,你现在可以为上面的 $store.commit 创建一个mutation,将值设置为 state,然后使用 getter 访问应用程序中任何地方的平台值。 我最近在一个基于区块链的项目中使用了它,在该项目中,了解用户的平台以触发正确的区块链钱包(浏览器扩展钱包或移动应用程序钱包)至关重要,并且它的作用非常吸引人。注意:如果你没有使用 Vuex,你可以使用 localStorage.setItem 将此值存储在用户的 localStorage 中,然后使用 localStorage.getItem 在你的应用程序中的任何位置使用它。

// in App.vue inside of your mounted() hook:
const currentPlatform = this.$isMobile() ? ‘mobile’ : ‘desktop’
localStorage.setItem('platform', currentPlatform)

// Use it anywhere
localStorage.getItem(‘platform’)

8、当用户按下 ENTER 时关注下一个表单输入

表格是一个巨大的 PITA。一些软件包大大减少了这种情况(我最喜欢的是 vue-formulate),但无论你使用什么软件包,或者你是否从头开始编写表单,这都是你的用户会喜欢的概念。如果用户在关注此输入时按下 Enter 键,则会将光标焦点设置到以下输入框:

<input 
 type="text"
 @keyup.enter="$event.target.nextElementSibling.focus()"
/>

9、动态刷新(重新加载)特定组件

有许多边缘情况需要重新加载组件而不影响它所在页面的其余部分。你有时需要强制它使用新属性刷新,或者因为你使用的包在传递新属性时没有按预期更新。

<template>
  <component-to-re-render :key="reloadMe" />
</template>

<script>
export default { 
  data() { 
    return { 
      reloadMe: 0, 
    }
  }; 

  methods: { 
    forceRerender() { this.reloadMe += 1; } 
  } 
}
</script>

当然,如果你想重新加载整个页面,那也很简单:

// Using traditional JS (If you don't have access to $router)
window.location.reload()
// Using vue-router
this.$router.go(0)

10、从父组件调用子组件的方法

通常,父组件通过 props 将数据向下发送给子组件,子组件通过 $emit 事件向上发送给父组件。但是有时我们可能希望从仅存在于子组件内部的父组件内部触发一个方法。听起来很复杂?事实并非如此,Vue refs 提供了完美的解决方案!

// Parent.vue
<template>
  <ChildComponent ref="child" />
</template>


// In Parent.vue's methods
this.$refs.child.methodName()

这是一个更清晰的例子,以防上面的内容太简短:

11、验证组件道具

验证你的道具有两件事。它会告诉你是否向组件传递了不正确的 prop,并且可以轻松查看该组件旨在接受哪些选项。你可以附加任何你想要创建自定义道具验证器的逻辑,但以下可能是你最常用的情况(验证字符串选项):在下面的示例中,我创建了一个在我的应用程序中使用的自定义 Button 组件。请注意,我有变体和类型道具。**注意:**对于自定义 Button 组件,当你实际上是指样式变体时,请确保不要将 type 作为 prop 使用,因为 type 已经是 HTML 按钮上的一个东西,应该是一个单独的 prop 来处理表单提交和重置等事情。对于这些道具中的每一个,我声明我只想接受几个不同的选项。如果我传递了错误的东西,这将帮助我调试我的代码。它还将帮助其他人查看我的代码以了解该组件可以接受哪些选项。

<template>
  <button
    :disabled="disabled"
    :type="type"
    class="btn"
    :class="[
      variant ? `btn-${variant}` : '',
      disabled ? disabled : ''
    ]"
    @click="!disabled ? $emit('clicked') : ''"
  >
  // Use slot to add text to it like a normal button
    <slot />
  </button>
</template>

<script>
export default {
  props: {
    variant: {
      type: String,
      validator: s => ['outline', 'success', 'warning', 'danger'].includes(s)
    },
    type: {
      type: String,
      validator: s => ['submit', 'reset'].includes(s)
    },
    disabled: {
      type: Boolean,
      default: false
    }
  }
}
</script>

<style lang="scss" scoped>
// limited styles here for brevity
.btn {
  line-height: 25px;
  padding: 5px 20px;
}
.disabled {
  border: 2px solid var(--grey-ultralight) !important;
  cursor: default !important;
  background: var(--grey-ultralight) !important;
  color: var(--grey-light) !important;
}
.btn-outline {
  border: 2px solid var(--blue);
  background: var(--bg);
  color: var(--blue);
  &:hover {
    background: var(--blue);
    color: var(--white);
    border: 2px solid var(--blue);
  }
}
.btn-success {
  // Success styles here
}
.btn-warning {
  // Warning styles here
}
.btn-danger {
  // Danger styles here
}
</style>

我希望你喜欢这些技巧并发现它们很有用。如果你有自己的高级技巧,请随时在评论中分享。

本文由哈喽比特于3年以前收录,如有侵权请联系我们。
文章来源:https://mp.weixin.qq.com/s/sdXsIvQG6dwoqn-Gv7oiyA

 相关推荐

刘强东夫妇:“移民美国”传言被驳斥

京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。

发布于:1年以前  |  808次阅读  |  详细内容 »

博主曝三大运营商,将集体采购百万台华为Mate60系列

日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。

发布于:1年以前  |  770次阅读  |  详细内容 »

ASML CEO警告:出口管制不是可行做法,不要“逼迫中国大陆创新”

据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。

发布于:1年以前  |  756次阅读  |  详细内容 »

抖音中长视频App青桃更名抖音精选,字节再发力对抗B站

今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。

发布于:1年以前  |  648次阅读  |  详细内容 »

威马CDO:中国每百户家庭仅17户有车

日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。

发布于:1年以前  |  589次阅读  |  详细内容 »

研究发现维生素 C 等抗氧化剂会刺激癌症生长和转移

近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。

发布于:1年以前  |  449次阅读  |  详细内容 »

苹果据称正引入3D打印技术,用以生产智能手表的钢质底盘

据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。

发布于:1年以前  |  446次阅读  |  详细内容 »

千万级抖音网红秀才账号被封禁

9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...

发布于:1年以前  |  445次阅读  |  详细内容 »

亚马逊股东起诉公司和贝索斯,称其在购买卫星发射服务时忽视了 SpaceX

9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。

发布于:1年以前  |  444次阅读  |  详细内容 »

苹果上线AppsbyApple网站,以推广自家应用程序

据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。

发布于:1年以前  |  442次阅读  |  详细内容 »

特斯拉美国降价引发投资者不满:“这是短期麻醉剂”

特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。

发布于:1年以前  |  441次阅读  |  详细内容 »

光刻机巨头阿斯麦:拿到许可,继续对华出口

据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。

发布于:1年以前  |  437次阅读  |  详细内容 »

马斯克与库克首次隔空合作:为苹果提供卫星服务

近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。

发布于:1年以前  |  430次阅读  |  详细内容 »

𝕏(推特)调整隐私政策,可拿用户发布的信息训练 AI 模型

据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。

发布于:1年以前  |  428次阅读  |  详细内容 »

荣耀CEO谈华为手机回归:替老同事们高兴,对行业也是好事

9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。

发布于:1年以前  |  423次阅读  |  详细内容 »

AI操控无人机能力超越人类冠军

《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。

发布于:1年以前  |  423次阅读  |  详细内容 »

AI生成的蘑菇科普书存在可致命错误

近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。

发布于:1年以前  |  420次阅读  |  详细内容 »

社交媒体平台𝕏计划收集用户生物识别数据与工作教育经历

社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”

发布于:1年以前  |  411次阅读  |  详细内容 »

国产扫地机器人热销欧洲,国产割草机器人抢占欧洲草坪

2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。

发布于:1年以前  |  406次阅读  |  详细内容 »

罗永浩吐槽iPhone15和14不会有区别,除了序列号变了

罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。

发布于:1年以前  |  398次阅读  |  详细内容 »
 目录