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

作者:鲸腾FE,来自鲸腾网络。是一支专注于 Web 前端的开发团队,并在 Web 前端领域积累了多年的疑难问题解决经验。崇尚高效、优质、成长、自由、快乐。

来源:恒生LIGHT云社区

一、定义

vue中插槽指的就是在组件中用标签 <slot></slot>定义的预留位置,该标签有个name属性,使用者可以根据实际情况对其设置,或者不设置都可以。设置了name属性的插槽叫做【具名插槽】,没有设置name属性的叫【不具名插槽】。在父组件中使用子组件时,可以在使用子组件标签内通过v-slot声明插槽名或不声明插槽名的方式往子组件中的具名插槽或者不具名插槽中写入html代码。

插槽使用的特性在于:在父组件中使用子组件标签的时候可以往子组件内写入代码。

二、使用步骤

  1. 子组件中用<slot>标签定义插槽
  2. 父组件中使用子组件时利用v-slot在子组件标签内写入html代码。
  3. v-slot搭配<template>标签使用

三、插槽使用场景

这样的场景:一个父组件,一个子组件。

父组件

<template>
  <div class="slot-content">
    <Student v-slot:default>wangxiaoer</Student>
  </div>
</template>

子组件

<template>
  <div>
    <span>name: </span>
  </div>
</template>

在这里,父组件想直接在标签中插入名字。但是事与愿违。通过浏览器的渲染,我们发现“wangxiaoer"字段并没有显示。如下图3.1。如果我们想在父组件中写入代码并在子组件成功渲染,我们就可以用插槽帮助我们实现。

插槽3-1.png

(图3.1)

四、插槽使用方法

我们对上面子组件的代码进行改造

<template>
  <div>
    <span>name: </span>
    <slot></slot>
  </div>
</template>

父组件代码不变,这时候我们发现,浏览器上出现了在父组件往组件插入到”wangxiaoer“。如图4.1

插槽4_1.png

(图4.1)

结合定义,我们会发现,这个场景中我们使用的是不具名插槽。那么具名插槽怎么使用呢?我们继续对上面的代码进行改造

子组件改造如下

<template>
  <div>
    <div>
      <span>name: </span>
      <slot></slot>
    </div>
    <div>
      <span>age:</span>
      <slot name="age-slot"></slot>
    </div>
  </div>
</template>

父组件改造如下

<template>
  <div class="slot-content">
    <Student v-slot:default>wangxiaoer</Student>
    <Student>
      <template v-slot:default>
        wangdagang
      </template>
      <template v-slot:age-slot>
         18岁
      </template>
    </Student>
  </div>
</template>

效果如下图4.2。

插槽4.2.png

(图4.2)

可以看出,v-slot: default指的是不具名插槽。当我们给v-slot赋值正常的字符串时,这个字符串就是插槽的名称。

五、作用域插槽

作用域插槽在官网中是这么描述的:父组件模板的所有内容都会在父级作用域内编译。简单的说,就是父组件中不能直接用子组件定义的data数据。而scope的出现就是解决了这样的问题。

使用方法:

在v-slot声明后面用 = 连接作用域插槽完成作用域插槽的声明,例子(v-slot:defaule="scope")

有这样的场景:一个子组件,一个父组件

父组件

<template>
  <div>
    <Teacher>
      <template
        v-slot:teacher-info>
        <div v-for="item in list">
          父组件传入的内容
          <div>name: {{item.name}}</div>
          <div>age: {{item.age}}</div>
        </div>
      </template>
    </Teacher>
  </div>
</template>

子组件

<template>
  <div>
    这是子组件
    <slot name="teacher-info"></slot>
  </div>
</template>

<script>
  export default {
    name: 'SlotScope',
    components: {},
    data () {
      return {
        list: [{
          name: 'zhangyue',
          age: '18'
        }, {
          name: 'liuyue',
          age: '20'
        }, {
          name: 'zhaoyue',
          age: '22'
        }]
      };
    },
    methods: {}
  }
</script>

从代码逻辑上看,显而易见,该场景是父组件在渲染子组件时利用子组件中的list做处理。但是根据浏览器的渲染结果来看是失败了。如图5.1

插槽5_1.png

(图5.1)

要实现上面场景的需求,就可以使用scope来实现需求。代码改造如下

父组件代码改造如下

<template>
  <div>
    <Teacher>
      <template
        v-slot:teacher-info="scope">
        <div v-for="item in scope.list">
          父组件传入的内容
          <div>name: {{item.name}}</div>
          <div>age: {{item.age}}</div>
        </div>
      </template>
    </Teacher>
  </div>
</template>

此时可以看到浏览器成功将我们想实现的效果渲染出来了。如图5.2

插槽5_2.png

(图5.2)

{{o.name}}
{{m.name}}

猜你喜欢

转载自my.oschina.net/u/3620858/blog/5476436
今日推荐