(19)深入理解 Vue 组件——⑥ 在 Vue 中使用插槽 | Vue 基础理论实操

3,869 阅读2分钟
本文版权归 “公众号 | 前端一万小时” 所有,欢迎转载!

转载请注明出处,未经同意,不可修改文章内容。

🔥🔥🔥本系列文章已在“公众号 | 前端一万小时”更新完毕,有需要的小伙伴可按需前往查看。

🔥🔥🔥“前端一万小时”两大明星专栏——“从零基础到轻松就业”、“前端面试刷题”,已于本月大改版,合二为一,干货满满,欢迎点击公众号菜单栏各模块了解。


涉及面试题:
什么是 slot?

[编号:vue_19]

🔗本阶段对应的“官方文档”阅读


1 什么时候用到 slot

当父组件要传递内容给子组件时,按照我们之前学习的方法,我们的做法是:属性形式,向子组件传值

<body>
  <div id="root">
    <child content="<p>world</p>"></child>
  </div>
  <script>
    Vue.component("child",{
      props: ["content"],
      template: `<div>
                  <p>hello</p>
                  <div v-html="this.content"></div> // ❌这外层的 div 标签截止目前所学,弄不掉!
                </div>`
    })
    var vm = new Vue({
      el: "#root"
    })
  </script>
</body>

❌运行以上代码(需删除代码中注释),我们虽然很好的显示出了 hello world ,但我们打开后台查看代码结构,会发现:即使使用了之前学习的所有方式,依然不能只显示 <p>world</p> 这个标签(即,它外边怎么都会有一个 div 标签)。 19-01.png

2. 父组件向子组件优雅地传递 dom 结构—— slot

❓需求:

当子组件中部分内容是根据父组件传递过来的内容显示时会出现这样的状况:父组件传递内容给子组件含有较多内容。就无法只用一个_ _div 进行包裹。

<body>
  <div id="root">
    <child>
      <p>world</p> <!-- 1️⃣首先,我们直接在这里使用组件 child ,然后很“直观”地在这个组件里
									 “插入”需要的标签; -->
    </child>
  </div>
  <script>
    Vue.component("child", {
      template: `<div>
                   <p>Hello</p>
                   <slot></slot>
                 </div>` /*
                 				 2️⃣其次,我们在子组件的模板里,用 <slot></slot> 这个闭合标签
      									 来展示1️⃣中“插入”的标签。
                          */
    })
    var vm = new Vue({
      el: "#root"
    })
  </script>
</body>

19-02.png

💡slot 插槽也可以定义默认值:

父组件如果不传递内容,子组件所传递的 slot 插槽内容就会被显示。

<div id="root">
  <child>
  </child> <!-- 1️⃣首先,父组件这里没有向子组件传递内容——即,没有“插入”任何标签; -->
</div>

<script>
  Vue.component("child", {
    template: `<div>
                 <p>Hello</p>
                 <slot>默认内容</slot> 
               </div>` // 2️⃣slot 里边的内容会显示出来。
  })
  var vm = new Vue({
    el: "#root"
  })
</script>

19-03.png

3 具名插槽的使用

❌出现问题:

如果没定义父组件插入子组件的内容的唯一性,那么子组件接收多个插入内容,就会被一个 slot 同时占用并使用,如图所示: 19-04.png

✔️解决办法:

使用具名插槽——给插槽起一个名字,对传递内容进行唯一性的标识。 代码如下,分别命名父组件和子组件的插槽名:

<div id="root">
  <body-content>
    <div class="header" slot="header">header</div> 
    <div class="footer" slot="footer">footer</div> 
  </body-content> 
</div>
<script>
  Vue.component("body-content", {
    template: `<div>
                 <slot name="header"></slot>   
                 <div class="content">content</div>
                 <slot name="footer"></slot> 
               </div>`
  })
  var vm = new Vue({
    el: "#root"
  })
</script>

💡具名插槽的默认性:

调用父组件的时候没有传递插槽,那么如何传递插槽的默认值,如下:

<div id="root">
  <body-content>     
    <div class="footer" slot="footer">footer</div> 
  </body-content>
</div>
<script>
  Vue.component("body-content", {
    template: `<div>
                 <slot name="header">default header</slot> 
                 <div class="content">content</div>
                 <slot name="footer"></slot>
               </div>`
  })
  var vm = new Vue({
    el: "#root"
  })
</script>

19-05.png

祝好,qdywxs ♥ you!