Vue中的插槽详解

在了解插槽之前,我们需要先理解一个概念:编译作用域。
什么是编译作用域呢?

1.编译作用域

官方的解释是:父组件模板的所有东西都会在父级作用域内编译;子组件模板的所有东西都会在子级作用域内编译

怎么理解这句话的含义呢?通过一个例子来说明。(偷个懒,不搭环境了)

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>编译作用域</title>
</head>
<body>

<div id="app">
  <cpn v-show="isShow"></cpn>
</div>

<template id="cpn">
  <div>
    <h2>组件标题</h2>
    <p>组件内容</p>
  </div>
</template>
<script src="../js/vue.js"></script>
<script>
  const cpn = Vue.extend({
    template: '#cpn',
    data() {
    	isShow: false
    }
  })

  const app = new Vue({
    el: '#app',
    components: {
    	cpn
    },
    data: {
    	isShow: true
    }
  })
</script>

</body>
</html>

最终的结果是:isShow为true,子组件的内容会显示;

这是因为:使用的时候,整个组件的使用过程是相当于在父组件中出现的。作用域就是父组件,使用的属性也是属于父组件的属性。因此,isShow使用的是Vue实例中的属性,而不是子组件的属性。

2.为什么要使用插槽slot

插槽的目的在于,是组件更具有扩展性。举个栗子,电脑预留的usb接口,可以用来连接多种外部设备,耳机、音响、U盘等等,使得更具有扩展性。插槽slot的作用正是如此,例如,组件中的一个地方,默认情况下为button,而在使用的时候,我们有需求需扩展为span,扩展为input,这时候我们就需要使用到插槽。

在这里插入图片描述
如何封装合适呢?抽取共性,保留不同。

最好的封装方式就是将共性抽取到组件中,将不同暴露为插槽。一旦我们预留了插槽,就可以让使用者根据自己的需求,决定插槽中插入什么内容。是搜索框,还是文字,还是菜单。由调用者自己来决定。

3.solt插槽的使用

//-------------------------- index.vue 父组件
<template>
  <div>
    <cpn><button>我是button元素</button></cpn>
    <cpn></cpn>
  </div>
</template>

<script>
import cpn from './cpn.vue'
export default {
  data() {
    return {
    }
 },
 components:{
   cpn
 }
}
</script>
//-------------------分割线--------------------cpn组件:cpn.vue
<template>
  <div>
    <div>我是div元素</div>
    <h2>我是h2元素</h2>
    <slot></slot>
  </div>
</template>

<script>
export default {
  data() {
    return {
    }
 },
}
</script>

显示效果:
在这里插入图片描述

子组件预留的slot位置,父组件在使用子组件的时候,在子组件中定义的内容,将渲染在slot的位置处,如果不定义,则不显示。

4.具名插槽

在上面了解了slot的强大之处后,我们就有一个疑问:如果我想在使用子组件的时候,有多个slot插槽,且想指定添加到想要的slot的位置,那应该怎么处理呢?

再例如:当子组件的功能复杂时,子组件的插槽可能并非是一个。比如我们封装一个导航栏的子组件,可能就需要三个插槽,分别代表左边、中间、右边。那么,外面在给插槽插入内容时,如何区分插入的是哪一个呢?

这时候,我们就需要给slot指定一个name属性,也就是具名插槽。

//-------------------------- index.vue 父组件
<template>
  <div>
    <cpn>
    <div slot="center"><h2>中间被替换</h2></div>
  </cpn>
  </div>
</template>

<script>
import cpn from './cpn.vue'
export default {
  data() {
    return {
    }
 },
 components:{
   cpn
 }
}
</script>
//-------------------分割线--------------------cpn组件:cpn.vue
<template>
  <div>
    <slot name="left">我是左边</slot>
    <slot name="center">我是中间</slot>
    <slot name="right">我是右边</slot>
  </div>
</template>

<script>
export default {
  data() {
    return {
    }
 },
}
</script>

显示效果:
在这里插入图片描述
在使用的时候,指定solt的name,就可以替换指定的slot插槽。

5.作用域插槽

官方的定义比较拗口,讲讲自己的理解:
父组件在使用的时候可以替换slot插槽中的显示页面结构,但展示的数据还是来源于子组件。

看一个需求:子组件中包括一组数据,比如:pLanguages: [‘JavaScript’, ‘Python’, ‘Swift’, ‘Go’, ‘C++’]
需要在多个界面进行展示:

1.某些界面是以水平方向一一展示的,
2.某些界面是以列表形式展示的,
3.某些界面直接展示一个数组

内容在子组件,希望父组件告诉我们如何展示,怎么办呢?

//-------------------------- index.vue 父组件
<template>
  <div>
  <!-- 展示结构1 -->
  <cpn>
    <template slot-scope="slotProps">
      <ul>
        <li v-for="item in slotProps.data">{{item}}</li>
      </ul>
    </template>
  </cpn>
  <!-- 展示结构2 -->
  <cpn>
    <template slot-scope="slotProps">
      <h2>{{slotProps.data.join('-')}}</h2>
    </template>
  </cpn>
</div>
</template>
<script>
import cpn from './cpn.vue'
export default {
  data() {
    return {
    }
 },
 components:{
   cpn
 }
}
</script>
//-------------------分割线--------------------cpn组件:cpn.vue
<template>
  <div>
    <slot :data="languages"></slot>
  </div>
</template>
<script>
export default {
  data() {
    return {
    		languages: ['Java', 'Python', 'JavaScript', 'TypeScript', 'C++', 'OC']
      }
  },
}
</script>

显示效果:
在这里插入图片描述

我们来看看大型的网站中是怎么时候作用于插槽的:

element-ui中的el-table: element-ui表单 el-table

截取部分代码:

 <template slot-scope="scope">
        <el-button
          @click.native.prevent="deleteRow(scope.$index, tableData)"
          type="text"
          size="small">
          移除
        </el-button>
      </template>

其中的scope代表的就是表格中的一行的数据。

slot插槽在封装组件的过程中,使用的非常频繁,后续有时间再对开发中的一些实用方法进行总结,欢迎补充不足之处,非常感谢。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值