天,我为您带来一系列精选的知识,帮助您更快地构建 Vue 应用程序,同时让它们更高效、更易于大规模管理。
这些高级技巧从何而来?
- 五年的 Vue。
- 在 Vue 2 和 Vue 3 中构建的 20 多个大型客户端项目。
- 来自有影响力的 Vue 开发人员的精选时事通讯技巧。
虽然高级 Vue 开发人员会发现这些概念非常有用,但我已经详细概述了如何完成每个概念,这样初学者就不会落伍了!
如果您需要任何进一步的解释,请发表评论,我很乐意为您提供帮助。有自己的高级战术吗?也可以随意分享这些!
好的,让我们深入研究好东西。
动态 SVG 组件
如果您像我一样,喜欢手工制作您的应用程序 - 选择独特的 SVG 图标以适合您的样式指南,并将它们与自定义动画和样式配对。
这样做的问题是,要更改 SVG 图像的颜色fill
,您需要访问模板中内联的 SVG 代码。根据 SVG 的大小,即使只有一两个矢量图像,这也会使您的模板代码迅速膨胀。
我已经测试了多种方法和包来访问该fill
属性而不会破坏我的模板,事实证明,添加hover
或active
更改 SVG 中的一个或多个fill
属性的 CSS 状态的最佳方法实际上是最明显的方法 - 只是让它成为一个组件!
所以,当我们需要这种功能时,而不是使用这个:
<img src="@/assets/images/myImg.svg" />
相反,我们将.svg
在 VSCode 中打开我们的图像,然后复制<svg~
我们图像的代码:
复制 SVG 代码(使用Svg Preview来预览您的 SVG 图像)
旁注:为确保您查看的是正确的图像代码,我建议安装一个名为Svg Preview的 VSCode 扩展(如上所示)。这将打开图像的侧面板预览,如果您更改 SVG 代码,该预览也会更新。
现在,我们将此代码粘贴到新的component
. 我建议将所有 SVG 图标组件放入一个新文件夹并相应地命名它们以保持井井有条。(components/SVG/IconMoon.vue)
一旦我们将它作为一个组件,我们可以使用以下方法将它放到我们应用程序的任何其他组件或页面中<IconMoon />
:
在浏览器中测试动态 SVG 组件
在上面的示例中,当我将鼠标悬停在 SVG(.inner
此处称为)上时,我只是在要更改的部分上设置了一个类,但我也可以直接访问所有 SVG 的属性,因此您可以选择无穷无尽使用此方法,同时仍使您的其他组件免于 SVG 代码膨胀。
如果您想要上述的一些扩展功能,您只需要创建一个自定义 SVG 组件。否则,可以像往常一样简单地使用它们,就在src
图像中。
除了动态图标样式和动画之外,您还可以传递道具来更改 SVG 的大小和其他方面(就像任何其他组件一样)。如果您还不熟悉,Vue 文档有一个很好的例子来说明如何使用图标来做到这一点。
将Vue-Router
数据用于更智能的导航链接
您可能没有意识到这一点,但Vue-Router
可以像任何其他数据存储一样使用。您可以访问应用程序的所有可用路由、添加元数据以使逻辑更智能,甚至可以自动填充导航栏、页面面包屑等内容!
然而,这乍一看并不明显,也不能以我们通常访问路由的方式直接访问。
这是我们将添加到模板中的基本代码:
从 vue-router 访问所有数据和元数据
有了这个v-for
,您可以children
直接在模板中访问路由器树的所有路由和单个路由元数据。
我最近在一个项目中使用它来生成一个动态侧边栏导航组件。我在要隐藏在侧边栏中的某些路线上设置了showInSidebar
元数据属性。router
我还能够自动生成所有侧边栏链接,而无需对每个链接进行编码。
以下是我设置router
路线的方式:
为面包屑设置子路由和元数据(可以是任何值)
客户端还有一个额外的要求,即他们不仅需要从路由器生成侧边栏路由,还需要从他们的 API 中生成这些侧边栏路由。上述方法也以干净且易于管理的方式解决了此任务。我能够控制如何直接从路由器显示本地路由以及是否使用 API 传递的路由。我还用它来制作自动面包屑来显示用户的路线历史。
在此下方(此处未显示),我还有一个单独的部分,允许侧边栏切换到使用从 API 发送的一组路由。为了触发它,我简单地使用了 a v-if
which 如果它们存在则使用它们,否则它将恢复为使用来自vue-router
.
在我的SideNavbar
组件模板中:
示例用法
您可能已经注意到exact-active-class
代码:
精确的活动类自动突出显示链接
有了这个,如果路由器链接的目的地与当前路由匹配,Vue 会自动设置一个活动类。
这是一个很好的技巧,可以绕过我们用来实现这一点的典型逻辑并将其缩短为exact-active-class=”className”.
我经常将它用于导航栏链接——它既减小了模板大小,又使事情变得更干净。
从子组件访问父数据()
有时我们想从父级访问数据,但不想经历传递道具的麻烦。如果您只需要从 a$parent
的数据对象中获取一个快速值,您可以通过引用简单地做到这一点$parent
:
在孩子中访问父数据
如果您想要更多在组件之间传递数据的好方法,
简化你:class
的v-if
逻辑.includes( )
凭借 v 指令的所有功能,很容易忘记我们仍然可以在模板中访问纯 JavaScript 的高级功能。
例如,假设您想设置 aclass
但仅当用户位于三个特定路径中的任何一个时。当你第一次编写这个逻辑时,它可能看起来像这样:
:class="
$route.name === '首页'
|| $route.name === '画廊'
|| $route.name === '个人资料'
? 'classOnlyOnThesePages'
: ''
"
然后,您可能会像这样学习缩短它:
:class="{
'classOnlyOnThesePages' :
$route.name === '首页'
|| $route.name === '图库'
|| $route.name === '个人资料'
}"
但最好的写法绝对是这样的:
:class="{
'classOnlyOnThesePages' :
['Home', 'Gallery', 'Profile'].includes($route.name)
}"
如果你不喜欢那些让你的模板垃圾的东西,那么可以这样:
<template>
<div :class="classByRoute">
基于路由的变化
</div>
</template>
<script>
computed: {
classByRoute() {
return 'classOnlyOnThesePages' :
['Home', 'Gallery', 'Profile'].includes($route.name)
}
}
<style>
.classOnlyOnThesePages {
background:red;
}
</style>
这不仅更具可读性,而且以后扩展起来也容易得多。
路线更改时滚动到顶部
当您更改路线时,Vue 会保留您在页面上的当前位置。这有时很有用,但大多只是令人讨厌。如果您向下滚动一个长列表,然后转到另一个页面,您的滚动条将位于新页面的底部,而不是您期望的顶部。
解决这个问题很简单。只需在文件中添加一个watch:
在app.js
每次路由更改后触发滚动到顶部的文件:
在每次路线更改时滚动到顶部
对 DRYer 代码使用全局实用程序方法
几乎每个 Vue 项目都有在应用程序的多个地方重用的逻辑。为了使我们的代码保持干燥(不要重复自己)和可管理,我们应该创建一个单独的utils.js
文件来保存这个重用逻辑并且可以从任何地方访问。
注意:您可能认为 Vuex 非常适合这种情况,但除非您想将实用方法的结果值存储在状态中,否则它确实不适合这种情况。如果您只想从全局函数返回一个值,一个单独的utils.js文件是与 Vue.prototype 配对的键(如下所示)。但是,如果您仍然想在实用程序中访问您的 Vuex 状态,您可以这样做:import store from '../store'
,然后执行类似store.getters
或store.state
访问您的 Vuex 状态属性的操作。
好的——首先我们要设置我们的utils.js
文件并添加一个将文本复制到用户剪贴板的全局方法:
全局 Vue 实用程序函数
现在我们有了实用程序方法,我们只需要让它在整个应用程序中都可以访问。我们可以将它们导入组件并以这种方式使用它们,但我发现让它们在全球范围内可用会产生更清晰、更易读的代码,同时让事情更容易访问。
为了使这些函数全局可用,我们将编辑我们的main.js
文件。Vue 2 和 Vue 3 之间的设置略有不同,因此请相应地选择您的风格。
检测用户是在桌面还是移动设备上
检测用户在哪个平台上的方法经常变化。在评估了许多可以做到这一点的方法之后,我决定使用一个做得很好的包,并且当这些因素发生变化时(希望🤞 )会保持更新。
- 安装vue-mobile- detection
npm i vue-mobile-detection --save
- 在您的
App.vue
文件中,添加一个mounted()
挂钩以将用户的平台存储在您的 Vuex 商店中。
App.vue挂载时保存用户平台
如果你使用的是 Vuex,你现在可以为上面创建一个突变$store.commit
,将值设置为state
,然后使用 getter 在你的应用程序中的任何地方访问该platform
值。我最近在一个基于区块链的项目中使用了它,在该项目中,必须了解用户的平台才能触发正确的区块链钱包(浏览器扩展钱包或移动应用程序钱包),它就像一个魅力。
注意:如果您不使用 Vuex,您可以使用 将此值存储在用户的 localStorage 中localStorage.setItem
,然后在您的应用程序中的任何位置使用它localStorage.getItem
当用户按下 ENTER 时,关注下一个表单输入
表格是一个巨大的 PITA。一些软件包(我最喜欢的是 )大大减少了这种情况vue-formulate
,但无论您使用什么软件包,或者如果您是从头开始编写表单,这都是您的用户会欣赏的概念。
如果用户在关注该输入时按下回车键,它会将光标焦点设置到以下输入框:
<input
type="text"
@keyup.enter="$event.target.nextElementSibling.focus()"
/>
以下是我从Michael Thiessen的 Vue 提示时事通讯中学到的一些技巧——我强烈建议您订阅!
动态刷新(重新加载)特定组件
有许多极端情况需要重新加载组件而不影响它存在的页面的其余部分。您有时需要强制它使用新属性进行刷新,或者因为您正在使用的包在传递新属性时未按预期更新。
以编程方式重新加载单个组件
当然,如果你想重新加载整个页面,那也很简单:
this.$router.go(0)
从父组件调用子组件的方法
通常,父组件通过props
子$emit
事件向父组件发送数据。但有时我们可能希望从仅存在于子组件内部的父组件内部触发方法。听起来很复杂?事实并非如此,Vuerefs
提供了完美的解决方案!
这是一个更清晰的示例,以防上述内容过于简短:
使用ref设置 ChildComponent
使用this.$refs访问子方法
只存在于子组件上的方法
验证组件
验证你的道具有两件事。它会告诉您是否向组件传递了不正确的 prop,并且可以轻松查看该组件旨在接受哪些选项。您可以附加要创建自定义道具验证器的任何逻辑,但以下可能是您最常使用的情况(验证字符串选项):
在下面的示例中,我创建了一个Button
在我的应用程序中使用的自定义组件。请注意,我有variant
andtype
道具。
注意:对于自定义 Button 组件,当您真正指的是样式时,请确保不要用作道具,因为它已经是 HTML 按钮上的东西,应该是一个单独的道具来处理诸如表单和.type
variant
type
submit
reset
对于这些道具中的每一个,我都说我只想接受几个不同的选项。如果我传递了错误的东西,这将帮助我调试我的代码。它还将帮助其他任何查看我的代码的人查看该组件可以接受哪些选项。