一、插槽slot的基本使用

组件的插槽也是为了让我们封装的组件更加具有扩展性。让使用者可以决定组件内部的一些内容到底展示什么。
栗子:
slot.png
上述的图片展示的组件结构一样,但是内容不同,若每次都单独重写的话无疑工作量巨大,但是使用插槽就可以先把框架搭好,里面的内容就可根据实际需求进行修改,这样就减少了重复代码的书写。
代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <script src="../js/vue.js"></script>
  <template id="cpn">
    <div>
      <h2>哈哈哈</h2>
      <p>我是组件</p>
      <slot><button>我是默认值</button></slot><!--就相当于再这个组件中预留一个为位置作为扩展,可以在这个标签中添加内容作为默认值
      在使用这个组件时如果没有指定内容就使用默认值
      -->
    </div>
  </template>
  <!--有时需要再增添些内容向组件中,这时候就需要插槽了-->
  <div id="app">
    <!--现在我只想向第一个组件中加一个按钮,如下写法-->
    <cpn><button>按钮</button></cpn>
    <cpn><span>哈哈</span></cpn>
    <cpn></cpn>
    <cpn><a href="#">走你</a></cpn> 
  </div>
  <script>
  const app = new Vue({
    el: '#app',
    data: { 
      message: 'helloWorld!'
    },
    components:{
      cpn:{
        template:'#cpn'
      }
    }
  });
  </script>
</body>
</html>

二、具名插槽的使用

组件用到多个插槽时该怎末匹配替换插槽,使用name属性,而且使用时有限替换没有name属性值的插槽

代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <script src="../js/vue.js"></script>
  <template id="cpn">
    <!--组件用到多个插槽时该怎末匹配替换插槽,使用name属性,而且使用时有限替换没有name属性值的插槽-->
    <div>
      <slot name="left">左边</slot>
      <slot name="center">中间</slot>
      <slot name="right">右边</slot>
      <slot>hahaha</slot>
    </div>
  </template>
  <div id="app">
    <cpn>我替换的是没有name的插槽</cpn>
    <cpn><span slot="center">我替换的是中间的</span></cpn>
    <cpn><span slot="left">我替换的是左边的</span></cpn>
  </div>
  <script>
  const app = new Vue({
    el: '#app',
    data: { 
      message: 'helloWorld!'
    },
    components:{
      cpn:{
        template:'#cpn'
      }
    }
  });
  </script>
</body>
</html>

三、作用域插槽

理解:父组件替换插槽的标签,但是内容由子组件来提供。
我们先提一个需求:

  • 子组件中包括一组数据,比如:pLanguages: ['JavaScript', 'Python', 'Swift', 'Go', 'C++']
  • 需要在多个界面进行展示:某些界面是以水平方向一一展示的,某些界面是以列表形式展示的,某些界面直接展示一个数组

内容在子组件,希望父组件告诉我们如何展示,怎么办呢?
这里利用slot作用域插槽就可以了

代码如下:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <script src="../js/vue.js"></script>
  <!--有时父组件展示子组件内容,但是想换其他方式来展示,这就需要拿到子组件中的数据来展示,这个方法现在有改动-->
  <template id="cpn">
    <div>
      <slot :data="pLanguages">
        <ul>
          <li v-for="item in pLanguages">{{item}}</li>
        </ul>
      </slot>
    </div>
  </template>
  <div id="app">
    <!--现在我有个需求,让这三个以不同的方式来展示列表-->
    <!--这里我想用子组件中的pLanguage,这里就要获取到这个属性了-->
    <cpn>
      <template slot-scope="slot">
        <span v-for="item in slot.data">{{item}}--</span>
        <br>
        <span>{{slot.data.join("||")}}</span>
      </template>
    </cpn>
    <!--   -->
    <cpn></cpn>
  </div>
  <script>
    const app = new Vue({
      el: '#app',
      data: {
        message: 'helloWorld!'
      },
      components: {
        cpn: {
          template: '#cpn',
          data() {
            return {
              pLanguages: ['JavaScript', 'C++', 'C#', 'Go', 'python']
            }
          }
        }
      }
    });
  </script>
</body>

</html>

我们通过