Vue组件 - 输入

开始之前

  • 需要你对Vue有一定的了解,最好已阅读过一遍官方的教程。
  • 包含有Vue3的内容,如果你已熟悉Vue2,但还不熟悉Vue3,也不必感到恐惧。
  • 涉及到具体的API使用细节较少。
  • 我将Vue组件分成由三部分组成:输入、内部处理、输出(其实可当作一个函数来理解),这篇文章是关于“输入”的内容。

目录

正文

如何理解“输入”

输入,即向组件传值或能导致组件改变的外部因素。这篇文章将组件的所有输入方式进行了分类整理,以便清晰的了解组件的数据来源和改变的外部源。

组件输入的分类

我将输入分成了两类,一是:显式输入,第二个是:隐式输入。下面我将分别介绍这两种分类。

组件输入的分类

显式输入

显式输入,顾名思义,显式的传给组件的数据。

props

如下所示,利用props显式的向HelloWorld组件传入字符串“Welcome to Your Vue.js App”。你几乎可以借助propsHelloWorld组件传入任何值,但HelloWorld组件的内部需要在props中定义接收的属性名称才行。

    <HelloWorld msg="Welcome to Your Vue.js App" />

💡

  • props传值是 父级子级 传值方式的一种。
  • props传入一个回调函数,也可实现 子级父级 传值。此时,不仅是“输入”也能作为一种“输出”(通过回调函数的参数将值传给 父级)。
  • props中的default可理解为函数参数的默认值。type可理解为函数参数的类型。validator可理解对函数参数的验证。required可理解为函数参数是否为可选参数。
总结

组件输入的分类->显式输入->props

emits

"输入"不仅可以是具体的数值,也可以是一个事件(emits)的回调函数。这个事件即包含了HTML的原生事件,也包括组件自定义的事件。

总结

组件输入的分类->显式输入->emits

$attrs

当向组件传入一个未在propsemits中定义的 attribute 的时候,Vue会默认把值自动添加到根节点的 attribute 中。如下所示,Date组件的节点组成:

    <template>
        <div>
            //其它内容
        </div>
    </template>

我们以如下的方式调用:

    <Date class="my-date" />

实际渲染到DOM中的Date组件为:

    <div class="my-date"> 
        //Date组件渲染出来的其它DOM
    </div>

如上所示,传入的class添加到了<div>上。

但,当组件不止有两个根节点的时候(Vue2只允许有一个根节点,而Vue3允许有多个),Vue将怎么处理了?
Vue将选择权交给了你,使用v-bind="$attrs"将值赋其中任意 一个根 节点。

如果不想要除propsemits定义以外的任何值了? 配置:inheritAttrs: false

如果根节点不想要,而想给子节点了? 使用v-bind="$attrs"将值赋其中任意 一个子 节点。

总结

$attrs属于实例属性,一般用来接收原生HTML元素的属性。是否被使用,完全由组件内部决定。

💡

  • $attrs父级子级 传值方式的一种。

组件输入的分类->显式输入->$attrs

slot

在Vue中可借助插槽(slot)来做内容分发,插槽也可以视为组件的一种“输入”。如下所示,Date组件添加到了HelloWorld组件的default插槽中。

    <HelloWorld>
        <Date msg="Hi" />
    </HelloWorld>

💡

  • 当向Date组件传入msg的值时,是 祖辈级子孙级 传值方式的一种。
  • 当是 作用域插槽 时便是 父级 向 子级 传值方式的一种(将HelloWorld组件内部的值,传给Date组件)。
总结

组件输入的分类->显式输入->slots

directive

这里主要是指自定义指令。那为什么自定义指令会被认为是一种“输入”了?因为自定义指令可以对组件内的DOM元素进行底层操作,影响着组件的状态。关于组件的更多细节可以查看对应的官方文档。

总结

组件输入的分类->显式输入->directives

显式输入总结

下面我来看一个包含所有显式输入的组件使用情况:

  • msg为props
  • class为$attrs
  • click为emits
  • v-hour为自定义directive
  • Date和User组件为slot,其中User组件通过作用域插槽进行了传值
    <HelloWorld msg="Welcome to Your Vue.js App" class="my-hello" @clik="clickFn">
        <Date v-hour="time" />
        <template v-slot:user="slotProps">
            <User :name="slotProps.name" />
        </template>
    </HelloWorld>

进一步观察,我们可以发现:所有的显式输入基本都需要借助指令来实现!($attrs除外)

  • props借助v-bind
  • emits借助v-on
  • slot借助v-slot(默认插槽有时可不显式使用)
  • 自定义指令就更不用说了,它本身就是个指令
关于v-model

v-model指令也是组件中常用的输入源,但其本质是propsemits的语法糖,所以就不算入“输入”里面了。

隐式输入

隐式输入,是指那些除显式输入之外所有能影响组件状态的情况。他并不“显式”传入,却对组件内部起着影响。

inject

在组件内部通过inject可以获取祖辈级传入的数据,因为不是一眼就能看到的“输入”,而且还不一定能知道是哪个组件传入的值,所以注入(inject),我将其归类为隐式输入。

总结

组件输入的分类->隐式输入->inject

mixin

不管是全局混入(mixin)还是只在组件内混入,它都是一种隐式的不易观测的传值和处理方式,所以混入,也被归为隐式输入。

总结

组件输入的分类->隐式输入->mixin

extends

对另一个组件进行扩展(extends),与mixin类似。所以扩展,也是隐式输入的一种。

总结

组件输入的分类->隐式输入->extends

globalProperties

通过app.config.globalProperties添加全局属性(property),可让任何组件实例访问;与直接在Vue的原型链上添加类似。因为它是全局属性,是一种“隐式”传值,所以它是隐式输入的一种。

💡

  • 祖辈级子孙级 传值方式的一种。
总结

组件输入的分类->隐式输入->globalProperties

隐式输入总结

隐式输入一般用于祖孙级间传值或增加组件的复用性。

输入的总结

最后我们来总结下,“输入”共有哪些:

  • 显式输入:
    • props
    • emits
    • $attrs
    • slot
    • directive
  • 隐式输入:
    • inject
    • mixin
    • extend
    • globalProperties

最后

  • 转载请指明出处
  • 不当之处,欢迎交流指正
posted @ 2020-11-08 20:05  路真  阅读(265)  评论(0编辑  收藏  举报