Do something a little different here

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

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

watch {

‘$route.query.id’() {

// …

}

}

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

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

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

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

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

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

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

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

普通写法:

<template #header=“tableAttributes”>

不使用 template:

<DataTable #header=“tableAttributes”>

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

6. 有条件地渲染插槽

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

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

const $slots = {

default: ,

icon: ,

button: ,

};

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

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

Here are some slots

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

<template #second>

This will be applied to the second slot.

$slots = { second: }

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

A wrapped slot

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

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

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

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

  • 当使用封装的div来添加默认样式时

  • 插槽是空的

  • 如果我们将默认内容与嵌套槽相结合

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

This is a pretty great component, amirite?

<button @click=“$emit(‘click’)”>Click me!

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

This is a pretty great component, amirite?

<button @click=“$emit(‘click’)”>Click me!

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

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

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

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

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

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

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

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

Vue有一个 deep 选择器:

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

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

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

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

1.状态共享

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

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

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

Mustard Ketchup
Relish

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中使用解构吗?

v-for=“{ name, id } in users”

:key=“id”

{{ name }}

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

‘Lion King’,

‘Frozen’,

‘The Princess Bride’

]">

{{ index + 1 }} - {{ movie }}

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

name: ‘Lion King’,

released: 2019,

director: ‘Jon Favreau’,

}">

{{ key }}: {{ value }}

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

name: ‘Lion King’,

released: 2019,

director: ‘Jon Favreau’,

}">

#{{ index + 1 }}. {{ key }}: {{ value }}

13. 在指定范围内循环

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

    • Item #{{ n }}
    • 渲染结果:

      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组件。

      {{ heading }}

      <Icon

      :type=“iconType”

      :size=“iconSize”

      :colour=“iconColour”

      />

      为了让它工作,我们需要添加正确的 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组件。在这个过程中,我也发现了如何递归地使用槽。

      {{ list[0] }}

      <v-for

      v-if=“list.length > 1”

      :list=“list.slice(1)”

      />

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

      {{ list[0] }}

      <v-for

      v-if=“list.length > 1”

      :list=“list.slice(1)”

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

      {{ item }}

      18. 组件元数据

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

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

      3605934229-60fc46222c6ff_fix732.png

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

      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);

      },

      };
      自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

      深知大多数前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

      因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

      img

      既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!

      由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

      如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:前端)

      最后

      一个好的心态和一个坚持的心很重要,很多冲着高薪的人想学习前端,但是能学到最后的没有几个,遇到困难就放弃了,这种人到处都是,就是因为有的东西难,所以他的回报才很大,我们评判一个前端开发者是什么水平,就是他解决问题的能力有多强。

      分享一些简单的前端面试题以及学习路线给大家,狂戳这里即可获取

      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);

      },

      };
      自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

      深知大多数前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

      因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

      [外链图片转存中…(img-QyRglqYH-1712861607737)]

      [外链图片转存中…(img-YujActKn-1712861607738)]

      既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!

      [外链图片转存中…(img-4dLLApXS-1712861607738)]

      由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

      如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:前端)

      最后

      一个好的心态和一个坚持的心很重要,很多冲着高薪的人想学习前端,但是能学到最后的没有几个,遇到困难就放弃了,这种人到处都是,就是因为有的东西难,所以他的回报才很大,我们评判一个前端开发者是什么水平,就是他解决问题的能力有多强。

      分享一些简单的前端面试题以及学习路线给大家,狂戳这里即可获取

      [外链图片转存中…(img-xwwvy8A1-1712861607738)]

    Logo

    前往低代码交流专区

    更多推荐