당신이 알아야 할 25가지 Vue 팁

青灯夜游
풀어 주다: 2022-03-09 19:58:24
앞으로
2616명이 탐색했습니다.

이 기사는 개발 속도를 향상시키는 25가지 Vue 팁을 요약하고 공유합니다. 모든 사람에게 도움이 되기를 바랍니다.

당신이 알아야 할 25가지 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)
    }
  }
};
로그인 후 복사

这个 validator 函数接受一个 prop,返回 true 或 false。当你需要比布尔值允许的更多选项时,也可以使用它。按钮类型或警报类型(信息、成功、危险、警告)是一些比较常见的用途。【相关推荐:vuejs视频教程

2. 默认内容和扩展点

Vue 中的slot可以具有默认内容,你可以制作更易于使用的组件:

<button class="button" @click="$emit(&#39;click&#39;)">
  <slot>
    <!-- 如果没有提供slot则使用 -->
    Click me
  </slot>
</button>
로그인 후 복사

基本上你可以获取组件的任何部分,将它包装在一个slot中,然后你可以使用你想要的任何内容覆盖该组件的该部分。默认情况下,它仍然会照常一样工作,不过还可以有更多选择:

<template>
  <button class="button" @click="$emit(&#39;click&#39;)">
    <!-- 一开始在 slot 标签中添加什么都不做 -->
    <!-- 我们可以通过向 slot 提供内容来覆盖它 -->
    <slot>
      <div class="formatting">
        {{ text }}
      </div>
    </slot>
  </button>
</template>
로그인 후 복사

现在你可以用多种不同的方式使用此组件。简单的默认方式或者你自己的自定义方式:

<!-- 使用组件的默认功能 -->
<ButtonWithExtensionPoint text="Formatted text" />

<!-- 使用扩展点创建自定义行为 -->
<ButtonWithExtensionPoint>
  <div class="different-formatting">
    在这里做一些不同的事情
  </div>
</ButtonWithExtensionPoint>
로그인 후 복사

3. 使用引号观察嵌套值

你可能不知道这一点:只需使用引号就可以轻松地直接查看嵌套值:

watch {
  &#39;$route.query.id&#39;() {
    // ...
  }
}
로그인 후 복사

这对于处理深度嵌套的对象非常有用

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

有时不使用v-if,使用v-show会更高效:

<ComplicatedChart v-show="chartEnabled" />
로그인 후 복사

v-if打开和关闭时,它将完全创建和销毁元素。v-show不同的是将创建元素并将其留在那里,通过将其样式设置为display: none来隐藏它。

如果你需要切换的组件渲染起来代价比较高,那么这样做会更有效率。另一方面,如果你不需要立即使用那个组件,可以使用v-if以便它跳过渲染它并更快地加载页面。

5. 单作用域 slot 的简写(不需要模板标签!)

Scoped slot 比较有趣,但为了使用它们,你也必须使用很多template标签。

然而有一个速记可以让我们摆脱它,但前提是我们使用单个作用域slot。

可以不用这样写:

<DataTable>
  <template #header="tableAttributes">
    <TableHeader v-bind="tableAttributes" />
  </template>
</DataTable>
로그인 후 복사

我们可以这样写:

<DataTable #header="tableAttributes">
  <TableHeader v-bind="tableAttributes" />
</DataTable>
로그인 후 복사

这样更简单、直接。

6. 有条件地渲染slot

每个 Vue 组件都有一个特殊的 $slots 对象,其中包含所有slot。 默认slot具有默认键,名字命名的slot都使用它们的名称作为键:

const $slots = {
  default: <default slot>,
  icon: <icon slot>,
  button: <button slot>,
};
로그인 후 복사

但是这个$slots对象只有应用于组件的slot,而不是每个定义的slot。

以这个定义了几个slot的组件为例,包括几个命名的slot:

<!-- Slots.vue -->
<template>
  <div>
    <h2>这里是一些slots</h2>
    <slot />
    <slot name="second" />
    <slot name="third" />
  </div>
</template>
로그인 후 복사

如果我们只对组件应用一个slot,则只有该slot会出现在我们的$slots对象中:

<template>
  <Slots>
    <template #second>
      这将应用于第二个slot
    </template>
  </Slots>
</template>
로그인 후 복사
$slots = { second: <vnode> }
로그인 후 복사

我们可以在我们的组件中使用它来检测哪些slot已应用于组件,例如,通过隐藏slot的包装元素:

<template>
  <div>
    <h2>一个包裹的slot</h2>
    <div v-if="$slots.default" class="styles">
      <slot />
    </div>
  </div>
</template>
로그인 후 복사

现在div,应用样式的包装器只有在我们实际用某些东西填充该slot时才会呈现。

如果我们不使用v-ifdiv如果我们没有slot,我们最终会得到一个空的和不必要的。根据所div具有的样式,这可能会弄乱我们的布局并使事情看起来很奇怪。

为什么我们希望能够有条件地渲染slot呢?

使用条件slot主要有以下三个原因:

  • 使用 wrapper div 来添加默认样式时

  • slot是空的

  • 当我们将默认内容与嵌套slot组合

例如,当我们添加默认样式时,我们会在slot周围添加一个div

<template>
  <div>
    <h2>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>
로그인 후 복사

但是,如果父组件没有将内容应用到该slot,我们最终会在页面div上呈现一个空的:

<div>
  <h2>这是一个非常棒的组件</h2>
  <div class="default-styling">
    <!-- slot中没有内容,但仍会呈现此 div-->
  </div>
  <button @click="$emit(&#39;click&#39;)">Click me!</button>
</div>
로그인 후 복사

v-if在包装上添加它div

<div>
  <h2>这是一个非常棒的组件</h2>
  <button @click="$emit(&#39;click&#39;)">Click me!</button>
</div>
로그인 후 복사

이 유효성 검사기 함수는 prop을 받아들이고 true 또는 false를 반환합니다. 부울 값이 허용하는 것보다 더 많은 옵션이 필요한 경우에도 사용할 수 있습니다. 버튼 유형 또는 경고 유형(정보, 성공, 위험, 경고)은 보다 일반적으로 사용됩니다. [관련 권장사항: vuejs 비디오 튜토리얼

]

2. 기본 콘텐츠 및 확장 포인트

Vue의 슬롯에는 기본 콘텐츠가 있을 수 있으며 사용하기 쉬운 구성 요소를 만들 수 있습니다.

<!-- 可惜这个活动不存在 -->
<slot @change="update" />
로그인 후 복사

기본적으로 구성 요소의 일부를 가져와 추가할 수 있습니다. 슬롯에 래핑된 다음 원하는 대로 구성 요소의 해당 부분을 재정의할 수 있습니다. 기본적으로 평소와 같이 작동하지만 더 많은 옵션이 있습니다.

export default {
  mounted() {
    // 当事情发生变化时调用`update`
    const observer = new MutationObserver(this.update);

    // 观察这个组件的变化
    observer.observe(this.$el, {
      childList: true,
      subtree: true
    });
  }
};
로그인 후 복사

이제 이 구성 요소를 다양한 방법으로 사용할 수 있습니다. 간단한 기본 방법 또는 사용자 정의 방법:

<style scoped>
  .component {
    background: green;
  }
</style>
로그인 후 복사

3. 따옴표를 사용하여 중첩된 값 관찰 ​​

이 사실을 모를 수도 있습니다. 쉽게 확인하려면 따옴표를 사용하세요. ​​직접 값:

<style>
  /*全局应用*/
  .component p {
    margin-bottom: 16px;
  }
</style>

<style scoped>
  /*范围限定于此特定组件*/
  .component {
    background: green;
  }
</style>
로그인 후 복사
로그인 후 복사
🎜깊게 중첩된 객체를 작업하는 데 유용합니다🎜

4. v-if를 사용해야 하는 경우와 이를 피해야 하는 경우를 알아두세요🎜 🎜때때로 v-if를 사용하려면 v-show를 사용하는 것이 더 효율적입니다. 🎜
<style scoped>
/* 覆盖子组件的 CSS,同时保持样式范围*/
.my-component >>> .child-component {
  font-size: 24px;
}
</style>
로그인 후 복사
로그인 후 복사
🎜v-if를 켜고 끌 때, 요소가 완전히 생성되고 파괴됩니다. v-show는 요소를 생성하고 거기에 남겨두고 스타일을 display: none으로 설정하여 숨긴다는 점에서 다릅니다. 🎜🎜전환해야 하는 구성 요소를 렌더링하는 데 비용이 많이 드는 경우 이 방법이 더 효율적입니다. 반면 해당 구성 요소를 즉시 사용할 필요가 없다면 v-if를 사용하여 렌더링을 건너뛰고 페이지를 더 빠르게 로드할 수 있습니다. 🎜

5. 단일 범위 슬롯의 약자(템플릿 태그가 필요하지 않습니다!) 🎜🎜범위가 지정된 슬롯이 더 흥미롭지만 이를 사용하려면 많이 사용해야 합니다. 템플릿< /code> 태그. 🎜🎜그러나 단일 스코프 슬롯을 사용하는 경우에만 이를 제거할 수 있는 속기가 있습니다. 🎜🎜다음과 같이 작성할 필요는 없습니다.🎜<div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:js;toolbar:false;">&lt;!-- 为简单起见用作单个组件 --&gt; &lt;Dropdown v-model=&quot;selected&quot; :options=&quot;[]&quot; /&gt; &lt;!-- 拆分以获得更大的灵活性 --&gt; &lt;Select v-model=&quot;selected&quot;&gt; &lt;Option value=&quot;mustard&quot;&gt;Mustard&lt;/Option&gt; &lt;Option value=&quot;ketchup&quot;&gt;Ketchup&lt;/Option&gt; &lt;div class=&quot;relish-wrapper&quot;&gt; &lt;Option value=&quot;relish&quot;&gt;Relish&lt;/Option&gt; &lt;/div&gt; &lt;/Select&gt;</pre><div class="contentsignin">로그인 후 복사</div></div><div class="contentsignin">로그인 후 복사</div></div>🎜다음과 같이 작성할 수 있습니다.🎜<div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:js;toolbar:false;">.statistic { color: black; font-size: 24px; font-weight: bold; } /* 在彼此相邻的统计数据之间进行一些分离*/ .statistic + .statistic { margin-left: 10px; }</pre><div class="contentsignin">로그인 후 복사</div></div><div class="contentsignin">로그인 후 복사</div></div>🎜이것이 더 간단하고 직접적입니다. 🎜<h2 data-id="heading-5">6. 조건부로 슬롯 렌더링🎜🎜모든 Vue 구성 요소에는 모든 슬롯을 포함하는 특별한 $slots 객체가 있습니다. 기본 슬롯에는 기본 키가 있으며 명명된 슬롯은 해당 이름을 키로 사용합니다. 🎜<div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:js;toolbar:false;">const externalVariable = getValue(); export default { data() { return { reactiveVariable: externalVariable, }; } };</pre><div class="contentsignin">로그인 후 복사</div></div><div class="contentsignin">로그인 후 복사</div></div>🎜 하지만 이 <code>$slots 개체는 구성요소의 슬롯에만 적용되며 정의된 모든 A가 아닙니다. 슬롯. 🎜🎜몇 가지 명명된 슬롯을 포함하여 여러 슬롯을 정의하는 이 구성 요소를 예로 들어 보겠습니다. 🎜
import { ref } from &#39;vue&#39;;

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

// 使用 .value 访问
console.log(reactiveVariable.value);
로그인 후 복사
로그인 후 복사
🎜구성 요소에 하나의 슬롯만 적용하면 해당 슬롯만 개체의 $slots에 나타납니다. : 🎜
import { reactive } from &#39;vue&#39;;

// 可以完全在 Vue 组件之外完成
const externalVariable = getValue();
// Reactive 仅适用于对象和数组
const anotherReactiveVariable = reactive(externalVariable);

// 直接访问
console.log(anotherReactiveVariable);
로그인 후 복사
로그인 후 복사
<li
  v-for="{ name, id } in users"
  :key="id"
>
  {{ name }}
</li>
로그인 후 복사
로그인 후 복사
🎜 구성 요소에서 이를 사용하여 구성 요소에 어떤 슬롯이 적용되었는지 감지할 수 있습니다. 예를 들어 슬롯의 래핑 요소를 숨겨서 다음과 같이 할 수 있습니다. 🎜
<li v-for="(value, key) in [
  &#39;Hai Yong&#39;,
  &#39;Frozen&#39;,
  &#39;Web Beginner&#39;
]">
  {{ index + 1 }} - {{ value }}
</li>
로그인 후 복사
로그인 후 복사
🎜이제 div, 스타일이 적용됩니다. 래퍼는 실제로 슬롯을 무언가로 채울 때만 렌더링됩니다. 🎜🎜 v-if를 사용하지 않고, 슬롯이 없으면 div를 사용하지 않으면 비어 있고 불필요한 슬롯이 됩니다. div의 스타일에 따라 레이아웃이 엉망이 되고 상황이 이상해 보일 수 있습니다. 🎜

슬롯을 조건부로 렌더링하려는 이유는 무엇입니까?

🎜조건부 슬롯을 사용하는 세 가지 주요 이유는 다음과 같습니다. 🎜
  • 🎜기본 스타일을 추가하기 위해 래퍼 div를 사용하는 경우 🎜
  • 🎜슬롯이 비어 있습니다🎜
  • 🎜기본 콘텐츠를 중첩된 슬롯과 결합할 때🎜
🎜예를 들어 기본 스타일을 추가하면 슬롯 주위에 div를 추가합니다: 🎜
<li v-for="(value, key) in {
  name: &#39;Hai Yong&#39;,
  released: 2021,
  director: &#39;A blogger&#39;,
}">
  {{ key }}: {{ value }}
</li>
로그인 후 복사
로그인 후 복사
🎜 그러나 상위 구성 요소가 슬롯에 콘텐츠를 적용하지 않은 경우 페이지에 빈 div가 렌더링됩니다. :🎜
<li v-for="(value, key, index) in {
  name: &#39;Hai Yong&#39;,
  released: 2021,
  director: &#39;A blogger&#39;,
}">
  #{{ index + 1 }}. {{ key }}: {{ value }}
</li>
로그인 후 복사
로그인 후 복사
🎜 v-if 래퍼 div에 추가하면 문제를 해결할 수 있습니다. 슬롯에 콘텐츠가 적용되지 않습니까? 다음과 같습니다: 🎜
<template>
  <ul>
    <li v-for="n in 5">项目#{{ n }}</li>
  </ul>
</template>
로그인 후 복사
로그인 후 복사
🎜7. 슬롯의 변경 사항을 관찰하는 방법 🎜🎜 때때로 슬롯의 콘텐츠가 변경된 시기를 알아야 합니다. 🎜
export default {
  computed: {
    someComputedProperty() {
      // 更新计算道具
    },
  },
  watch: {
    someComputedProperty() {
      // 当计算的 prop 更新时做一些事情
    }
  }
};
로그인 후 복사
로그인 후 복사
🎜 불행히도 Vue에는 이를 감지할 수 있는 내장된 방법이 없습니다. 돌연변이 관찰자를 사용하는 것입니다. a 매우 깔끔한 방법: 🎜
<template>
  <div>
    <h2>{{ heading }}</h2>
    <Icon
      :type="iconType"
      :size="iconSize"
      :colour="iconColour"
    />
  </div>
</template>
로그인 후 복사
로그인 후 복사
🎜 8. 로컬 스타일과 전역 스타일을 함께 혼합 🎜🎜 일반적으로 스타일을 사용할 때 단일 구성 요소로 범위가 지정되기를 원합니다. 🎜
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,
    },
  },
};
로그인 후 복사
로그인 후 복사
🎜 필요한 경우 범위가 지정되지 않은 스타일 블록을 추가할 수도 있습니다. 글로벌 스타일: 🎜
<style>
  /*全局应用*/
  .component p {
    margin-bottom: 16px;
  }
</style>

<style scoped>
  /*范围限定于此特定组件*/
  .component {
    background: green;
  }
</style>
로그인 후 복사
로그인 후 복사

9. 覆盖子组件的样式——正确的方法

Scoped CSS 比较容易保持整洁,并且不会意外地将样式渗入应用程序的其他部分。但有时你需要覆盖子组件的样式,并突破该范围。Vue 有一个deep专门用于此的选择器:

<style scoped>
/* 覆盖子组件的 CSS,同时保持样式范围*/
.my-component >>> .child-component {
  font-size: 24px;
}
</style>
로그인 후 복사
로그인 후 복사

注意:如果你使用的是 SCSS 之类的 CSS 预处理器,则可能需要改用/deep/

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

上下文感知组件是“神奇的”——它们可以自动适应周围发生的事情,处理边缘情况,状态共享等等。有 3 种主要类型的上下文感知组件,但是我觉得配置是其中最有趣的一种。

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. 配置

有时需要根据应用程序其余部分的情况更改组件的行为。这样做通常是为了自动处理边缘情况,否则会很麻烦。Popup或者Tooltip应该重新定位自己,这样它就不会溢出页面。但是,如果该组件位于 modal 内部,则它应该重新定位自身,以免溢出modal。如果Tooltip知道它何时在模态内,这可以自动完成。

3. 造型

当你创建了上下文感知 CSS,根据父元素或兄弟元素中发生的情况应用不同的样式。

.statistic {
  color: black;
  font-size: 24px;
  font-weight: bold;
}

/* 在彼此相邻的统计数据之间进行一些分离*/
.statistic + .statistic {
  margin-left: 10px;
}
로그인 후 복사
로그인 후 복사

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

11. 如何使在 Vue 之外创建的变量具有响应性?

如果你从 Vue 外部获得一个变量,那么能够使其具有响应性就很好。这样你就可以在计算道具、观察者和其他任何地方使用它,它就像 Vue 中的任何其他状态一样工作。

当你正在使用 options API,你只需将它放在data组件的部分中:

const externalVariable = getValue();

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

当你在 Vue 3 中使用组合 API,则可以使用refreactive这样:

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

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

// 使用 .value 访问
console.log(reactiveVariable.value);
로그인 후 복사
로그인 후 복사

使用reactive来代替:

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

// 可以完全在 Vue 组件之外完成
const externalVariable = getValue();
// Reactive 仅适用于对象和数组
const anotherReactiveVariable = reactive(externalVariable);

// 直接访问
console.log(anotherReactiveVariable);
로그인 후 복사
로그인 후 복사

如果你仍在使用 Vue 2(就像我们中的许多人一样),你可以使用observable而不是reactive获得完全相同的结果。

12. 在 v-for 中解构

你知道你可以在 v-for 中解构吗?

<li
  v-for="{ name, id } in users"
  :key="id"
>
  {{ name }}
</li>
로그인 후 복사
로그인 후 복사

众所周知,你可以使用这样的元组从 v-for 中获取索引:

<li v-for="(value, key) in [
  &#39;Hai Yong&#39;,
  &#39;Frozen&#39;,
  &#39;Web Beginner&#39;
]">
  {{ index + 1 }} - {{ value }}
</li>
로그인 후 복사
로그인 후 복사

使用对象时,你还可以抓住key:

<li v-for="(value, key) in {
  name: &#39;Hai Yong&#39;,
  released: 2021,
  director: &#39;A blogger&#39;,
}">
  {{ key }}: {{ value }}
</li>
로그인 후 복사
로그인 후 복사

也可以结合这两种方法,获取属性的键和索引:

<li v-for="(value, key, index) in {
  name: &#39;Hai Yong&#39;,
  released: 2021,
  director: &#39;A blogger&#39;,
}">
  #{{ index + 1 }}. {{ key }}: {{ value }}
</li>
로그인 후 복사
로그인 후 복사

13. 在 Vue 中循环一个范围

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

<template>
  <ul>
    <li v-for="n in 5">项目#{{ n }}</li>
  </ul>
</template>
로그인 후 복사
로그인 후 복사

显示效果:

  • 项目#1
  • 项目#2
  • 项目#3
  • 项目#4
  • 项目#5

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

14. 观察组件中的任何内容

你的组件中的任何响应都可以被观察到:

export default {
  computed: {
    someComputedProperty() {
      // 更新计算道具
    },
  },
  watch: {
    someComputedProperty() {
      // 当计算的 prop 更新时做一些事情
    }
  }
};
로그인 후 복사
로그인 후 복사

你可以看:

  • 计算道具
  • 道具
  • 嵌套值

如果你使用组合 API,只要它是一个refreactive对象就可以监视任何值,。

15. 窃取道具类型

从子组件复制 prop 类型,只是为了在父组件中使用它们。但窃取这些道具类型比只是复制它们要好得多。

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

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

为了让它工作,我们需要添加正确的道具类型,从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 类型开始偏离组件中的 prop 类型,将引入错误Icon

所以这就是为什么我们会窃取它们:

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

除了在我们的示例中,我们在每个道具名称的开头添加了“icon”。所以我们必须做一些额外的工作来实现这一点:

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

const iconProps = {};

// Do some processing beforehand
Object.entries(Icon.props).forEach((key, val) => {
  iconProps[`icon${key[0].toUpperCase()}${key.substring(1)}`] = val;
});

export default {
  components: { Icon },
  props: {
    ...iconProps,
    heading: {
      type: String,
      required: true,
    },
  },
};
로그인 후 복사

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

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

16. 检测元素外部(或内部)的点击

有时我们需要检测点击是发生在特定元素el内部还是外部。这是我们通常使用的方法:

window.addEventListener(&#39;mousedown&#39;, e => {
  // 获取被点击的元素
  const clickedEl = e.target;

  // `el` 是你正在检测外部点击的元素
  if (el.contains(clickedEl)) {
    // 单击“el”内部
  } else {
    // 在`el`之外点击
  }
});
로그인 후 복사

17. 递归槽

我们是否可以v-for只使用模板来制作一个组件?在此过程中,我发现了如何递归地使用slot。

这是组件的样子:

<!-- VFor.vue -->
<template>
    <div>
        <!-- 渲染第一项 -->
    {{ list[0] }}
        <!-- 如果我们有更多的项目可以继续,但需要离开我们刚刚渲染的项目 -->
    <v-for
      v-if="list.length > 1"
            :list="list.slice(1)"
        />
    </div>
</template>
로그인 후 복사

如果你想用作用域slot来做这件事——为什么不呢?!— 只需要进行一些调整:

<template>
  <div>
    <!-- 将项目传递到要渲染的slot中 -->
    <slot v-bind:item="list[0]">
      <!-- Default -->
      {{ list[0] }}
    </slot>

    <v-for
      v-if="list.length > 1"
      :list="list.slice(1)"
    >
      <!-- 递归向下传递作用域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. 组件元数据

并不是你添加到组件的每一点信息都是状态。有时你需要添加一些元数据来为其他组件提供更多信息。

例如,如果你要为 Google Analytics 等分析仪表板构建一堆不同的小部件:

당신이 알아야 할 25가지 Vue 팁

如果你希望布局知道每个小部件应占用多少列,你可以将其作为元数据直接添加到组件上:

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` 包含组件的所有元数据
    console.log(`Using ${this.$options.metadata} columns`);
  },
};
로그인 후 복사

请记住,此元数据对于组件的每个实例都是相同的,并且不是响应式的。

其他用途包括(但不限于):

  • 保留各个组件的版本号
  • 用于构建工具的自定义标志以区别对待组件
  • 向组件添加自定义功能,超出计算道具、数据、观察者等。

19. 多文件单文件组件

这是 SFC 的一个鲜为人知的功能。你可以像使用常规 HTML 文件一样导入文件:

<!-- "single" 文件组件 -->
<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 传递点击处理程序、a11y 属性等。 -->
      <Button v-bind="bind">
        <!-- 使用我们自己的“...”图标,此按钮没有文字 -->
        <template #icon>
          <svg src="./ellipsis.svg" />
        </template>
      </Button>
    </template>
  </Menu>
</template>
로그인 후 복사

这里我们使用了一个Menu组件,但是在触发它打开的按钮上添加了一个“...”(省略号)图标。可能并不不值得用它来制作可重用的组件,因为它只有几行。每次我们想使用Menu这样的时候,我们不能只添加图标吗?但这OverflowMenu将使用数十次,现在如果我们想要更新图标或其行为,我们可以很容易地做到。而且使用起来也简单多了!

<template>
  <OverflowMenu
    :menu-items="items"
    @click="handleMenuClick"
  />
</template>
로그인 후 복사

21. 从组件外部调用方法

你可以通过给它一个从组件外部调用方法ref

<!-- Parent.vue -->
<template>
  <ChildComponent ref="child" />
</template>
로그인 후 복사
// Parent.vue 中的某个地方
this.$refs.child.method();
로그인 후 복사
로그인 후 복사

通常,我们使用道具和事件在组件之间进行通信。道具被发送到子组件,事件被发送回父组件。

<template>
  <ChildComponent
    :tell-me-what-to-do="someInstructions"
    @something-happened="hereIWillHelpYouWithThat"
  />
</template>
로그인 후 복사

但有时你可能会遇到需要父组件触发子组件中的方法的情况。这是只有向下传递道具不起作用的地方。可以向下传递一个布尔值并让子组件监视它:

<!-- Parent.vue -->
<template>
  <ChildComponent :trigger="shouldCallMethod" />
</template>
로그인 후 복사
// Child.vue
export default {
  props: [&#39;trigger&#39;],
  watch: {
    shouldCallMethod(newVal) {
      if (newVal) {
        // 当触发器设置为 `true` 时调用该方法
        this.method();
      }
    }
  }
}
로그인 후 복사

这工作正常,但仅限于第一次调用。如果你需要多次触发此操作,则必须清理并重置状态。然后逻辑看起来像这样:

  • Parent 组件传递truetriggerprop

  • Watch被触发,Child组件调用方法

  • Child 组件发出一个事件告诉 Parent 组件该方法已成功触发

  • Parent 组件重置triggerfalse,因此我们可以再次执行此操作

啊。

相反,如果我们在子组件上设置ref ,我们可以直接调用该方法:

<!-- Parent.vue -->
<template>
  <ChildComponent ref="child" />
</template>
로그인 후 복사
// Parent.vue 中的某个地方
this.$refs.child.method();
로그인 후 복사
로그인 후 복사

我们打破了“props down, events up”规则,打破了封装,但它更清晰、更容易理解值得这样做!

有时,“最佳”解决方案最终会成为最差的解决方案。

22. 观察数组和对象

使用观察者最棘手的部分是有时候它似乎不能正确触发。一般都是因为你试图查看一个数组或一个对象,但没有设置deeptrue

export default {
  name: &#39;ColourChange&#39;,
  props: {
    colours: {
      type: Array,
      required: true,
    },
  },
  watch: {
    // 使用对象语法而不仅仅是方法
    colours: {
      // 这将让 Vue 知道查看数组内部
      deep: true,

      // 我们必须将我们的方法移动到处理程序字段
      handler()
        console.log(&#39;颜色列表已更改!&#39;);
      }
    }
  }
}
로그인 후 복사

使用 Vue 3 的反应式 API 看起来像这样:

watch(
  colours,
  () => {
    console.log(&#39;颜色列表已更改!&#39;);
  },
  {
    deep: true,
  }
);
로그인 후 복사

如果你想了解更多信息,可以参阅Vue 3Vue 2的文档。

23. 与 Vue Router 深度链接

你可以在 URL 中存储(一些)状态,允许你直接跳转到页面上的特定状态。

比如你可以加载一个已选择日期范围过滤器的页面:

someurl.com/edit?date-range=last-week
로그인 후 복사

这对于用户可能共享大量链接的应用程序部分、服务器呈现的应用程序或在两个独立应用程序之间传递比常规链接通常提供的信息更多的信息非常有用。

你可以存储过滤器、搜索值、模式是打开还是关闭,或者我们滚动到的列表中的位置——非常适合无限分页。

使用vue-router这样的方式获取查询(这也适用于 Nuxt 和 Vuepress 等大多数 Vue 框架):

const dateRange = this.$route.query.dateRange;
로그인 후 복사

要更改它,我们使用RouterLink组件并更新query

<RouterLink :to="{
  query: {
    dateRange: newDateRange
  }
}">
로그인 후 복사

24. 模板标签的另一种用途

template标签可以在模板内的任何地方使用,以更好地组织代码。

我喜欢用它来简化v-if逻辑,有时v-for也是。

在这个例子中,我们有几个元素都使用相同的v-if条件:\

<template>
  <div class="card">
    <img  src="imgPath" / alt="당신이 알아야 할 25가지 Vue 팁" >
    <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-iftemplate标签本身:\

<template>
  <div class="card">
    <img  src="imgPath" / alt="당신이 알아야 할 25가지 Vue 팁" >
    <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 等错误跟踪服务挂接到这些处理程序中以记录错误,但你也可以使用它们来更优雅地处理错误以获得更好的用户体验。

例如,如果错误未得到处理,应用程序不仅会崩溃,还可以显示整页错误屏幕并让用户刷新或尝试其他操作。

在 Vue 3 中,错误处理程序仅适用于模板和观察程序错误,但 Vue 2 错误处理程序几乎可以捕获所有内容。两个版本中的警告处理程序仅适用于开发。

(学习视频分享:vuejs教程web前端

위 내용은 당신이 알아야 할 25가지 Vue 팁의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
vue
원천:juejin.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿