学会用插槽(Slot),子组件也能横着走

        在实际项目,我们不仅仅是单纯的在父组件中引入子组件,有时候还得根据父组件的需求来动态更改子组件的内容和样式。虽然有很多的方法可以来实现这个步骤,比如使用父子组件传值来实现父组件动态更改子组件中的数据,进而改变内容和样式,但是这种方式并不是很直观。

         为此,在这里介绍Vue中的一个知识点:插槽(slot),插槽其实就是一段模块,在父组件中定义模块,在子组件中选择任意位置放置(是不是很有趣,以前都是在父组件中引入子组件,然后在父组件中选择位置放置,但现在却反过来了)

       模板种类大体可以分为两类:

             1.非插槽模板,也就是常规的html标签,如<template>标签中放置的<div>、<select>、<button>等标签,都是已经固定好了展示位置的;

             2.插槽模板,这套模板是在父组件中定义的,在子组件中使用。不过,你可以在子模板<template>中选择任意位置放置插槽,还可以放置多次,此外,可以在模块中加入名字属性,就可以使之成为具名插槽,在模板中加入'slot-scope'(Vue3中已改为'v-slot')获取从子组件中传入的数据,使之成为作用域插槽,这样可以很好地解决父组件决定插槽的样式,子组件提供相应内容的需求

        为了方便大家理解,我将每种插槽全部分开讲解,请大家记得详看代码中的注释,项目核心结构如下(3种插槽结构都一样,只展示变化了的文件)

正在加载中

 1.默认插槽(也叫匿名插槽,或单个插槽),先上效果图:

文件代码如下:

 Child.vue

<template>
    <div class="Child">
        <h1>我是子组件</h1>
        //这个地方才是真正渲染插槽的地方,也就是<p>默认插槽</p>
        //所以'默认插槽'这四个字才会是绿色
        <slot />     
    </div>
</template>

<style scoped>
    .Child{
        color: green;
    }
</style>

 Father.vue 

<template>
  <div class="hello">
    <h1>我是父组件</h1>
    //这个地方也可以写成<ChildComponent><p>默认插槽</p> </ChildComponent>
    //因为在template中child-component可以解析成ChildComponent(看一个大佬说过,这个标签的源码是用正则表达式匹配的)
    <child-component>
      //这个地方虽然看似是在父组件中放置了<p>默认插槽</p>
      //但是它是在子组件中进行解析的
      //大家可以看一下文字的颜色,如果是直接在父组件中渲染,那么应该是红色
      //但是最终的结果却是绿色,表明这个模块其实是属于子组件的
      <p>默认插槽</p>
    </child-component>
  </div>
</template>

<script>
import ChildComponent from './Child'
export default {
  name: 'Father',
  components:{
    ChildComponent
  }
}
</script>

<style scoped>
  .hello{
    color:red
  }
</style>

  router/index.js(这部分代码匿名插槽、具名插槽和定义域插槽共用)

import Vue from 'vue'
import Router from 'vue-router'
import Father from '@/components/Father'

Vue.use(Router)

const routes = [
  {
    path: '/',
    name: 'Father',
    component: Father
  }
]
const routers = new Router({
  //别问我为什么不用默认的hash模式,问就是我觉得hash模式在路由中加的'#'不好看,哈哈
  mode: 'history',  
  routes
})

export default routers

 2.具名插槽,先上效果图:

文件代码如下:

Child.vue

<template>
    <div class="Child">
        <h1>我是子组件</h1>
        <slot name="BigSlot"></slot>  
        <slot name="SmallSlot"></slot>
        <slot name="SmallSlot"></slot>
        <slot name="SmallSlot"></slot>
    </div>
</template>

<style scoped>
    .Child{
        color: green;
    }
    //这里的 .big 和 .small 的样式放在父组件中同样生效 
    .big{
        font-size: 50px;
    }
    .small{
        font-size: 20px;
    }
</style>

 Father.vue

<template>
  <div class="hello">
    <h1>我是父组件</h1>
    <child-component>
      //下面这部分标签全部都会在子组件中渲染,通过slot属性设置相应的名字,即可在子组件中使用
      <p class="big" slot="BigSlot">我是大插槽</p>
      <p class="small" slot="SmallSlot">我是小插槽</p>
    </child-component>
  </div>
</template>

<script>
import ChildComponent from './Child'
export default {
  name: 'Father',
  components:{
    ChildComponent
  }
}
</script>

<style scoped>
  .hello{
    color:red
  }
</style>

3.定义域插槽,先上效果图:

这里要给各位提个醒:一定要注意父组件获取到的子组件中数据的效果,强烈建议大家都亲手试一下,不然光看有时候是没用的

当前的Father.vue

<template>
  <div class="hello">
    <h1>我是父组件</h1>
    <child-component>
        //一定要注意这个传输过来的data数据的值
        <div slot-scope="data">
          <p>子组件传输过来的数据</p>
          <p>{{ data }}</p>
        </div>
    </child-component>
  </div>
</template>

<script>
import ChildComponent from './Child'
export default {
  name: 'Father',
  components:{
    ChildComponent
  }
}
</script>

<style scoped>
  .hello{
    color:red
  }
</style>

我最开始想做的效果如下:

但是最开始没注意数据的传输格式,所以浪费了一些时间

现在的Father.vue

<template>
  <div class="hello">
    <h1>我是父组件</h1>
    <child-component>
        //最新版本使用的是 v-slot 这个标签
        <div slot-scope="data">
          <p>姓名:{{ data.person.name }}</p>
          <p>身份:{{ data.person.identity }}</p>
          <p>技能:{{ data.person.skill }}</p>
          <p>憎恨:{{ data.person.hate }}</p>
          <p>名言: {{ data.person.quotes }}</p>
        </div>
    </child-component>
  </div>
</template>

<script>
import ChildComponent from './Child'
export default {
  name: 'Father',
  components:{
    ChildComponent
  }
}
</script>

<style scoped>
  .hello{
    color:red
  }
</style>

Child.vue

<template>
    <div class="Child">
        <h1>我是子组件</h1>
        <slot :person="person"></slot>
    </div>
</template>

<script>
export default {
    name: 'Child',
    data(){
        return{
            person:{
                name: '马保国',
                identity: '浑元形意太极门掌门人',
                skill: '五鞭太极拳',
                hate: '不讲武德',
                quotes: '年轻人不讲武德,耗子尾汁'
            }
        }
    }    
}

</script>
<style scoped>
    .Child{
        color: green;
    }
</style>

         在定义域插槽中,我们可以看到绑定数据的插槽,显示内容完全由子组件决定,数据来自子组件

         多么美妙的知识呀,虽然感觉头发蓬蓬的能起飞,但是感觉自己还能刚呢,各位小伙伴,一起加油吧,奥利给!

        

 

  • 11
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值