목차
Here are some slots
A wrapped slot
This is a pretty great component, amirite?
那么,为什么我们希望能够有条件地渲染插槽呢?
{{ heading }}
웹 프론트엔드 View.js 알아두면 좋은 Vue 팁 25개, 여전히 이런 방식으로 사용할 수 있는 것으로 나타났습니다!

알아두면 좋은 Vue 팁 25개, 여전히 이런 방식으로 사용할 수 있는 것으로 나타났습니다!

May 20, 2022 am 10:49 AM
vue vue.js

이 글은 25가지 Vue 팁을 요약하고 정리한 것입니다. 사용법을 배우는 데 너무 오랜 시간이 걸렸습니다. 이제 이 팁이 모든 사람에게 도움이 되고 프로그래밍 생활을 더 쉽게 만들 수 있기를 바랍니다.

알아두면 좋은 Vue 팁 25개, 여전히 이런 방식으로 사용할 수 있는 것으로 나타났습니다!

더 나은 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有效或无效,则返回truefalse

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

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

2、默认内容和扩展点

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

<button class="button" @click="$emit(&#39;click&#39;)">
  <slot>
    <!-- Used if no slot is provided -->
    Click me
  </slot>
</button>
로그인 후 복사

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

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

<template>
  <button class="button" @click="$emit(&#39;click&#39;)">
    <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 {
  &#39;$route.query.id&#39;() {
    // ...
  }
}
로그인 후 복사

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 id="Here-nbsp-are-nbsp-some-nbsp-slots">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 id="A-nbsp-wrapped-nbsp-slot">A wrapped slot</h2>
    <div v-if="$slots.default" class="styles">
      <slot />
    </div>
  </div>
</template>
로그인 후 복사

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

如果不使用v-if,那么如果没有插槽,就会得到一个空的不必要的div。根据div

<template>
  <div>
    <h2 id="This-nbsp-is-nbsp-a-nbsp-pretty-nbsp-great-nbsp-component-nbsp-amirite">This is a pretty great component, amirite?</h2>
    <div class="default-styling">
      <slot >
    </div>
    <button @click="$emit(&#39;click&#39;)">Click me!</button>
  </div>
</template>
로그인 후 복사
로그인 후 복사

이 확인 함수는 prop을 받아들이고 prop이 유효하거나 유효하지 않은 경우 true 또는 false를 반환합니다. 🎜🎜단순히 true 또는 false를 전달하여 특정 조건을 제어할 수 없을 때 일반적으로 이 방법을 사용합니다. 🎜🎜버튼 유형이나 경고 유형(정보, 성공, 위험, 경고)이 가장 일반적으로 사용됩니다. 컬러도 활용도가 좋습니다. 🎜🎜🎜🎜2. 기본 콘텐츠 및 확장 포인트🎜🎜🎜🎜Vue의 슬롯에는 기본 콘텐츠가 있어 사용하기 쉬운 구성 요소를 만들 수 있습니다. 🎜
<div>
  <h2 id="This-nbsp-is-nbsp-a-nbsp-pretty-nbsp-great-nbsp-component-nbsp-amirite">This is a pretty great component, amirite?</h2>
  <div class="default-styling">
    <!-- 槽中没有内容,但这个div 仍然被渲染。糟糕 -->
  </div>
  <button @click="$emit(&#39;click&#39;)">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 &#39;vue&#39;;

// 可以完全在Vue组件之外完成
const externalVariable = getValue();
const reactiveVariable = ref(externalVariable);

console.log(reactiveVariable.value);
로그인 후 복사
로그인 후 복사
import { reactive } from &#39;vue&#39;;

//  可以完全在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 id="This-nbsp-is-nbsp-a-nbsp-pretty-nbsp-great-nbsp-component-nbsp-amirite">This is a pretty great component, amirite?</h2>
    <div class="default-styling">
      <slot >
    </div>
    <button @click="$emit(&#39;click&#39;)">Click me!</button>
  </div>
</template>
로그인 후 복사
로그인 후 복사

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

<div>
  <h2 id="This-nbsp-is-nbsp-a-nbsp-pretty-nbsp-great-nbsp-component-nbsp-amirite">This is a pretty great component, amirite?</h2>
  <div class="default-styling">
    <!-- 槽中没有内容,但这个div 仍然被渲染。糟糕 -->
  </div>
  <button @click="$emit(&#39;click&#39;)">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 组件分解成 SelectOption 组件,这样会获得更多的灵活性。但是为了方便使用,SelectOption组件彼此共享 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

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

一个 PopupTooltip 应该重新定位,以便它不会溢出页面。但是,如果该组件是在一个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 propswatch和其他任何地方使用它,它的工作方式就像Vue中的任何其他状态一样。

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

const externalVariable = getValue();

export default {
  data() {
    return {
      reactiveVariable: externalVariable,
    };
  }
};
로그인 후 복사
로그인 후 복사

如果使用Vue3的组合API,可以直接使用refreactive

import { ref } from &#39;vue&#39;;

// 可以完全在Vue组件之外完成
const externalVariable = getValue();
const reactiveVariable = ref(externalVariable);

console.log(reactiveVariable.value);
로그인 후 복사
로그인 후 복사

使用 reactive 代替:

import { reactive } from &#39;vue&#39;;

//  可以完全在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 [
  &#39;Lion King&#39;,
  &#39;Frozen&#39;,
  &#39;The Princess Bride&#39;
]">
  {{ index + 1 }} - {{ movie }}
</li>
로그인 후 복사

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

<li v-for="(value, key) in {
  name: &#39;Lion King&#39;,
  released: 2019,
  director: &#39;Jon Favreau&#39;,
}">
  {{ key }}: {{ value }}
</li>
로그인 후 복사

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

<li v-for="(value, key, index) in {
  name: &#39;Lion King&#39;,
  released: 2019,
  director: &#39;Jon Favreau&#39;,
}">
  #{{ 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,任何值都可以被监视,只要它是一个refreactive对象。

15、窃取 prop 类型

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

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

<template>
  <div>
    <h2 id="nbsp-heading-nbsp">{{ heading }}</h2>
    <Icon
      :type="iconType"
      :size="iconSize"
      :colour="iconColour"
    />
  </div>
</template>
로그인 후 복사

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

import Icon from &#39;./Icon&#39;;
export default {
  components: { Icon },
  props: {
    iconType: {
      type: String,
      required: true,
    },
    iconSize: {
      type: String,
      default: &#39;medium&#39;,
      validator: size => [
        &#39;small&#39;,
        &#39;medium&#39;,
        &#39;large&#39;,
        &#39;x-large&#39;
      ].includes(size),
    },
    iconColour: {
      type: String,
      default: &#39;black&#39;,
    },
    heading: {
      type: String,
      required: true,
    },
  },
};
로그인 후 복사

多么痛苦啊。

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

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

import Icon from &#39;./Icon&#39;;
export default {
  components: { Icon },
  props: {
    ...Icon.props,
    heading: {
      type: String,
      required: true,
    },
  },
};
로그인 후 복사

不需要再复杂了。

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

import Icon from &#39;./Icon&#39;;

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(&#39;mousedown&#39;, 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这样的分析仪表:

알아두면 좋은 Vue 팁 25개, 여전히 이런 방식으로 사용할 수 있는 것으로 나타났습니다!

如果你想让布局知道每个小组件应该占多少列,你可以直接在组件上添加元数据。

export default {
  name: &#39;LiveUsersWidget&#39;,
  // ? 只需将其作为一个额外的属性添加
  columns: 3,
  props: {
    // ...
  },
  data() {
    return {
      //...
    };
  },
};
로그인 후 복사
export default {
  name: &#39;LiveUsersWidget&#39;,
  // ?  只需将其作为一个额外的属性添加
  columns: 3,
  props: {
    // ...
  },
  data() {
    return {
      //...
    };
  },
};
로그인 후 복사

你会发现这个元数据是组件上的一个属性。

import LiveUsersWidget from &#39;./LiveUsersWidget.vue&#39;;
const { columns } = LiveUsersWidget;
로그인 후 복사

我们也可以通过特殊的$options属性从组件内部访问元数据。

export default {
  name: &#39;LiveUsersWidget&#39;,
  columns: 3,
  created() {
    // ? `$options` contains all the metadata for a component
    console.log(`Using ${this.$options.metadata} columns`);
  },
};
로그인 후 복사

只要记住,这个元数据对组件的每个实例都是一样的,而且不是响应式的。

这方面的其他用途包括(但不限于):

  • 保持单个组件的版本号
  • 用于构建工具的自定义标志,以区别对待组件
  • 在计算属性、数据、watch 等之外为组件添加自定义功能
  • 其它

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: [&#39;trigger&#39;],
  watch: {
    shouldCallMethod(newVal) {
      if (newVal) {
        // Call the method when the trigger is set to `true`
        this.method();
      }
    }
  }
}
로그인 후 복사

这可以正常工作,但只能在第一次调用时使用。如果您需要多次触发此操作,则必须进行清理并重置状态。逻辑是这样的

  • 父组件将 true 传递给触发器 prop
  • Watch 被触发,然后 Child 组件调用该方法
  • 子组件发出一个事件,告诉父组件该方法已被成功触发
  • Parent组件将 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: &#39;ColourChange&#39;,
  props: {
    colours: {
      type: Array,
      required: true,
    },
  },
  watch: {
    // 使用对象语法,而不仅仅是方法
    colours: {
      // 这将让Vue知道要在数组内部寻找
      deep: true,

      handler()
        console.log(&#39;The list of colours has changed!&#39;);
      }
    }
  }
}
로그인 후 복사

使用Vue 3的API会是这样的:

watch(
  colours,
  () => {
    console.log(&#39;The list of colours has changed!&#39;);
  },
  {
    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="/static/imghw/default1.png"  data-src="imgPath"  class="lazy"   / 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="/static/imghw/default1.png"  data-src="imgPath"  class="lazy"   / 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 중국어 웹사이트의 기타 관련 기사를 참조하세요!

본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

Video Face Swap

Video Face Swap

완전히 무료인 AI 얼굴 교환 도구를 사용하여 모든 비디오의 얼굴을 쉽게 바꾸세요!

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

vue.js vs. React : 프로젝트 별 고려 사항 vue.js vs. React : 프로젝트 별 고려 사항 Apr 09, 2025 am 12:01 AM

vue.js는 중소형 프로젝트 및 빠른 반복에 적합한 반면 React는 크고 복잡한 응용 프로그램에 적합합니다. 1) vue.js는 사용하기 쉽고 팀이 불충분하거나 프로젝트 규모가 작는 상황에 적합합니다. 2) React는 더 풍부한 생태계를 가지고 있으며 고성능 및 복잡한 기능적 요구가있는 프로젝트에 적합합니다.

Vue에서 부트 스트랩을 사용하는 방법 Vue에서 부트 스트랩을 사용하는 방법 Apr 07, 2025 pm 11:33 PM

vue.js에서 bootstrap 사용은 5 단계로 나뉩니다 : Bootstrap 설치. main.js.의 부트 스트랩 가져 오기 부트 스트랩 구성 요소를 템플릿에서 직접 사용하십시오. 선택 사항 : 사용자 정의 스타일. 선택 사항 : 플러그인을 사용하십시오.

Vue 용 버튼에 기능을 추가하는 방법 Vue 용 버튼에 기능을 추가하는 방법 Apr 08, 2025 am 08:51 AM

HTML 템플릿의 버튼을 메소드에 바인딩하여 VUE 버튼에 함수를 추가 할 수 있습니다. 메소드를 정의하고 VUE 인스턴스에서 기능 로직을 작성하십시오.

Vue에서 시계를 사용하는 방법 Vue에서 시계를 사용하는 방법 Apr 07, 2025 pm 11:36 PM

vue.js의 시계 옵션을 사용하면 개발자가 특정 데이터의 변경 사항을들을 수 있습니다. 데이터가 변경되면 콜백 기능을 트리거하여 업데이트보기 또는 기타 작업을 수행합니다. 구성 옵션에는 즉시 콜백을 실행할지 여부와 DEEP를 지정하는 즉시 포함되며, 이는 객체 또는 어레이에 대한 변경 사항을 재귀 적으로 듣는 지 여부를 지정합니다.

Vue 다중 페이지 개발은 무엇을 의미합니까? Vue 다중 페이지 개발은 무엇을 의미합니까? Apr 07, 2025 pm 11:57 PM

VUE 멀티 페이지 개발은 vue.js 프레임 워크를 사용하여 응용 프로그램을 구축하는 방법입니다. 여기서 응용 프로그램은 별도의 페이지로 나뉩니다. 코드 유지 보수 : 응용 프로그램을 여러 페이지로 분할하면 코드를보다 쉽게 ​​관리하고 유지 관리 할 수 ​​있습니다. 모듈 식 : 각 페이지는 쉬운 재사용 및 교체를 위해 별도의 모듈로 사용할 수 있습니다. 간단한 라우팅 : 페이지 간의 탐색은 간단한 라우팅 구성을 통해 관리 할 수 ​​있습니다. SEO 최적화 : 각 페이지에는 자체 URL이있어 SEO가 도움이됩니다.

Vue Traversal 사용 방법 Vue Traversal 사용 방법 Apr 07, 2025 pm 11:48 PM

vue.js가 트래버스 어레이 및 객체에 대한 세 가지 일반적인 방법이 있습니다. V- 결합 지시문은 V-FOR와 함께 사용하여 각 요소의 속성 값을 동적으로 설정할 수 있습니다. .MAP 메소드는 배열 요소를 새 배열로 변환 할 수 있습니다.

Vue의 div로 점프하는 방법 Vue의 div로 점프하는 방법 Apr 08, 2025 am 09:18 AM

VUE에서 DIV 요소를 점프하는 두 가지 방법이 있습니다. VUE 라우터를 사용하고 라우터 링크 구성 요소를 추가하십시오. @Click 이벤트 리스너를 추가하고 이것을 호출하십시오. $ router.push () 메소드를 점프하십시오.

태그를 vue로 점프하는 방법 태그를 vue로 점프하는 방법 Apr 08, 2025 am 09:24 AM

VUE에서 태그의 점프를 구현하는 방법에는 다음이 포함됩니다. HTML 템플릿의 A 태그를 사용하여 HREF 속성을 지정합니다. VUE 라우팅의 라우터 링크 구성 요소를 사용하십시오. javaScript 에서이. $ router.push () 메소드를 사용하십시오. 매개 변수는 쿼리 매개 변수를 통해 전달 될 수 있으며 동적 점프를 위해 라우터 옵션에서 경로가 구성됩니다.

See all articles