Vue--插槽slot

默认插槽

当类似结构的组件需要插入不同元素的时候,可以使用插槽。
默认插槽很简单,只需要在App中将组件写为双标签格式,并在标签内写入需要插入的标签或者内容,然后再组件中需要插入的位置写上slot标签,slot标签内可以写无插入默认显示的内容,当然不写也是可以的。

MySlot组件:

<template>
  <div class="slotBox">
    <h1>{{ title }}</h1>
    <!--slot的位置-->
    <slot></slot>
  </div>
</template>

<script>
export default {
  name: "MyList",
  props: ["title"],
};
</script>

<style scoped>
h1 {
  background-color: aqua;
  text-align: center;
}
.slotBox {
  background-color: pink;
  width: 200px;
  height: 300px;
}
img,
video {
  width: 100%;
}
</style>

App组件

<template>
  <div class="container">
    <MySlot title="美食">
      <!--将需要插入的内容写在标签内部-->
      <img src="https://s3.ax1x.com/2021/01/16/srJlq0.jpg" />
    </MySlot>
    <MySlot title="游戏">
      <ul>
        <li v-for="(game, index) in games" :key="index">{{ game }}</li>
      </ul>
    </MySlot>
    <MySlot title="电影">
      <video
        controls
        src="http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4"
      ></video>
    </MySlot>
  </div>
</template>

<script>
import MySlot from "./components/MySlot.vue";
export default {
  components: { MySlot },
  name: "App",
  data() {
    return {
      foods: ["梨子", "饮料", "其他"],
      games: ["冒险岛", "dota2", "魔兽世界"],
      movies: ["权利的游戏", "魔法少女小圆", "斩赤红之瞳"],
    };
  },
};
</script>
<style scoped>
.container {
  display: flex;
  justify-content: space-around;
}
</style>

具名插槽

可以给slot标签加上name属性,而相应的组件加上slot属性,从而实现精准填充。并且在用template的时候,slot="xxx"可以替换为v-slot:xxx,但是一般都用原来的写法,因为只有在标签为template的时候才能使用。
MySlot组件:

<template>
  <div class="slotBox">
    <h1>{{ title }}</h1>
    <slot name="center"></slot>
    <slot name="footer"></slot>
  </div>
</template>

<script>
export default {
  name: "MyList",
  props: ["title"],
};
</script>

<style scoped>
h1 {
  background-color: aqua;
  text-align: center;
}
.slotBox {
  background-color: pink;
  width: 200px;
  height: 300px;
}
img,
video {
  width: 100%;
}
</style>

App组件:

<template>
  <div class="container">
    <MySlot title="美食">
      <img slot="center" src="https://s3.ax1x.com/2021/01/16/srJlq0.jpg" />
      <a slot="footer" class="foot" href="http://www.baidu.com">更多美食</a>
    </MySlot>
    <MySlot title="游戏">
      <ul slot="center">
        <li v-for="(game, index) in games" :key="index">{{ game }}</li>
      </ul>
      <div slot="footer" class="foot">
        <a href="http://www.baidu.com">单机游戏</a>
        <a href="http://www.baidu.com">网络游戏</a>
      </div>
    </MySlot>
    <MySlot title="电影">
      <video
        slot="center"
        controls
        src="http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4"
      ></video>
      <template v-slot:footer>
        <div class="foot">
          <a href="http://www.baidu.com">经典</a>
          <a href="http://www.baidu.com">热门</a>
          <a href="http://www.baidu.com">推荐</a>
        </div>
        <h2>欢迎</h2>
      </template>
    </MySlot>
  </div>
</template>

<script>
import MySlot from "./components/MySlot.vue";
export default {
  components: { MySlot },
  name: "App",
  data() {
    return {
      foods: ["梨子", "饮料", "其他"],
      games: ["冒险岛", "dota2", "魔兽世界"],
      movies: ["权利的游戏", "魔法少女小圆", "斩赤红之瞳"],
    };
  },
};
</script>
<style scoped>
.container,
.foot {
  display: flex;
  justify-content: space-around;
}
h2 {
  text-align: center;
}
</style>

作用域插槽

数据在某组件内,但是想给其父组件定义该组件的结构时候,使用作用域插槽,如本实例中,数据在MySlot中,但是其父组件可以用到MySlot的数据,传的方式类似于父传子的props,但是父组件需要用template将想插入的内容包裹起来,并用scope(最新的为slot-scope)属性接收,该属性不用es6的解构赋值是为一个自定义的变量,并且在v-for的时候需要这个变量.相应的数据,如果是用es6的解构赋值,则可以直接将里面的数据取出来,格式为scope=“{xxx}”。

App组件

<template>
  <div class="container">
    <MySlot title="美食">
      <!-- 这里用的slot-scope,跟scope一样的,并且没用es6,因此自定义了一个接收的变量 -->
      <!-- 一定需要用template包裹 -->
      <template slot-scope="peiqi">
        <ol>
          <!-- 接受的为一个对象,因此需要获取里面的数据 -->
          <li v-for="(food, index) in peiqi.foods" :key="index">{{ food }}</li>
        </ol>
      </template>
    </MySlot>
    <MySlot title="美食">
      <!-- 这里用的scope,并且用的es6语法,直接取出对象中的属性 -->
      <template scope="{foods}">
        <ul>
          <!-- 直接用属性即可 -->
          <li v-for="(food, index) in foods" :key="index">{{ food }}</li>
        </ul>
      </template>
    </MySlot>
  </div>
</template>

<script>
import MySlot from "./components/MySlot.vue";
export default {
  components: { MySlot },
  name: "App",
};
</script>
<style scoped>
.container,
.foot {
  display: flex;
  justify-content: space-around;
}
h2 {
  text-align: center;
}
</style>

MySlot组件

<template>
  <div class="slotBox">
    <h1>{{ title }}</h1>
    <slot :foods="foods"></slot>
  </div>
</template>

<script>
export default {
  name: "MyList",
  props: ["title"],
  data() {
    return {
      foods: ["梨子", "饮料", "其他"],
    };
  },
};
</script>

<style scoped>
h1 {
  background-color: aqua;
  text-align: center;
}
.slotBox {
  background-color: pink;
  width: 200px;
  height: 300px;
}
img,
video {
  width: 100%;
}
</style>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值