이 글은 25가지 Vue 팁을 요약하고 정리한 것입니다. 사용법을 배우는 데 너무 오랜 시간이 걸렸습니다. 이제 이 팁이 모든 사람에게 도움이 되고 프로그래밍 생활을 더 쉽게 만들 수 있기를 바랍니다.
더 나은 Vue 개발자가 되기 위해 배우는 것이 항상 숙달하는 데 시간과 노력이 필요한 큰 개념에 관한 것은 아닙니다. 몇 가지 팁과 요령을 알면 많은 반복 작업 없이 프로그래밍 생활이 더 쉬워질 수 있습니다.
지난 몇 년간 Vue로 개발하면서 유용한 기술을 많이 배웠습니다. 일부는 까다롭고 일부는 거의 매일 사용하며 일부는 더 고급이지만 모두 유용합니다. (학습 영상 공유: vue 영상 튜토리얼)
1. prop을 유형 목록으로 제한하세요
prop 정의에서 validator
옵션을 사용하여 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、知道何时使用<span style="font-size: 18px;">v-if</span>
(以及何时避免使用)
与其使用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
<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>이 확인 함수는 prop을 받아들이고 prop이 유효하거나 유효하지 않은 경우
true
또는 false
를 반환합니다. 🎜🎜단순히 true 또는 false를 전달하여 특정 조건을 제어할 수 없을 때 일반적으로 이 방법을 사용합니다. 🎜🎜버튼 유형이나 경고 유형(정보, 성공, 위험, 경고)이 가장 일반적으로 사용됩니다. 컬러도 활용도가 좋습니다. 🎜🎜🎜🎜2. 기본 콘텐츠 및 확장 포인트🎜🎜🎜🎜Vue의 슬롯에는 기본 콘텐츠가 있어 사용하기 쉬운 구성 요소를 만들 수 있습니다. 🎜<div> <h2>This is a pretty great component, amirite?</h2> <div class="default-styling"> <!-- 槽中没有内容,但这个div 仍然被渲染。糟糕 --> </div> <button @click="$emit('click')">Click me!</button> </div>🎜기본 슬롯을 사용하는 가장 좋은 방법은 이를 사용하여 확장 지점을 만드는 것입니다. 🎜🎜컴포넌트의 어떤 부분이라도 가져다가 슬롯에 캡슐화한 다음 외부에서 원하는 대로 컴포넌트의 해당 부분을 덮어쓸 수 있습니다. 기본적으로는 여전히 동일한 방식으로 작동하지만 그렇게 하면 더 많은 옵션이 제공됩니다. 🎜
<!-- 可惜这个事件不存在 --> <slot @change="update" />🎜 이제 이 구성 요소를 다양한 방법으로 사용할 수 있습니다. 단순, 기본 방식 또는 사용자 정의 방식. 🎜
export default { mounted() { // 当有变化时调用`update` const observer = new MutationObserver(this.update); // 监听此组件的变化 observer.observe(this.$el, { childList: true, subtree: true }); } };🎜🎜🎜 3. 따옴표를 사용하여 중첩된 속성을 수신합니다. 🎜🎜🎜🎜 이것을 모를 수도 있지만 따옴표를 사용하면 중첩된 값을 직접 쉽게 들을 수 있습니다. 🎜
<style scoped> .component { background: green; } </style>🎜🎜🎜 4. 사용 시기를 파악합니다 🎜
🎜v-if🎜
🎜(및 이를 피해야 하는 경우) 🎜🎜🎜🎜v-if
를 사용하는 대신 때때로 v-show
를 사용하세요. 대신에 더 높은 성능이 나올 것입니다. 🎜<style> /* 全局 */ .component p { margin-bottom: 16px; } </style> <style scoped> /* 在该组件内有效 */ .component { background: green; } </style>🎜
v-if
를 켜거나 끄면 요소가 생성되고 완전히 파괴됩니다. 대신 v-show
는 요소를 생성하고 거기에 그대로 두고 스타일을 display: none
으로 설정하여 숨깁니다. 🎜🎜전환하려는 구성 요소의 렌더링 비용이 높을 경우 더 효율적입니다. 🎜🎜반대로, 비용이 많이 드는 구성 요소를 즉시 실행할 필요가 없다면 v-if
를 사용하면 렌더링을 건너뛰고 페이지 로드 속도를 높일 수 있습니다. 🎜🎜🎜🎜5. 단일 범위 슬롯의 약칭(템플릿 태그 필요 없음) 🎜🎜🎜🎜 범위 지정 슬롯은 매우 흥미롭지만 이를 사용하려면 많은 템플릿 태그도 사용해야 합니다. 🎜🎜 다행스럽게도 단일 스코프 슬롯을 사용하는 경우에만 이를 피할 수 있는 속기가 있습니다. 🎜🎜일반적인 글쓰기: 🎜<style scoped> .my-component >>> .child-component { font-size: 24px; } </style>🎜
템플릿
을 사용하지 마세요: 🎜<!-- 为简单起见,作为一个单一组件使用 --> <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>🎜간단하고 직설적이며 놀랍습니다. 🎜🎜🎜🎜 6. 조건부로 슬롯 렌더링 🎜🎜🎜🎜 먼저 어떻게 하는지 살펴보고 슬롯을 숨기려는 이유에 대해 논의해 보겠습니다. 🎜🎜모든 Vue 구성 요소에는 모든 슬롯을 포함하는 특별한
$slots
개체가 있습니다. 기본 슬롯의 키는 default
이며 명명된 모든 슬롯은 해당 이름을 키로 사용합니다. 🎜.statistic { color: black; font-size: 24px; font-weight: bold; } .statistic + .statistic { margin-left: 10px; }🎜하지만 이
$slots
객체에는 정의된 모든 슬롯이 아닌 이 구성 요소에 적용 가능한 슬롯만 있습니다. 🎜🎜몇 가지 명명된 슬롯을 포함하여 여러 슬롯을 정의하는 이 구성 요소를 사용하세요. 🎜const externalVariable = getValue(); export default { data() { return { reactiveVariable: externalVariable, }; } };🎜구성 요소에 하나의 슬롯만 적용하면 해당 슬롯만
$slots
개체에 표시됩니다. 🎜import { ref } from 'vue'; // 可以完全在Vue组件之外完成 const externalVariable = getValue(); const reactiveVariable = ref(externalVariable); console.log(reactiveVariable.value);
import { reactive } from 'vue'; // 可以完全在Vue组件之外完成 const externalVariable = getValue(); // reactive 只对对象和数组起作用 const anotherReactiveVariable = reactive(externalVariable); // Access directly console.log(anotherReactiveVariable);🎜 이를 구성 요소에서 사용하여 슬롯의 래핑 요소를 숨기는 등 구성 요소에 적용된 슬롯을 감지할 수 있습니다. 🎜
<li v-for="{ name, id } in users" :key="id" > {{ name }} </li>🎜이제 스타일이 적용되는 래퍼
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没有内置的方法让我们检测这一点。
然而,我的朋友Austin想出了一个非常干净的方法,使用MutationObserver来做这件事。
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、将局部和全局的 <span style="font-size: 18px;">style</span>
混合在一起
通常情况下,在处理样式时,我们希望它们能被划分到一个单独的组件中。
<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 } } };
我们可以监听:
如果你使用组合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
来保持动态。
16、检测元素外部(或内部)的单击
有时我需要检测一个点击是发生在一个特定元素el
的内部还是外部。这就是我通常使用的方法。
window.addEventListener('mousedown', e => { // 获取被点击的元素 const clickedEl = e.target; if (el.contains(clickedEl)) { //在 "el "里面点击了 } else { //在 "el "外点击了 } });
17、递归插槽
有一次,我决定看看我是否可以只用模板来做一个v-for
组件。在这个过程中,我也发现了如何递归地使用槽。
<!-- VFor.vue --> <template> <div> <!-- 渲染第一项 --> {{ list[0] }} <!-- 如果我们有更多的项目,继续!但是不要使用我们刚刚渲染的项 --> <v-for v-if="list.length > 1" :list="list.slice(1)" /> </div> </template>
如果你想用作用域插槽来做这件事,只是需要一些调整
<template> <div> <!-- Pass the item into the slot to be rendered --> <slot v-bind:item="list[0]"> <!-- Default --> {{ list[0] }} </slot> <v-for v-if="list.length > 1" :list="list.slice(1)" > <!-- Recursively pass down scoped slot --> <template v-slot="{ item }"> <slot v-bind:item="item" /> </template> </v-for> </div> </template>
下面是这个组件的使用方法。
<template> <div> <!-- 常规列表 --> <v-for :list="list" /> <!-- 加粗的项目列表 --> <v-for :list="list"> <template v-slot="{ item }"> <strong>{{ item }}</strong> </template> </v-for> </div> </template>
18、组件元数据
并不是添加到一个组件的每一点信息都是状态。有时我们需要添加一些元数据,给其他组件提供更多信息。
例如,如果正在为谷歌 analytics这样的分析仪表:
如果你想让布局知道每个小组件应该占多少列,你可以直接在组件上添加元数据。
export default { name: 'LiveUsersWidget', // ? 只需将其作为一个额外的属性添加 columns: 3, props: { // ... }, data() { return { //... }; }, };
export default { name: 'LiveUsersWidget', // ? 只需将其作为一个额外的属性添加 columns: 3, props: { // ... }, data() { return { //... }; }, };
你会发现这个元数据是组件上的一个属性。
import LiveUsersWidget from './LiveUsersWidget.vue'; const { columns } = LiveUsersWidget;
我们也可以通过特殊的$options
属性从组件内部访问元数据。
export default { name: 'LiveUsersWidget', columns: 3, created() { // ? `$options` contains all the metadata for a component console.log(`Using ${this.$options.metadata} columns`); }, };
只要记住,这个元数据对组件的每个实例都是一样的,而且不是响应式的。
这方面的其他用途包括(但不限于):
19、多文件单文件组件
这是**SFC(单文件组件)**的一点已知功能。
可以像常规HTML文件一样导入文件:
<template src="./template.html"></template> <script src="./script.js"></script> <style scoped src="./styles.css"></style>
如果你需要分享样式、文件或其他任何东西,这可能会非常方便。
20、可重复使用的组件并不是你所想的那样
可重复使用的组件不一定是大的或复杂的东西。
我经常让小的和短的组件可以重复使用。
因为我没有到处重写这段代码,所以更新它变得更加容易,而且我可以确保每个OverflowMenu
的外观和工作方式都完全一样--因为它们是一样的!"。
<!-- OverflowMenu.vue --> <template> <Menu> <!-- 添加一个自定义按钮来触发我们的菜单 --> <template #button v-slot="bind"> <!-- 使用bind来传递click处理程序、a11y 属性等 --> <Button v-bind="bind"> <template #icon> <svg src="./ellipsis.svg" /> </template> </Button> </template> </Menu> </template>
在这里,我们采用了一个菜单组件,但在触发它的按钮上添加了一个 ellipsis 图标
。(省略号)的图标来触发它的打开。
这似乎不值得把它做成一个可重复使用的组件,因为它只有几行。难道我们就不能在每次要使用这样的菜单时添加图标吗?
但是这个OverflowMenu将被使用几十次,现在如果我们想更新图标或它的行为,我们可以非常容易地做到。而且,使用它也更简单了。
21、从组件外部调用一个方法
我们可以从一个组件的外部通过给它一个 ref
用来调用一个方法。
<!-- Parent.vue --> <template> <ChildComponent ref="child" /> </template>
// Somewhere in Parent.vue this.$refs.child.method();
再解释一下这个问题。
有时候,“最佳实践”并不适用于你正在做的事情,你需要一个像这样的逃生口。
通常情况下,我们使用 props 和 events 在组件之间进行交流。props 被下发到子组件中,而events 被上发到父组件中。
<template> <ChildComponent :tell-me-what-to-do="someInstructions" @something-happened="hereIWillHelpYouWithThat" /> </template>
// Child.vue export default { props: ['trigger'], watch: { shouldCallMethod(newVal) { if (newVal) { // Call the method when the trigger is set to `true` this.method(); } } } }
这可以正常工作,但只能在第一次调用时使用。如果您需要多次触发此操作,则必须进行清理并重置状态。逻辑是这样的
true
传递给触发器 prop
trigger
重置为 false
,所以我们可以从头再来一次相反,如果我们在子组件上设置一个 ref
,我们可以直接调用该方法:
<!-- Parent.vue --> <template> <ChildComponent ref="child" /> </template>
// Somewhere in Parent.vue this.$refs.child.method();
是的,我们打破了 “props down, events up"” 的规则,我们打破了封装,但是这样做更清晰,更容易理解,所以是值得的
有时,"最好的 "解决方案最终会成为最糟糕的解决方案。
22、监听数组和对象
使用 watcher
最棘手的部分是,有时它似乎不能正确触发。
通常,这是因为我们试图监听数组或对象,但没有将deep
设置为true
export default { name: 'ColourChange', props: { colours: { type: Array, required: true, }, }, watch: { // 使用对象语法,而不仅仅是方法 colours: { // 这将让Vue知道要在数组内部寻找 deep: true, handler() console.log('The list of colours has changed!'); } } } }
使用Vue 3的API会是这样的:
watch( colours, () => { console.log('The list of colours has changed!'); }, { deep: true, } );
23、用Vue Router进行深度链接
我们可以在URL中存储(一点)状态,允许我们直接跳到页面上的一个特定状态。
例如,你加载一个已经选择了日期范围过滤器的页面:
someurl.com/edit?date-range=last-week
这对于应用中用户可能共享大量链接的部分来说是非常棒的,对于服务器渲染的应用,或者在两个独立的应用之间通信的信息比普通链接通常提供的更多。
我们可以存储过滤器、搜索值、模态框是打开还是关闭,或者在列表的哪个位置滚动以完美地实现无限分页。
使用 vue-router
获取查询参数是这样工作的(这也适用于大多数Vue框架,如Nuxt和Vuepress):
const dateRange = this.$route.query.dateRange;
为了改变它,我们使用 RouterLink
组件并更新 query
。
<RouterLink :to="{ query: { dateRange: newDateRange } }">
24、<span style="font-size: 18px;">template</span>
标签的另一个用途
template
标签可以在模板中的任何地方使用,以更好地组织代码。
我喜欢用它来简化v-if
逻辑,有时也用v-for
。
在这个例子中,我们有几个元素都使用同一个v-if
条件。
<template> <div class="card"> <img src="imgPath" / alt="알아두면 좋은 Vue 팁 25개, 여전히 이런 방식으로 사용할 수 있는 것으로 나타났습니다!" > <h3> {{ title }} </h3> <h4 v-if="expanded"> {{ subheading }} </h4> <div v-if="expanded" class="card-content" > <slot /> </div> <SocialShare v-if="expanded" /> </div> </template>
这有点笨拙,而且一开始并不明显,一堆这样的元素被显示和隐藏在一起。在一个更大、更复杂的组件上,这可能是一个更糟糕的情况
但我们能优化它。
我们可以使用 template
标签来分组这些元素,并将 v-if
提升到模板 template
本身。
<template> <div class="card"> <img src="imgPath" / alt="알아두면 좋은 Vue 팁 25개, 여전히 이런 방식으로 사용할 수 있는 것으로 나타났습니다!" > <h3> {{ title }} </h3> <template v-if="expanded"> <h4> {{ subheading }} </h4> <div class="card-content"> <slot /> </div> <SocialShare /> </template> </div> </template>
现在看起来就更容易理解,而且它在做什么,一目了然。
25、处理错误(和警告)的更好方法
我们可以为Vue中的错误和警告提供一个自定义处理程序。
// Vue 3 const app = createApp(App); app.config.errorHandler = (err) => { alert(err); }; // Vue 2 Vue.config.errorHandler = (err) => { alert(err); };
像 Bugsnag 和 Rollbar 这样的错误跟踪服务,可以钩住这些处理程序来记录错误,但你也可以用它们来更优雅地处理错误,以获得更好的用户体验。
예를 들어 오류가 처리되지 않은 경우 앱이 직접 충돌하는 대신 전체 오류 화면을 표시하고 사용자가 새로 고치거나 다른 작업을 시도하도록 할 수 있습니다.
Vue3에서 오류 핸들러는 template
和 watcher
错误,但是 Vue2
오류 핸들러만 처리할 수 있으며 거의 모든 오류를 포착할 수 있습니다. 두 버전의 경고 처리기는 개발 단계에서만 작동합니다.
(학습 영상 공유: 웹 프론트엔드 개발, 기본 프로그래밍 영상)
위 내용은 알아두면 좋은 Vue 팁 25개, 여전히 이런 방식으로 사용할 수 있는 것으로 나타났습니다!의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!