vue插槽slot理解

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了vue插槽slot理解相关的知识,希望对你有一定的参考价值。

参考技术A

vue的插槽用法,官方文档写的内容个人感觉有点乱,不自己梳理一下的话,使用的时候也容易懵逼,下面是我对vue插槽使用的理解:

slot概念源于web components规范草案(地址: https://github.com/WICG/webcomponents/blob/gh-pages/proposals/Slots-Proposal.md )
vue官网关于插槽的文档中,第一句话即说明了vue的slot插槽设计源于web components,具体内容可以自行了解,这里只说vue框架下slot的用法。

概念: slot可将 父组件 子组件标签里 写的 content 渲染到子组件 对应 的地方

先说通用性用法,再说特殊情况会让人比较容易接受。这里以最具通用性的写法,以 具名插槽 的写法为例子展开
父组件中:

子组件中

渲染结果:

父组件template标签上的v-slot指令与子组件的slot标签的name属性,通过绑定一样的值,形成一一对应的关系。
父组件中:

子组件中:

注意,上述例子中,都有v-slot绑定default属性的情况,这里需要说明下,vue中的插槽用法,default属性的模板和插槽存在特殊的对应情况,而比较容易混乱的点就在这里,这也是vue官网插槽文档让人看得很蒙圈的地方,因为官网并没有给我们分区域的讲述通用情况和特殊情况,而是穿插着讲,让人容易理不清楚关系。

子组件的slot标签中的值可以写入内容,这部分内容会在没有对应的模板内容的时候,作为默认值展示
父组件

子组件

渲染结果

具名插槽的写法具备通用性,学会了具名插槽写法,那么插槽的用法已经能够掌握8成了。下面将展开的是插槽中的特殊对应关系

------------ 默认的default模板和插槽 -----------
父组件

子组件情形1

子组件情形2

渲染结果都是

由于两种情形中都没有name属性是test的插槽,所以渲染结果中没有出现test模板里的内容。

上述例子中涵盖了2个知识点,首先通过子组件情形2能得到渲染结果,可以得出一个结论:

default模板的内容必定会渲染到defalut插槽中,所以,通过子组件情形1能得出渲染结果,也可以得出一个结论:

最后还需要注意,模板和插槽的对应关系是1对多的关系。即同名模板只能有一个,但是同名插槽可以有无数个,会同时渲染

以上内容涵盖了9成的插槽用法,足以满足日常使用。下面将要对插槽作用域问题展开讲解

很简单
1.模板内容一般都是在父组件,所以模板内容的作用域自然是父组件的作用域,父组件的动态内容基本上取自父组件的变量或函数,但是有特殊情况可以读取到子组件传出来的值,第3点会讲。

2.同理,插槽一般都是在子组件,所以作用域自然在子组件,比如子组件插槽中放入了动态内容作为默认值,该动态内容必定取值于子组件的变量,也只能读取到子组件的变量和函数

3.特殊情况,父组件可以用子组件传出来的值,这个时候会有写法上的变化:
子组件

父组件正常调用

父组件解构对象调用

渲染结果

v-slot指令可以变成缩写的写法,类似v-bind缩写为:,v-on缩写为@,v-slot可以缩写为#
例如

等价于

这里出现了v-slot指令直接绑定在子组件标签名上的情况,使用场景是,当前模板只有一个default模板,并且需要获取子组件传来的值时,才能这样使用。

不接受传值的情况,会报错

非default模板,也会报错
子组件

父组件

除了default模板外,还存在其他模板时,也会报错

以上基本总结了插槽的所有用法,其中第5点和第8点的特殊情况都是针对default模板的,这一点一定要分清楚。

还有1点很关键的知识,即default模板和插槽不算是具名模板和插槽,第8点的非default模板会报错的原因,即该特殊情况不支持具名模板和插槽。但是default模板和插槽在平时写的时候可以用具名模板和插槽的写法,也可以用省略的写法,即第5点描述的情况。

vue中的插槽slot理解

本篇文章参考赛冷思的个人博客

1.函数默认传参

在我们写js函数我们的可能会给他们一个默认的参数,写法是

function show(age,name){
  var age = age || 20;
  var name = name || 张三;
console.log(age,name); } show();
// 20,张三 show(18,"命名") // 18,明明

如果用户不传入参数,那么会输出默认值,如果用户传入,会输出传入的值,这种写法很灵活

vue中的组件,也可以有默认的模板,当我们调用一个组件,啥都不传时,显示我们定义的默认模板,当我们传了自定义模板时,就应该使用我们自定义的模板,来替换默认模板,那么,今天说的slot,其实它就是实现的这个功能,可以理解为函数的传参。下面以类似官方的例子进行解释。

现在有个一个模板 child

<div>
      <h2>我是子组件的标题</h2>
      <slot>
        <p>当父组件调用我时,没有传自定义内容时,我就会显示了,如果传了自定义内容,我就不显示了。</p>
      </slot>
</div>

slot中的就是默认参数,如果我们不传入参数

<child></child>就会被渲染成

<div>
      <h2>我是子组件的标题</h2>
        <p>当父组件调用我时,没有传自定义内容时,我就会显示了,如果传了自定义内容,我就不显示了。</p>
</div>

如果我们传入参数

<child><p>这是我自定义的内容,覆盖子组件slot中的内容</p></child>渲染为

    <div>
          <h2>我是子组件的标题</h2>
          <p>这是我自定义的内容,覆盖子组件slot中的内容</p>
    </div>     

我们可以看到child中的元素会把模板中的内容改变,就好像我们传入的参数一样,所有理解为默认模板

但是可以看到,这种方式过于粗暴,并且只能定义一块默认内容,不是很方便,所以官方说了,slot还提供了一个具名功能,意思就是,在子组件定义slot时,加个标识,在父组件调用,自定义内容时,也加上标识,这样就实现了可以在任意地方定义默认内容,下面有请具名slot,其实就是给slot起个名字

<div class="container">
      <header>
        <slot name="header"><h1>默认header</h1></slot>
      </header>
      <main>
        <slot><p>默认main</p></slot>
      </main>
      <footer>
        <slot name="footer"><p>默认footer</p></slot>
      </footer>
</div>

上面的是子组件,我们给每一个slot一个name属性,如果是默认值的话,name是没有什么作用的,在传参时,我们可以让child中的元素,加上slot属性

<div>
      <child>
          <h1 slot=‘header‘>自定义标题</h1>
          <p slot=‘footer‘>自定义底部</p>
          <p>自定义main</p>
      </child>
</div>

所以,我们的child最后就被渲染成了

<div>
      <div class="container">
          <header>
            <h1>自定义标题</h1>
          </header>
          <main>
            <p>自定义main</p>
          </main>
          <footer>
            <p>自定义底部</p>
          </footer>
    </div>
</div>

在子组件定义slot加个name属性值,在父组件调用时,加上slot属性,值就是子组件中slot的name属性值,这样就会自动定位到对应的slot中,就实现了多个地方定义默认内容。


以上是关于vue插槽slot理解的主要内容,如果未能解决你的问题,请参考以下文章

Vue插槽理解

大前端之vue插槽slot

Vue插槽slot理解与初体验 ~

Vue 开发之插槽(slot)的理解和使用

vue插槽

简单理解vue的slot插槽