Vue中插槽的使用备忘

Vue中插槽的使用备忘

插槽(slot)是 Vue 为组件的封装者提供的能力。
允许开发者在封装组件时,把不确定的、希望由用户指定的部分,
定义为插槽。可以把插槽认为是组件封装期间,为用户预留的占位符

参考链接

1. 默认插槽

当子组件模板只有一个没有属性的插槽时,
父组件传入的整个内容片段将插入到插槽所在的 DOM 位置,
并替换掉插槽标签本身

1-1 实例:父组件

<template>
  <div>
    <h3 class="title">App组件</h3>
    <hr />
    <child>
      <!-- 待替换默认插槽中的内容 -->
      <h3>我是标题</h3>
    </child>
    <!-- 显示默认插槽中的内容 -->
    <child />
    <!-- 显示默认插槽中的内容 -->
    <child></child>
  </div>
</template>

<script>
import child from './components/child.vue'
export default {
  components: {
    child
  },
  data() {
    return {}
  },
  methods: {}
}
</script>
<style lang="scss" scoped></style>

1-2 实例:子组件

<template>
  <div>
    <h3>child组件</h3>
    <!-- 声明位置,<slot>标签中间内容为显示的位置 -->
    <!-- 单个插槽,一个组件只能有一个默认插槽,有个潜在的name=default -->
    <!-- <slot name="default"></slot> -->
    <!-- 简写 -->
    <slot>默认</slot>
  </div>
</template>

<script>
export default {
  data() {
    return {}
  },
  methods: {}
}
</script>
<style lang="scss" scoped></style>

1-3 实例:页面效果

在这里插入图片描述

2. 具名插槽

有时页面需要多个插槽,来完成对应的数据自定义显示。
一个不带 name 的 <slot> 插槽会带有隐含的名字“default”,即默认插槽。
指定name属性值的,即为具名插槽 -- 相当于给插槽自己起名字

2-1 实例:父组件

<template>
  <div>
    <h3 class="title">App组件</h3>
    <hr />
    <child>
      <!-- 具名插槽 -->
      <!-- vue2.6之前写法 -- 重复调用会依次执行显示,最终都会显示 -->
      <!-- <h3 slot="header">我是文章标题1</h3> -->
      <!-- <h3 slot="header">我是文章标题2</h3> -->
      <!-- <h3 slot="header">我是文章标题3</h3> -->
        
      <!-- vue2.6及之后写法 只能写在template中,不能写在html标签上 -->
      <!-- vue2.6之后的具名插槽,重复调用,只会执行最后1次 -->
      <!-- <template v-slot:header> -->
      <!-- 简写:v-slot:header ==>  #header 	-->
      <template #header>
        <h3>我是文章标题1</h3>
      </template>
      <template #header>
        <h3>我是文章标题2</h3>
      </template>
      <!-- 	vue2.6及之后,多个template使用同一个具名插槽,
      		最终页面会显示最后一个,
      		此处仅显示<h3>我是文章标题3</h3> 
      -->
      <template #header>
        <h3>我是文章标题3</h3>
      </template>

      <!-- 	如下html片段,未指定插槽的name,
      		则自动放在默认插槽的位置;
      		若child组件没有默认插槽,则该块内容不显示		
      -->
      <div>默认插槽</div>
    </child>
  </div>
</template>

<script>
// 同步导入
import child from './components/child.vue'
export default {
  components: {
    child
  },
  data() {
    return {}
  },
  methods: {}
}
</script>
<style lang="scss" scoped></style>

2-2 实例:子组件

<template>
  <div>
    <h3>child组件</h3>
    <!-- 具名插槽,给slot添加一个名称为header,名称不能重复 -->
    <slot name="header">默认头部</slot>
    <!-- 默认插槽 -->
    <slot>默认</slot>
  </div>
</template>

<script>
export default {
  data() {
    return {}
  },
  methods: {}
}
</script>
<style lang="scss" scoped></style>

2-3 实例:页面效果

在这里插入图片描述

3. 作用域插槽 – 向使用者传递数据

作用域插槽是一种特殊类型的插槽,
能被传递数据的可重用模板,来代替已经渲染好的元素。
在子组件中,只需将数据传递到插槽,就像将 prop 传递给组件一样。

在封装组件的过程中,可以为预留的<slot>插槽绑定props 数据,
这种带有props 数据的 <slot> 叫做“作用域插槽”。
作用域插槽就是在具名插槽的基础上,多了数据的传递

3-1 使用语法

# 子组件中
Vue.component('child', {
template: `
<div class="child">
    <slot name="default" text="我是子组件中的内容"></slot>
</div>
`
})

# 父组件中
<div class="parent">
    <child>
        // 老写法
        <div name="default" slot-scope="props">
            <div>父组件</div>
            <h3>{{ props.text }}</h3>
        </div>
        // 新写法
        <template #default="props">
            <div>
                <div>父组件</div>
                <h3>{{ props.text }}</h3>
            </div>
        </template>
    </child>
</div>

3-2 实例:父组件

<template>
  <div>
    <h3 class="title">App组件</h3>
    <hr />
    <child :users="users">
      <!-- vue2.6之前的写法 -->
      <!-- 
      <button slot="del" slot-scope="index" @click="del(index)">删除</button> 
	  或者
	  <button slot="del" slot-scope="props" @click="del(props.index)">删除</button>
	  -->

      <!-- vue2.6之后的写法 -->
      <!-- 	<template v-slot:del="index">,
      		即<template v-slot:[slot的name变量值]="index">
      -->

      <!-- vue2.6之后的写法简写 -->
      <!-- 父组件接收子组件通过作用于插槽传过来的index -->
      <template #del="index">
        <!-- 把子组件中的span标签替换为了button标签 -->
        <button @click="del(index)">删除</button>
      </template>
    </child>
  </div>
</template>

<script>
// 同步导入
import child from "./components/child.vue";
export default {
  components: {
    child,
  },
  data() {
    return {
      users: [
        { id: 1, name: "张三" },
        { id: 2, name: "李四" },
        { id: 3, name: "王五" },
      ],
    };
  },
  methods: {
    // 传过来的index是一个对象,所以需要解构一下
    del({ index }) {
      console.log("app", index);
    },
  },
};
</script>
<style lang="scss" scoped></style>

3-3 实例:子组件

<template>
  <div>
    <h3>child组件</h3>
    <hr />
    <ul>
      <li v-for="(item, index) in users" :key="item.id">
        <span>
          {{ item.name }}
        </span>
        <span>
          <!-- 让插槽传数据 作用域插槽 -->
          <!-- 子组件将index通过作用域插槽传给父组件 -->
          <slot name="del" :index="index">
          	<!-- 	要被外部替换的部分,若使用者不传html元素,
          			则默认显示的内容 -->
            <span @click="del(index)">删除</span>
          </slot>
        </span>
      </li>
    </ul>
  </div>
</template>

<script>
export default {
  props: ['users'],
  data() {
    return {}
  },
  methods: {
    del(index) {
      console.log(index)
    }
  }
}
</script>
<style lang="scss" scoped></style>

3-4 实例:页面效果

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值