十一、插槽

插槽介绍
  • 插槽是Vue实现了一套内容分发的API。
  • <slot>元素:<slot>元素作为承载内容分发的出口
  • 当组件渲染的时候,<slot></slot>元素将会替换为你所插入的内容(可以是字符串、HTML、组件)
字符串
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>
<body>
  <div id="app">
    <hello-word>
      世界
    </hello-word>
  </div>
  <!-- 组件 -->
  <template id='hello'>
    <div>
      <span>你好!</span>
      <slot></slot>
    </div>
  </template>
  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  <script>
    const HelloWord = {
      template: '#hello'
    }
    new Vue({
      el: '#app',
      components: {
        HelloWord
      }
    })
  </script>
</body>
</html>
HTML
<body>
  <div id="app">
    <hello-word>
      <h1>世界</h1>
    </hello-word>
  </div>
  <template id='hello'>
    <div>
      <span>你好!</span>
      <slot></slot>
    </div>
  </template>
  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  <script>
    const HelloWord = {
      template: '#hello'
    }
    new Vue({
      el: '#app',
      components: {
        HelloWord
      }
    })
  </script>
</body>
组件
<body>
  <div id="app">
    <hello-word>
      <demo-scope></demo-scope>
    </hello-word>
  </div>
  <!-- 组件 -->
  <template id='hello'>
    <div>
      <span>你好!</span>
      <slot></slot>
    </div>
  </template>
  <!-- 组件 -->
  <template id='scope'>
    <div>
      你的名字是?
    </div>
  </template>
  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  <script>
    const HelloWord = {
      template: '#hello'
    }
    const DemoScope = {
      template: '#scope'
    }
    new Vue({
      el: '#app',
      components: {
        HelloWord,
        DemoScope
      }
    })
  </script>
</body>

注意⚠️:如果没有<slot></slot>元素,那么组件起始标签到结束标签之间的任何内容都将会被抛弃。

具名插槽

v-slot指令自Vue2.6.0起引入,提供更好的slotslot-scope特性的API代替方案

  • 一个不带name<slot>元素会带有隐含的名字‘default’
  • 在向具名插槽提供内容的时候,我们可以在一个<template>元素上使用v-slot指令,并以v-slot的参数的形式提供其名称
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
  </head>
  <body>
    <div id="app">
      <hello-word>
        <!-- 现在<template>元素的所有内容都将会被传入相应的插槽 -->
        <template v-slot:header>
          <div>头部</div>
        </template>
        <!-- 任何没有被包裹在带有v-slot的template元素中的内容都将会被视为默认插槽的内容 -->
        <div>主体</div>
        <template v-slot:footer>
          <div>底部</div>
        </template>   
      </hello-word>
    </div>
    <template id='hello'>
      <div>
        <slot name="header"></slot>
        <slot></slot>
        <slot name="footer"></slot>
      </div>
    </template>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script>
      const HelloWord = {
        template: '#hello'
      }
      new Vue({
        el: '#app',
        components: {
          HelloWord
        }
      })
    </script>
  </body>
</html>
作用域插槽
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
  </head>
  <body>
    <div id="app">
      <!-- 子组件使用 -->
      <hello-word>
        <template v-slot:header="scope">
          <div>{{scope.user.first}}</div>
        </template>
        <div>主体</div>
        <template v-slot:footer>
          <div>底部</div>
        </template>
      </hello-word>
    </div>
    
    <template id='hello'>
      <div>
        <slot name="header" :user="msg"></slot>
        <slot></slot>
        <slot name="footer"></slot>
      </div>
    </template>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script>
      // 子组件
      const HelloWord = {
        template: '#hello',
        data () {
          return {
            msg: {
              first: '你好!世界。。。',
              last: '你好!地球。。。'
            }
          }
        }
      }
      new Vue({
        el: '#app',
        components: {
          HelloWord
        }
      })
    </script>
  </body>
</html>
作用域插槽理解:
  1. 首先需要理解,上面的代码存在两个不同的作用域。一个是使用HelloWord组件所具有的Vue实例与对应的作用域,另一个则是HelloWord这个组件自身对应的Vue实例与对应作用域
  2. 其次要知道这两个作用域是彼此隔离的,再不加任何额外设置的情况下,无法访问到彼此Vue实例,因此不要说什么datamethods之类的Vue实例所具有的成员统统都无法交互的。
  3. 正是在此基础上,当我们需要达成这两个作用域能彼此知晓一些信息的目标时,不得不采取一些设置。这设置里就包括了作用域插槽
  4. 同时这两作用域可以认为存在父子关系,即使用HelloWord组件的Vue作用域是父作用域,组件HelloWord的Vue作用域是子作用域。进一步,我们可以将目标分成两大类:父知晓子的信息、子知晓父的信息。
  5. 所以作用域插槽的真正目的是让父知晓子的信息
什么是插槽prop

官方文档有这么一句话解释得很清楚:绑定在<slot>元素上的特性被称为插槽prop。对应上面代码:user="msg"就是插槽prop

结构插槽prop
<hello-word>
  <template v-slot:header="{ user }">
    <div>{{ user.first }}</div>
  </template>
  <div>主体</div>
  <template v-slot:footer>
    <div>底部</div>
  </template>
</hello-word>
prop重命名
<hello-word>
  <template v-slot:header="{ user: person }">
    <div>{{ person.first }}</div>
  </template>
  <div>主体</div>
  <template v-slot:footer>
    <div>底部</div>
  </template>
</hello-word>
插槽总结
  1. 插槽的内容可以是任何模版(字符串、HTML、组件)
  2. 2.6.0新增具名插槽,通过<slot>的name属性和v-slot可以实现插槽的按需加载和指定位置加载
  3. 注意⚠️:v-slot指令是需要写在<template>标签上的,v-slot可以简写为(#)
  4. 插槽可以简单的理解为:在子组件挖一个坑,坑里放什么东西由父组件来决定
  5. 作用域插槽的作用就是让父知晓子的信息
  6. v-slot可以简写为(#)x`
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值