>  기사  >  웹 프론트엔드  >  꼭 써봐야 할 Vue 스킬 25가지 상세 정리!

꼭 써봐야 할 Vue 스킬 25가지 상세 정리!

WBOY
WBOY앞으로
2022-01-27 17:33:372232검색

이 기사에서는 Vue 사용에 대한 25가지 팁을 제공합니다. 유용한 팁이 많고 일부는 까다롭고 일부는 거의 매일 사용되며 일부는 더 고급이지만 모두 유용합니다. 모두에게 도움이 되기를 바랍니다.

꼭 써봐야 할 Vue 스킬 25가지 상세 정리!

더 나은 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>
  <slot>
    <!-- Used if no slot is provided -->
    Click me
  </slot>
</button>

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

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

<template>
  <button>
    <slot>
      <p>
        {{ text }}
      </p>
    </slot>
  </button>
</template>

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

<!-- Uses default functionality of the component -->
<buttonwithextensionpoint></buttonwithextensionpoint>

<buttonwithextensionpoint>
  <p>
    Do something a little different here
  </p>
</buttonwithextensionpoint>

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

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

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

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

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

<complicatedchart></complicatedchart>

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

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

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

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

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

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

普通写法:

<datatable>
  <template>
    <tableheader></tableheader>
  </template>
</datatable>

不使用 template:

<datatable>
  <tableheader></tableheader>
</datatable>

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

6. 有条件地渲染插槽

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

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

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

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

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

<!-- Slots.vue -->
<template>
  <p>
    </p>
<h2>Here are some slots</h2>
    <slot></slot>
    <slot></slot>
    <slot></slot>
  
</template>

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

<template>
  <slots>
    <template>
      This will be applied to the second slot.
    </template>
  </slots>
</template>
$slots = { second: <vnode> }</vnode>

我们可以在我们的组件中使用这一点来检测哪些插槽已经被应用到组件中,例如,通过隐藏插槽的包装元素。

<template>
  <p>
    </p>
<h2>A wrapped slot</h2>
    <p>
      <slot></slot>
    </p>
  
</template>

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

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

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

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

  • 当使用封装的p来添加默认样式时
  • 插槽是空的
  • 如果我们将默认内容与嵌套槽相结合

例如,当我们在添加默认样式时,我们在插槽周围添加一个p:

<template>
  <p>
    </p>
<h2>This is a pretty great component, amirite?</h2>
    <p>
      <slot>
    </slot></p>
    <button>Click me!</button>
  
</template>

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

<p>
  </p><h2>This is a pretty great component, amirite?</h2>
  <p>
    <!-- 槽中没有内容,但这个p 仍然被渲染。糟糕 -->
  </p>
  <button>Click me!</button>
이 확인 함수는 prop을 받아들이고 prop이 유효하거나 유효하지 않은 경우 true 또는 false를 반환합니다.

단순히 true 또는 false를 전달하여 특정 조건을 제어할 수 없을 때 일반적으로 이 방법을 사용합니다. 🎜🎜버튼 유형이나 경고 유형(정보, 성공, 위험, 경고)이 가장 일반적으로 사용됩니다. 컬러도 활용도가 좋습니다. 🎜🎜🎜2. 기본 콘텐츠 및 확장 포인트 🎜🎜🎜Vue의 슬롯에는 기본 콘텐츠가 있어 사용하기 쉬운 구성 요소를 만들 수 있습니다. 🎜
<!-- 可惜这个事件不存在 -->
<slot></slot>
🎜기본 슬롯을 사용하는 가장 좋은 방법은 이를 사용하여 확장 지점을 만드는 것입니다. 🎜🎜컴포넌트의 어떤 부분이라도 가져다가 슬롯에 캡슐화한 다음 외부에서 원하는 대로 컴포넌트의 해당 부분을 덮어쓸 수 있습니다. 기본적으로는 여전히 동일한 방식으로 작동하지만 그렇게 하면 더 많은 옵션이 제공됩니다. 🎜
export default {
  mounted() {
    // 当有变化时调用`update`
    const observer = new MutationObserver(this.update);

    // 监听此组件的变化
    observer.observe(this.$el, {
      childList: true,
      subtree: true
    });
  }
};
🎜 이제 이 구성 요소를 다양한 방법으로 사용할 수 있습니다. 단순, 기본 방식 또는 사용자 정의 방식. 🎜
<style>
  .component {
    background: green;
  }
</style>
🎜🎜3. 따옴표를 사용하여 중첩된 속성 듣기 🎜🎜🎜모를 수도 있지만 따옴표를 사용하면 중첩된 값을 직접 쉽게 들을 수 있습니다. 🎜
<style>
  /* 全局 */
  .component p {
    margin-bottom: 16px;
  }
</style>

<style>
  /* 在该组件内有效 */
  .component {
    background: green;
  }
</style>
🎜🎜4 v를 사용해야 하는 경우를 알아보세요. -if (및 이를 피해야 하는 경우) 🎜🎜🎜v-if를 사용하는 대신 때로는 v-show를 사용하면 성능이 더 높아집니다. 🎜
<style>
.my-component >>> .child-component {
  font-size: 24px;
}
</style>
🎜v-if를 켜거나 끄면 요소가 생성되고 완전히 파괴됩니다. 대신 v-show는 요소를 생성하고 거기에 그대로 두고 스타일을 display: none으로 설정하여 숨깁니다. 🎜🎜전환하는 구성 요소의 렌더링 비용이 높을 경우 더 효율적입니다. 🎜🎜반대로, 비용이 많이 드는 구성 요소를 즉시 실행할 필요가 없다면 v-if를 사용하면 렌더링을 건너뛰고 페이지 로드 속도를 높일 수 있습니다. 🎜🎜🎜5. 단일 범위 슬롯에 대한 약칭(템플릿 태그 필요 없음) 🎜🎜🎜 범위 지정 슬롯은 매우 흥미롭지만 이를 사용하려면 많은 템플릿 태그도 사용해야 합니다. 🎜🎜 다행스럽게도 단일 스코프 슬롯을 사용하는 경우에만 이를 피할 수 있는 속기가 있습니다. 🎜🎜일반적인 글쓰기: 🎜
<!-- 为简单起见,作为一个单一组件使用 -->
<dropdown></dropdown>

<!-- 分多个组件,更灵活 -->
<select>
  <option>Mustard</option>
  <option>Ketchup</option>
  <p>
    <option>Relish</option>
  </p>
</select>
🎜템플릿을 사용하지 마세요: 🎜
.statistic {
  color: black;
  font-size: 24px;
  font-weight: bold;
}

.statistic + .statistic {
  margin-left: 10px;
}
🎜간단하고 직설적이며 놀랍습니다. 🎜🎜🎜6. 조건부로 슬롯 렌더링 🎜🎜🎜 먼저 어떻게 하는지 살펴보고 슬롯을 숨기려는 이유에 대해 논의해 보겠습니다. 🎜🎜모든 Vue 구성 요소에는 모든 슬롯을 포함하는 특별한 $slots 개체가 있습니다. 기본 슬롯의 키는 default이며 명명된 모든 슬롯은 해당 이름을 키로 사용합니다. 🎜
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);
🎜구성 요소에 하나의 슬롯만 적용하면 해당 슬롯만 $slots 개체에 표시됩니다. 🎜
import { reactive } from 'vue';

//  可以完全在Vue组件之外完成
const externalVariable = getValue();
// reactive 只对对象和数组起作用
const anotherReactiveVariable = reactive(externalVariable);

// Access directly
console.log(anotherReactiveVariable);

  •   {{ name }}
  • 🎜 이를 구성 요소에서 사용하여 슬롯의 래핑 요소를 숨기는 등 구성 요소에 적용된 슬롯을 감지할 수 있습니다. 🎜
    
    
  •   {{ index + 1 }} - {{ movie }}
  • 🎜이제 p 스타일을 적용하는 래퍼는 이 슬롯을 무언가로 채울 때만 렌더링됩니다. 🎜🎜v-if를 사용하지 않고 슬롯이 없으면 불필요한 빈 p를 얻게 됩니다. p의 스타일에 따라 레이아웃이 엉망이 되고 인터페이스가 이상해 보일 수 있습니다. 🎜

    그럼 조건부로 슬롯을 렌더링할 수 있는 이유는 무엇입니까?

    🎜조건부 슬롯을 사용하는 세 가지 주요 이유는 다음과 같습니다.🎜
    • 기본 스타일을 추가하기 위해 캡슐화된 p를 사용하는 경우
    • 슬롯이 비어 있습니다 li>
    • 기본 콘텐츠를 중첩된 슬롯과 결합하는 경우
    🎜 예를 들어 기본 스타일을 추가할 때 슬롯 /code> 주위에 p<li>   {{ key }}: {{ value }} </li>🎜 그러나 상위 구성 요소가 이 슬롯에 콘텐츠를 적용하지 않으면 결국 페이지에 빈 <code>p가 렌더링됩니다. 🎜
    
    
  •   #{{ index + 1 }}. {{ key }}: {{ value }}
  • 🎜해결책은 위에서 언급한 여러 조건을 판단하는 것입니다. 🎜

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

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

    <!-- 可惜这个事件不存在 -->
    <slot></slot>

    不幸的是,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. 将局部和全局的 style混合在一起

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

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

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

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

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

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

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

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

    Vue有一个 deep 选择器:

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

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

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

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

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

    1.状态共享

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

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

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

    <!-- 为简单起见,作为一个单一组件使用 -->
    <dropdown></dropdown>
    
    <!-- 分多个组件,更灵活 -->
    <select>
      <option>Mustard</option>
      <option>Ketchup</option>
      <p>
        <option>Relish</option>
      </p>
    </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 '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中使用解构吗?

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

    
    
  •   {{ index + 1 }} - {{ movie }}
  • 当使用一个对象时,可以这样使用 key

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

    
    
  •   #{{ index + 1 }}. {{ key }}: {{ value }}
  • 13. 在指定范围内循环

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

    <template>
      <ul>
        <li>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>
      <p>
        </p>
    <h2>{{ heading }}</h2>
        <icon></icon>
      
    </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>
        <p>
            <!--  渲染第一项 -->
        {{ list[0] }}
            <!-- 如果我们有更多的项目,继续!但是不要使用我们刚刚渲染的项 -->
        <v-for> 1"
                :list="list.slice(1)"
            />
        </v-for></p>
    </template>

    如果你想用作用域插槽来做这件事,只是需要一些调整

    <template>
      <p>
        <!-- Pass the item into the slot to be rendered -->
        <slot>
          <!-- Default -->
          {{ list[0] }}
        </slot>
    
        <v-for> 1"
          :list="list.slice(1)"
        >
          <!-- Recursively pass down scoped slot -->
          <template>
            <slot></slot>
          </template>
        </v-for>
      </p>
    </template>

    下面是这个组件的使用方法。

    <template>
      <p>
        <!-- 常规列表 -->
        <v-for></v-for>
    
        <!-- 加粗的项目列表 -->
        <v-for>
          <template>
            <strong>{{ item }}</strong>
          </template>
        </v-for>
      </p>
    </template>

    18. 组件元数据

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

    例如,如果正在为谷歌 analytics这样的分析仪表:

    꼭 써봐야 할 Vue 스킬 25가지 상세 정리!

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

    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`);
      },
    };

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

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

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

    19. 多文件单文件组件

    这是**SFC(单文件组件)**的一点已知功能。

    可以像常规HTML文件一样导入文件:

    <template></template>
    <script></script>
    <style></style>

    如果你需要分享样式、文件或其他任何东西,这可能会非常方便。

    20. 可重复使用的组件并不是你所想的那样

    可重复使用的组件不一定是大的或复杂的东西。

    我经常让小的和短的组件可以重复使用。

    因为我没有到处重写这段代码,所以更新它变得更加容易,而且我可以确保每个OverflowMenu的外观和工作方式都完全一样–因为它们是一样的!"。

    <!-- OverflowMenu.vue -->
    <template>
      <menu>
        <!-- 添加一个自定义按钮来触发我们的菜单   -->
        <template>
          <!-- 使用bind来传递click处理程序、a11y 属性等 -->
          <button>
            <template>
              <svg></svg>
            </template>
          </button>
        </template>
      </menu>
    </template>

    在这里,我们采用了一个菜单组件,但在触发它的按钮上添加了一个 ellipsis 图标。(省略号)的图标来触发它的打开。

    这似乎不值得把它做成一个可重复使用的组件,因为它只有几行。难道我们就不能在每次要使用这样的菜单时添加图标吗?

    但是这个OverflowMenu将被使用几十次,现在如果我们想更新图标或它的行为,我们可以非常容易地做到。而且,使用它也更简单了。

    21. 从组件外部调用一个方法

    我们可以从一个组件的外部通过给它一个 ref 用来调用一个方法。

    <!-- Parent.vue -->
    <template>
      <childcomponent></childcomponent>
    </template>
    // Somewhere in Parent.vue
    this.$refs.child.method();

    再解释一下这个问题。

    有时候,“最佳实践”并不适用于你正在做的事情,你需要一个像这样的逃生口。

    通常情况下,我们使用 props 和 events 在组件之间进行交流。props 被下发到子组件中,而events 被上发到父组件中。

    <template>
      <childcomponent></childcomponent>
    </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
    • Watch 被触发,然后 Child 组件调用该方法
    • 子组件发出一个事件,告诉父组件该方法已被成功触发
    • Parent组件将 trigger 重置为 false,所以我们可以从头再来一次

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

    <!-- Parent.vue -->
    <template>
      <childcomponent></childcomponent>
    </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></routerlink>

    24. template 标签的另一个用途

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

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

    在这个例子中,我们有几个元素都使用同一个v-if条件。

    <template>
      <p>
        <img  alt="꼭 써봐야 할 Vue 스킬 25가지 상세 정리!" >
        </p>
    <h3>
          {{ title }}
        </h3>
        <h4>
          {{ subheading }}
        </h4>
        <p>
          <slot></slot>
        </p>
        <socialshare></socialshare>
      
    </template>

    这有点笨拙,而且一开始并不明显,一堆这样的元素被显示和隐藏在一起。在一个更大、更复杂的组件上,这可能是一个更糟糕的情况

    但我们能优化它。

    我们可以使用 template 标签来分组这些元素,并将 v-if 提升到模板 template 本身。

    <template>
      <p>
        <img  alt="꼭 써봐야 할 Vue 스킬 25가지 상세 정리!" >
        </p>
    <h3>
          {{ title }}
        </h3>
        <template>
          <h4>
            {{ subheading }}
          </h4>
          <p>
            <slot></slot>
          </p>
          <socialshare></socialshare>
        </template>
      
    </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 中,错误处理程序只能处理 templatewatcher 错误,但是 Vue2的错误处理程序可以捕获几乎所有错误。这两个版本中的警告处理程序只在开发阶段有效。

    代码部署后可能存在的BUG没法实时知道,事后为了解决这些BUG,花了大量的时间进行log 调试,这边顺便给大家推荐一个好用的BUG监控工具 Fundebug。

    【相关推荐:《vue.js教程》】

    위 내용은 꼭 써봐야 할 Vue 스킬 25가지 상세 정리!의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

    성명:
    이 기사는 csdn.net에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제