pekonchan/Blog

vue3插槽用法

Opened this issue · 0 comments

前言

关于vue3的插槽用法,在2.6.0版本前,是旧用法;在2.6.0 ~ 3.0版本,新旧用法兼容;但是在vue3之后,旧用法就不支持了。因此有必要掌握新用法。

slot

这部分内容还是原来的情况,并没有新语法,写出来是为了文章内容的完整性。

在自定义组件内部,用slot标签来表示接受的插槽内容,预留展示位置。

通过name属性来指定该插槽的名字

<slot />
<slot name="header" />

如果没name属性,那就是一个默认插槽了,只会有一个默认插槽。

默认插槽除了预留位置外,还起到了后备内容的作用,即如果你使用组件时,没有插槽内容的话,就会显示默认插槽的内容。

v-slot

新用法是引入了v-slot指令,该指令只能用在template标签上(除了下面说到的独占默认插槽缩写法外)。

首先我们要知道用插槽的两个个场景:

  • 具名插槽,指定名字的插槽应用
  • 插槽作用域,指定插槽的作用域

新旧用法都是围绕这两个场景来解决问题的。

具名插槽

使用组件时,v-slot用参数就能指定插槽名了

<custom>
    这是默认插槽内容
    <template v-slot:header>这是header插槽内容</template>
</custom>

实际上,上面的默认插槽是简写,原本是:

<custom>
    <template v-slot:default>这是默认插槽内容</tempalte>
    <template v-slot:header>这是header插槽内容</template>
</custom>

这时候,对应的slot会变换成对应的插槽内容

插槽作用域

首先要明白这个的使用场景,一个组件(记做A)是有自己的作用域的,你用这个组件的所在页面(记做B,实际上也是一个组件)也有自身的作用域。如果你在B页上用了A组件,A下有插槽,想在该插槽上执行一些操作要利用A作用域下的某个值,那么这时你就需要指定该插槽的作用域为A了,因为默认情况下,用在该插槽上的数据的作用域都是属于B的。

明白上面的背景后,接着我们要知道,如果任何人都可以随意改变组件内部的变量的话,那就失去了组件的独立性了,我们也知道vue是提倡单向改变的数据的,所以如果要指向组件的作用域里的变量的话,前提是你的组件要往外暴露这么一个“入口”,告诉别人,你允许别人在插槽上使用你内部的哪些数据,这个我们叫做插槽prop

<slot v-bind:myData="myData></slot>

如上,插槽上有一个名为myDataprop,值为该插槽所在组件里的作用域下的myData变量。上面内容即告诉别人,这个组件的默认插槽上往外暴露了一个叫myData的入口,给父组件用来引用,起到访问内部myData变量的作用

要知道,上面的myData不一定要相同名的,只是一般都会是而已。父组件访问的是属性上的myData,只是值的变量名刚好也叫myData

使用v-slot指定作用域很简单,就是该指令的值了。

<!--在B页里-->
<custom>
    <template v-slot:default="scopeA">
        {{scopeA.myData}}
    </template>
</custom>

以上为使用方法,父组件指定了名为“scopeA”的作用域,指向custom组件的作用域,然后引用之前暴露的myData。默认插槽的:default可省略

在支持es6语法的环境下,上面可以写成以下更方便

<custom>
    <template v-slot="{ myData }">
        {{myData}}
    </template>
</custom>

独占默认插槽缩写

当你使用组件时,只用到了一个默认插槽,没有其他插槽的话(虽然官方资料上说没有其他具名插槽,但是发现只要出现不是一个插槽,包括内嵌插槽,仍然不能使用),v-slot是可以直接写在组件上的,如

<custom>
    <template v-slot="{ myData }">
        <p>{{myData}}</p>
    </template>
</custom>

<!--上面可缩写为:-->
<custom v-slot="{ myData }">
    <p>{{myData}}</p>
</custom>

除了这种情况外,任何其他情况v-slot都只能写在template上。

注意上面的条件,

只用到了一个默认插槽,没有其他具名插槽的

v-slot的缩写

v-bindv-on一样,v-slot也有缩写,用#来表示,如

<custom>
    <p #default="{ myData }">{{myData}}</p>
</custom>

要使用这种缩写,那么指令参数是不可省略的,意味着默认插槽的default不能省略。

与旧语法的不同

简单说一下旧语法的不同点,说太多怕大家记混淆了就更惨了。

  • 具名插槽:以前应用具名插槽时,用slot="slotName"这个属性就能指明当前代码是属于哪个插槽的了,可以用在template或任意html标签上,但是新语法v-slot只能用在template标签上,指令参数为插槽名。
  • 插槽作用域:以前是在插槽内容上(即用了slot="slotName"的标签上或默认插槽标签上)用slot-scope="scopeName"来指明作用域,但是新语法v-slot只能用在template标签上,同样是值为域名。