vue开发技巧

娜娜 2021-10-13 15:47:09
Vue.js


1. 将一个 prop 限制在一个类型的列表中

使用 prop 定义中的 validator 选项,可以将一个 prop 类型限制在一组特定的值中。

export default {
name: 'Image',
props: {
src: {
type: String,
},
style: {
type: String,
validator: s => ['square', 'rounded'].includes(s)
}
}
};

这个验证函数接受一个prop,如果prop有效或无效,则返回true或false。

当单单传入的 true 或 false 来控制某些条件不能满足需求时,我通常使用这个方法来做。

按钮类型或警告类型(信息、成功、危险、警告)是最常见的用法、、。颜色也是一个很好的用途。

2. 默认内容和扩展点

Vue中的槽可以有默认的内容,这使我们可以制作出更容易使用的组件。

<button class="button" @click="$emit('click')">
<slot>
<!-- Used if no slot is provided -->
Click me
</slot>
</button

我最喜欢使用默认槽,就是用它们来创建扩展点。

我们可以取组件的任何部分,将其封装在一个插槽中,在外面我们可以用想要的任何内容覆盖组件的该部分。默认情况下,它仍然会按照原来的方式工作,但这样做会有了更多的选项

<template>
<button class="button" @click="$emit('click')">
<slot>
<div class="formatting">
{{ text }}
</div>
</slot>
</button>
</template>

现在我们可以用许多不同的方式使用这个组件。简单的、默认的方式,或者自定义的方式。

<!-- Uses default functionality of the component -->
<ButtonWithExtensionPoint text="Formatted text" />
<ButtonWithExtensionPoint>
<div class="different-formatting">
Do something a little different here
</div>
</ButtonWithExtensionPoint>

3. 使用引号来监听嵌套属性

你可能不知道这一点,我们可以通过使用引号轻松地直接监听嵌套值:

watch {
'$route.query.id'() {
// ...
}
}

4. 知道何时使用v-if(以及何时避免使用)

与其使用v-if,有时使用v-show来代替,会有更高的性能。

<ComplicatedChart v-show="chartEnabled" />

当v-if被打开或关闭时,它将创建并完全销毁该元素。相反,v-show将创建该元素并将其留在那里,通过设置其样式为display: none来隐藏它。

如果你要切换的组件的渲染成本很高,那么这样做会更有效率。

反过来说,如果不需要立即执行昂贵的组件件,可以使用v-if,这样它就会跳过渲染它,而使页面的加载速度更快一些。

5. 单个作用域插槽的简写(不需要 template 标签)

限定范围的插槽非常有趣,但为了使用它们,您还必须使用许多模板标记。

幸运的是,有一个简写可以让我们摆脱它,但只有在我们使用单个作用域槽的情况下。

普通写法:

<DataTable>
<template #header="tableAttributes">
<TableHeader v-bind="tableAttributes" />
</template>
</DataTable>

不使用 template:

<DataTable #header="tableAttributes">
<TableHeader v-bind="tableAttributes" />
</DataTable>

简单、直截了当,令人赞叹不已。

6. 有条件地渲染插槽

我们先来看如何做,然后在讨论为什么想隐藏插槽。

每个Vue组件都有一个特殊的$slots对象,里面有你所有的插槽。默认槽的键是default,任何被命名的槽都使用其名称作为键。

const $slots = {
default: <default slot>,
icon: <icon slot>,
button: <button slot>,
};

但这个$slots对象只有适用于该组件的插槽,而不是每一个定义的插槽。

拿这个定义了几个插槽的组件来说,包括几个命名的插槽。

<!-- Slots.vue -->
<template>
<div>
<h2>Here are some slots</h2>
<slot />
<slot name="second" />
<slot name="third" />
</div>
</template>

如果我们只对组件应用一个插槽,那么只有那个插槽会显示在我们的$slots对象中。

<template>
<Slots>
<template #second>
This will be applied to the second slot.
</template>
</Slots>
</template>

$slots = { second: <vnode> }
我们可以在我们的组件中使用这一点来检测哪些插槽已经被应用到组件中,例如,通过隐藏插槽的包装元素。

<template>
<div>
<h2>A wrapped slot</h2>
<div v-if="$slots.default" class="styles">
<slot />
</div>
</div>
</template>

现在,应用样式的包装器div只有在我们用某些东西填充这个插槽时才会被渲染。

如果不使用v-if,那么如果没有插槽,就会得到一个空的不必要的div。根据div的样式,这可能会打乱我们的布局,让界面看起来很奇怪。

那么,为什么我们希望能够有条件地渲染插槽呢?

使用条件插槽的主要原因有三个:

  • 当使用封装的div来添加默认样式时
  • 插槽是空的
  • 如果我们将默认内容与嵌套槽相结合
    例如,当我们在添加默认样式时,我们在插槽周围添加一个div:
<template>
<div>
<h2>This is a pretty great component, amirite?</h2>
<div class="default-styling">
<slot >
</div>
<button @click="$emit('click')">Click me!</button>
</div>
</template>

然而,如果父组件没有将内容应用到该插槽中,我们最终会在页面上渲染出一个空的div。

<div>
<h2>This is a pretty great component, amirite?</h2>
<div class="default-styling">
<!-- 槽中没有内容,但这个div 仍然被渲染。糟糕 -->
</div>
<button @click="$emit('click')">Click me!</button>
</div>

解决方法就是像上面讲的一样,多个条件判断,就行啦。

7. 如何监听一个插槽的变化

有时我们需要知道插槽内的内容何时发生了变化。

<!-- 可惜这个事件不存在 -->
<slot @change="update" />

不幸的是,Vue没有内置的方法让我们检测这一点。

MutationObserver接口提供了监视对DOM树所做更改的能力。它被设计为旧的Mutation Events功能的替代品,该功能是DOM3 Events规范的一部分。
export default {
mounted() {
// 当有变化时调用`update`
const observer = new MutationObserver(this.update);
// 监听此组件的变化
observer.observe(this.$el, {
childList: true,
subtree: true
});
}
};

8. 将局部和全局的 style混合在一起

通常情况下,在处理样式时,我们希望它们能被划分到一个单独的组件中。

<style scoped>
.component {
background: green;
}
</style>

不过,如果需要的话,也可以添加一个非作用域样式块来添加全局样式

<style>
/* 全局 */
.component p {
margin-bottom: 16px;
}
</style>
<style scoped>
/* 在该组件内有效 */
.component {
background: green;
}
</style>

但要小心,全局样式是危险的,难以追踪。但有时,它们是一个完美的逃生舱口,正是你所需要的

9. 重写子组件的样式--正确的方法

Scoped CSS在保持内容整洁方面非常棒,而且不会将样式引入应用的其他组件中。

但有时你需要覆盖一个子组件的样式,并跳出这个作用域。

Vue有一个 deep 选择器:

<style scoped>
.my-component >>> .child-component {
font-size: 24px;
}
</style>

注意:如果你使用像SCSS这样的CSS预处理器,你可能需要使用/deep/来代替。

10. 用上下文感知组件创造魔法

上下文感知组件(context-aware)是“魔法的”,它们自动适应周围发生的事情,处理边缘情况、状态共享等等。

有3种主要的 context-aware ,但 Configuration 是我最感兴趣的一种。

1.状态共享

当你把一个大的组件分解成多个小的组件时,它们往往仍然需要共享状态。

我们可以在 "幕后 "做这些工作,而不是把这些工作推给使用者。

我们一般会把 Dropdown 组件分解成 Select 和 Option 组件,这样会获得更多的灵活性。但是为了方便使用,Select 和Option组件彼此共享 selected 状态。

<!-- 为简单起见,作为一个单一组件使用 -->
<Dropdown v-model="selected" :options="[]" />
<!-- 分多个组件,更灵活 -->
<Select v-model="selected">
<Option value="mustard">Mustard</Option>
<Option value="ketchup">Ketchup</Option>
<div class="relish-wrapper">
<Option value="relish">Relish</Option>
</div>
</Select>

2. Configuration

有时,一个组件的行为需要根据应用程序的其他部分的情况来改变。这通常是为了自动处理边缘情况,否则处理起来会很烦人。

一个 Popup 或 Tooltip 应该重新定位,以便它不会溢出页面。但是,如果该组件是在一个modal 内,它应该重新定位,以便它不会溢出 modal。

如果Tooltip知道它是在一个模态里面,这可以自动完成。

3.样式

创建了 context-aware的CSS,根据父级或同级元素的情况应用不同的样式。

.statistic {
color: black;
font-size: 24px;
font-weight: bold;
}
.statistic + .statistic {
margin-left: 10px;
}

CSS变量让我们更进一步,允许我们在一个页面的不同部分设置不同的值。

11. 如何在Vue之外创建一个具有响应性的变量(Vue2和3)

如果你从Vue之外得到一个变量,让它具有反应性是很好的。

这样,我们就可以在computed props、watch和其他任何地方使用它,它的工作方式就像Vue中的任何其他状态一样。

如果我们使用的选项API,需要的只是将其放在组件的数据部分中:

const externalVariable = getValue();
export default {
data() {
return {
reactiveVariable: externalVariable,
};
}
};

如果使用Vue3的组合API,可以直接使用ref或reactive。

import { ref } from 'vue';
// 可以完全在Vue组件之外完成
const externalVariable = getValue();
const reactiveVariable = ref(externalVariable);
console.log(reactiveVariable.value);

使用 reactive 代替:

import { reactive } from 'vue';
// 可以完全在Vue组件之外完成
const externalVariable = getValue();
// reactive 只对对象和数组起作用
const anotherReactiveVariable = reactive(externalVariable);
// Access directly
console.log(anotherReactiveVariable);

如果你还在使用 Vue2,你可以使用observable而不是reactive来实现完全相同的结果。

12. v-for 中的解构

你知道可以在-vfor中使用解构吗?

<li
v-for="{ name, id } in users"
:key="id"
>
{{ name }}
</li>

更广为人知的是,可以通过使用这样的元组从v-for中取出索引。

<li v-for="(movie, index) in [
'Lion King',
'Frozen',
'The Princess Bride'
]">
{{ index + 1 }} - {{ movie }}
</li>

当使用一个对象时,可以这样使用 key:

<li v-for="(value, key) in {
name: 'Lion King',
released: 2019,
director: 'Jon Favreau',
}">
{{ key }}: {{ value }}
</li>

也可以将这两种方法结合起来,获取key以及属性的 index。

<li v-for="(value, key, index) in {
name: 'Lion King',
released: 2019,
director: 'Jon Favreau',
}">
#{{ index + 1 }}. {{ key }}: {{ value }}
</li>

13. 在指定范围内循环

v-for指令允许我们遍历数组,但它也允许我们遍历一个范围

<template>
<ul>
<li v-for="n in 5">Item #{{ n }}</li>
</ul>
</template>

渲染结果:

Item #1
Item #2
Item #3
Item #4
Item #5

当我们使用带范围的v-for时,它将从1开始,以我们指定的数字结束。

14. 监听你的组件中的任何东西

export default {
computed: {
someComputedProperty() {
// Update the computed prop
},
},
watch: {
someComputedProperty() {
// Do something when the computed prop is updated
}
}
};

我们可以监听:

  • 计算属性
  • props
  • 嵌套值
    如果你使用组合API,任何值都可以被监视,只要它是一个ref或reactive对象。

    15.窃取 prop 类型

    我从一个子组件中复制 prop 类型,只是为了在一个父组件中使用它们。但我发现,偷取这些 prop 类型要比仅仅复制它们好得多。

例如,我们在这个组件中使用了一个Icon组件。

<template>
<div>
<h2>{{ heading }}</h2>
<Icon
:type="iconType"
:size="iconSize"
:colour="iconColour"
/>
</div>
</template>

为了让它工作,我们需要添加正确的 prop 类型,从`Icon组件复制。

import Icon from './Icon';
export default {
components: { Icon },
props: {
iconType: {
type: String,
required: true,
},
iconSize: {
type: String,
default: 'medium',
validator: size => [
'small',
'medium',
'large',
'x-large'
].includes(size),
},
iconColour: {
type: String,
default: 'black',
},
heading: {
type: String,
required: true,
},
},
};

当 Icon 组件的 prop类型被更新时,我们肯定会忘记返回这个组件并更新它们。随着时间的推移,当该组件的 prop类型开始偏离Icon组件中的 prop 类型时,就会引入错误。

因此,这就是为什么我们要窃取组件的 prop 类型:

import Icon from './Icon';
export default {
components: { Icon },
props: {
...Icon.props,
heading: {
type: String,
required: true,
},
},
};

不需要再复杂了。

除了在我们的例子中,我们把 icon 加在每个 prop 名称的开头。所以我们必须做一些额外的工作来实现这一点。

import Icon from './Icon';
const iconProps = {};
Object.entries(Icon.props).forEach((key, val) => {
iconProps[`icon${key.toUpperCase()}`] = val;
});
export default {
components: { Icon },
props: {
...iconProps,
heading: {
type: String,
required: true,
},
},
};

现在,如果Icon组件中的 prop 类型被修改,我们的组件将保持最新状态。

但是,如果一个 prop 类型从 Icon 组件中被添加或删除了呢?为了应对这些情况,我们可以使用v-bind和一个计算的 prop 来保持动态。

版权声明
本文为[娜娜]所创,转载请带上原文链接,感谢
https://segmentfault.com/a/1190000040806580

  1. Projet Java: système de gestion du rendement des employés (Java + SSM + MySQL + Maven + HTML)
  2. CSS tips | one line of code to realize the integration of avatar and national flag
  3. Maotai and Paris Fashion Week joined hands to make Chinese elements appear on the show
  4. Wang Xiaoya showed up in a sleeveless skirt and reappeared her intellectual elegance. She was still full of temperament after leaving the nest CCTV
  5. Comment écrire un document de conception frontale
  6. Créer une api javascript haute performance avec Rust et l'exécuter dans webassembly
  7. Analyse de certains principes techniques clés du SDK de surveillance frontale
  8. Point de vue: la NFT de type portrait a formé un modèle d'entreprise. Quelles sont ses perspectives d'avenir et ses difficultés?
  9. Stars celebrate the motherland's birthday in patterns: Tang Yan Bixin, Liu Xiaoqing in military uniform, Zhao Liying and he Jiong send blessings
  10. L'amour entre Wing Mei et Luan Tree: de l'amour à première vue à l'amour éternel
  11. Disappeared car companies: tape measure is useless? Zhongtai is on the verge of death and has no way to return to heaven
  12. BUUCTF [极客大挑战 2019]Http
  13. element缓存到本地使用
  14. How can the volunteer army with less steel and more gas beat the American army with more steel and less gas? Changjin Lake gives you the answer
  15. CentOS installation source package nginx error
  16. Mise en cache des éléments pour utilisation locale
  17. Disappeared car companies: tape measure is useless? Zhongtai is on the verge of death and has no way to return to heaven
  18. He saifei est si naturel!58 ans est si beau, porter des vêtements de vieillesse pour accepter de vieillir!
  19. Finally pregnant! Seven years of pregnancy, collective blessing of the entertainment industry
  20. Wu Qili sent blessings on the national day. She looked haggard and thin on her own. It was worrying
  21. Error in spring source code compilation: the monoprocessor in reactor.core.publisher is outdated
  22. Buctf [geek Challenge 2019] http
  23. 20 个值得学习的 Vue 开源项目
  24. 20 projets open source à apprendre
  25. Scène et application de la manette des gaz anti - bavardage
  26. Qu'est - ce que j'ai gagné en abandonnant vue pour les six mois de React?
  27. À partir de [Bytecode cache] et de [http cache], intervieweur: « est - ce si mince? »
  28. [niveau intermédiaire et avancé] obligatoire, 30 + questions manuscrites à haute fréquence et réponses détaillées (dix mille caractères longs), voyez comment "vous" ne pouvez pas m'abattre
  29. Mise en œuvre d'un outil d'échafaudage universel pour l'ingénierie Web de 0 à 1
  30. 【中高级前端】必备,30+高频手写题及详细答案(万字长文),看“你”怎么难倒我
  31. In less than two days, the box office exceeded 400 million, and Changjin Lake broke out, breaking seven records in Chinese film history
  32. Tong Liya Jin Chen bumps her hair, Xie Na Zhao Liying bumps her shirt, and she sees EQ from the reaction
  33. react之组件生命周期
  34. L'équipe de vue dévoile un nouvel outil d'échafaudage rapide comme la foudre Create View, qui remplacera la vue CLI à l'avenir, avec seulement 300 lignes de code, apprenez - le!
  35. 20 dessins illustrant le fonctionnement du moteur de rendu du Navigateur
  36. In less than two days, the box office exceeded 400 million, and Changjin Lake broke out, breaking seven records in Chinese film history
  37. 千锋重庆web前端学习之理解CSS位置属性
  38. 什么是语义HTML标记以及如何使用它们?
  39. Si vous vous représentez avec un tableau, c'est le champ de Van Gogh.
  40. 前端面试手写代码
  41. 前端开发框架Vue中Vuex的使用原理分享
  42. vue-echarts初次体验
  43. 分享一些web前端开发好用的网站
  44. 每天读一点webpack-003
  45. react之组件生命周期
  46. Alibaba collection version of mybatis handwritten documents, Java front-end interview questions
  47. SpringBoot Java后端实现okhttp3超时设置
  48. react之組件生命周期
  49. Cycle de vie des composants de React
  50. 使用Reactor将阻塞调用变为异步非阻塞
  51. Baked cake wife sun photos, plain face on camera, beautiful appearance is still a beauty, watching children during the festival is a little helpless
  52. 亚洲知名插画师荒川(arakawa) 仅8件独版NFT作品系列《Can't Out》正式上架Element综合市场
  53. Taiyuan: singing, welcoming the national day, gathering to praise blessings
  54. Arakawa, un illustrateur Asiatique bien connu, n'a mis sur le marché que huit pièces de la collection NFT "can't out" en une seule édition.
  55. Résumé des questions d'entrevue Hadoop (II) - - hdfs
  56. 如何解决“Serverless”系统的冷启动问题
  57. BootstrapBlazor 模板安装
  58. BootstrapBlazor 模板安装
  59. Tong Liya Jin Chen bumps her hair, Xie Na Zhao Liying bumps her shirt, and she sees EQ from the reaction
  60. 使用ESLint+Prettier来统一前端代码风格