解决父子组件通信的三种Vue插槽

 更新时间:2021-12-17 12:01:51   作者:佚名   我要评论(0)

目录前言环境准备Category组件App组件一、默认插槽二、具名插槽三、作用域插槽总结前言
插槽可以说是 Vue 中非常重要的一部分吧,在我学习和

前言

插槽可以说是 Vue 中非常重要的一部分吧,在我学习和练习的过程中,当组件搭配着插槽一起使用的时候,会发挥的更好一些。更多时候也会更加方便。

今天介绍Vue中三种插槽吧:默认插槽、具名插槽、作用域插槽。

环境准备

先搭个初始环境给大家看看哈。一步一步讲完这个插槽。

就是写了一个类别组件,分别渲染这三种数据。

image-20211120150949138

Category组件

<template>
  <div class="category">
    <h1>{{title}}</h1>
    <ul>
      <li 
      v-for="(item,index) in listData"
      :key="index">{{item}}</li>
    </ul>
  </div>
</template>
<script>
export default {
  props: {
    listData:Array,
    title: String
  }
}
</script>
<style scoped>
.category{
  width: 200px;
  height: 300px;
  background-color:pink;
}
</style>

App组件

<template>
  <div id="app">
    <Category :listData="games" :title="'Games'" />
    <Category :listData="movies" :title="'Movies'" />
    <Category :listData="foods" :title="'Foods'" />
  </div>
</template>
<script>
import Category from './components/Category.vue'
export default {
  name: 'App',
  components: {
    Category
  },
  data () {
    return {
      games:['穿越火线','qq飞车','洛克王国'],
      movies:['你好,李焕英','青春派','匆匆那年'],
      foods:['邵阳米粉','长沙茶颜','重庆火锅']
    }
  }
}
</script>
<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
  display: flex;
  justify-content: space-between;
}
</style>

最开始就是如上图一样的需求,但是现在业务需求更改了,电影变成了只宣传其中一个,其他的不进行宣传,吃的也变成只宣传一个拉。

如下图:

image-20211120151432264

我们怎么改合适呢?

是在Category组件中加if一个个进行判断吗?还是有更好的方法勒???

一个个判断是不行的,那样子代码会变得十分繁杂,不易阅读,万一以后又要更改业务需求,代码都不好动。

接下来就到默认插槽的出现拉。

一、默认插槽

我们在子组件中不用再用props 接收数据,也不做渲染,而是定义一个插槽。

<template>
<div class="category">
    <!-- 定义插槽,插槽默认内容 -->
    <slot>如果当父组件不传值过来,即显示此默认</slot>
    </div>
</template>
<script>
    export default {
        props: {
        }
    }
</script>

App组件也作出更改

<template>
<div id="app">
    <Category>
        <h1>Games</h1>
        <!-- <ul>
<li v-for="(item, index) in games" :key="index">{{ item }}</li>
    </ul> -->
        <img src="https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fi0.hdslb.com%2Fbfs%2Farticle%2Fb352264fa7bfdb6d211f2e71e87cc2c48d85b805.jpg&refer=http%3A%2F%2Fi0.hdslb.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1639931135&t=0b2c6c622c84a1e387196cce8f50455e">
    </Category>
    
    <Category>
        <h1>Movies</h1>
        <img class="movies" src="https://gimg2.baidu.com/image_search/src=http%3A%2F%2Finews.gtimg.com%2Fnewsapp_bt%2F0%2F13236694597%2F641.jpg&refer=http%3A%2F%2Finews.gtimg.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1639931502&t=f89c2197bda9bb129d9404d3c4b30f2f">
        <!-- <ul> -->
        <!-- <li v-for="(item, index) in movies" :key="index">{{ item }}</li> -->
        <!-- </ul> -->
    </Category>
    <Category>
        <h1>Foods</h1>
        <ul>
            <li v-for="(item, index) in foods" :key="index">{{ item }}</li>
    </ul>
    </Category>
    
    <!-- 当我们什么都没有写的时候,看展示什么 -->
    <Category>
    </Category>
    </div>
</template>
 
<script>
    import Category from './components/Category.vue'
 
    export default {
        name: 'App',
        components: {
            Category
        },
        data () {
            return {
                games:['穿越火线','qq飞车','洛克王国'],
                movies:['你好,李焕英','青春派','匆匆那年'],
                foods:['邵阳米粉','长沙茶颜','重庆火锅']
            }
        }
    }
</script>

显示效果:

image-20211120152024922

解释:

我们在子组件写了一个<slot>如果当父组件不传值过来,即显示此默认</slot> 标签,此处就相当于占了一个位置。

我们在父组件中,也不再像之前一样<Category/>写自闭和标签,而是写了非自闭和标签<Category> 内容 </Category>。这样做,Vue就会默认的将写在组件标签中的内容渲染完,然后再放回子组件中的 <slot></slot> 占好位置的地方去。

注意:CSS样式写在父组件或者子组件中都是可以的,因为它是渲染完后才放回子组件中的。写在子组件中,就是在放回子组件中时渲染。

写完这里,客户突然觉得你们这么厉害,不满足啦,又开始给你们整幺蛾子。

image-20211120152906020

接下来就又到具名插槽登场啦哈。

二、具名插槽

竟然我们能够想到用一个插槽啦,那么为什么不能想着用两个插槽来试一试勒?

改造子组件

<template>
  <div class="category">
    <!-- 必须加上名称 在父组件中才能指定要放入那个插槽 这也是为什么叫做具名插槽的原因--->
    <slot name="slot1">如果当父组件不传值过来,即显示此默认</slot>
    <slot name="slot2"></slot>
  </div>
</template>
<script>
export default {
  props: {
  }
}
</script>

父组件

<template>
	<div id="app">
    	<Category>
       	 <template slot="slot1">
          	  <h1>Games</h1>
            <img src="https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fi0.hdslb.com%2Fbfs%2Farticle%2Fb352264fa7bfdb6d211f2e71e87cc2c48d85b805.jpg&refer=http%3A%2F%2Fi0.hdslb.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1639931135&t=0b2c6c622c84a1e387196cce8f50455e"
                 />
	</template>
	<template slot="slot2">
		<button > qq登录</button>
		<button > 微信登录</button>
	</template>
 
</Category>
<Category>
    <template slot="slot1">
		<h1>Movies</h1>
			<img
     class="movies"
     src="https://gimg2.baidu.com/image_search/src=http%3A%2F%2Finews.gtimg.com%2Fnewsapp_bt%2F0%2F13236694597%2F641.jpg&refer=http%3A%2F%2Finews.gtimg.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1639931502&t=f89c2197bda9bb129d9404d3c4b30f2f"
     />
    </template>
    <template slot="slot2">
		<button > 点击购票</button>
    </template>
</Category>
 
<Category>
    <template slot="slot1">
		<h1>Foods</h1>
		<ul>
    		<li v-for="(item, index) in foods" :key="index">{{ item }}</li>
        </ul>
    </template>
</Category>
 
<!-- 当我们什么都没有写的时候,看展示什么 -->
<Category> </Category>
</div>
</template>
 
<script>
    import Category from './components/Category.vue'
 
    export default {
        name: 'App',
        components: {
            Category
        },
        data () {
            return {
                games:['穿越火线','qq飞车','洛克王国'],
                movies:['你好,李焕英','青春派','匆匆那年'],
                foods:['邵阳米粉','长沙茶颜','重庆火锅']
            }
        }
    }
</script>

效果展示

image-20211120153500451

解释:

我们可以在组件中放多个slot,但是多个的时候必须要给他们命名,另外父组件中也要进行指定,这样才不会放不进去。

三、作用域插槽

作用域插槽和前面稍稍有点不同,之前都是数据在父组件中,而作用域插槽是数据在子组件中,反过来传递给父组件,让父组件定义结构进行渲染。

改造的子组件

<template>
  <div class="category">
    <slot name="slot1">如果当父组件不传值过来,即显示此默认</slot>
    <slot name="slot2" :foods="foods">如果当父组件不传值过来,即显示此默认</slot>
  </div>
</template>
<script>
export default {
  data () {
    return{
      foods:['邵阳米粉','长沙茶颜','重庆火锅']
    }
  }
}
</script>

父组件

<template>
  <div id="app">
    <Category>
      <template slot="slot1">
        <h1>Foods</h1>
      </template>
      <template slot="slot2" scope="listData">
        <!--如果不知道的 咱们可以输出看看这是什么· {{listData}}  -->
        <ul>
          <li v-for="(item, index) in listData.foods" :key="index">
            {{ item }}
          </li>
        </ul>
      </template>
    </Category>
    <Category>
      <template slot="slot1">
        <h1>Foods</h1>
      </template>
      <template slot="slot2" scope="listData">
        <ol>
          <li v-for="(item, index) in listData.foods" :key="index">
            {{ item }}
          </li>
        </ol>
      </template>
    </Category>
    <Category>
      <template slot="slot1">
        <h1>Foods</h1>
      </template>
      <template slot="slot2" scope="listData">
          <h4 v-for="(item, index) in listData.foods" :key="index">
            {{ item }}
          </h4>
      </template>
    </Category>
    <Category>
      <template slot="slot1" scope="listData">	
{{listData}}
      </template>
    </Category>
  </div>
</template>
 
<script>
import Category from './components/Category.vue'
 
export default {
  name: 'App',
  components: {
    Category
  }
}
</script>

效果图

image-20211120154438477

这种我在学习及练习过程中,并没有想到哪些使用场景,但是在官网上有案例,我想它必定是有存在的理由,只是我的见识太少,而未能利用到而已。

解释:

子组件中通过:变量名="定义的数据" 向父组件传值,父组件用 <template slot="slot2" scope="不用和子组件传递过来的名称相同"> 接收,因为还要. 一层,才到

<template slot="slot2" scope="listData">
<!--如果不知道的 咱们可以输出看看这是什么· {{listData}}  -->
<ul>
    <li v-for="(item, index) in listData.foods" :key="index">
        {{ item }}
    </li>
    </ul>
</template>

总结

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注脚本之家的更多内容!

您可能感兴趣的文章:
  • Vue匿名插槽与作用域插槽的合并和覆盖行为
  • vue具名插槽的基本使用实例
  • vue 使用插槽分发内容操作示例【单个插槽、具名插槽、作用域插槽】
  • vue默认插槽的理解与实例代码
  • 浅谈Vue中插槽slot的使用方法
  • 详解Vue slot插槽
  • Vue中的匿名插槽与具名插槽详解

您可能感兴趣的文章:

相关文章

  • 解决父子组件通信的三种Vue插槽

    解决父子组件通信的三种Vue插槽

    目录前言环境准备Category组件App组件一、默认插槽二、具名插槽三、作用域插槽总结前言 插槽可以说是 Vue 中非常重要的一部分吧,在我学习和
    2021-12-17
  • JavaScript仿小米官网注册登录功能的实现

    JavaScript仿小米官网注册登录功能的实现

    目录首先我们需要搭建好页面布局JS功能1JS功能2JS功能3JS功能4效果图如下: 首先我们需要搭建好页面布局 html的代码如下: ? <div class=
    2021-12-17
  • vue实现手机验证码登录

    vue实现手机验证码登录

    本文实例为大家分享了vue实现手机验证码登录的具体代码,供大家参考,具体内容如下 验证码 <template> <div> <el-main> <el-f
    2021-12-17
  • 解析.netcore项目中IStartupFilter使用教程

    解析.netcore项目中IStartupFilter使用教程

    背景: netcore项目中有些服务是在通过中间件来通信的,比如orleans组件。它里面服务和客户端会指定网关和端口,我们只需要开放客户端给外界
    2021-12-17
  • ASP.NET Core设置URLs的五种方法

    ASP.NET Core设置URLs的五种方法

    目录前言URL格式前提条件方法1 使用环境变量方法2 使用命令行参数方法3 使用配置文件方法4 使用UseUrls方法5 使用Kestrel优先级总结前言 在使
    2021-12-17
  • JavaScript函数this指向问题详解

    JavaScript函数this指向问题详解

    目录一、 函数内 this 的指向1、普通函数2、构造函数3、对象方法4、事件绑定方法5、定时器函数6、立即执行函数二、改变函数内部 this 指向1、
    2021-12-17
  • JavaScript中的宏任务和微任务详情

    JavaScript中的宏任务和微任务详情

    目录1、微任务有哪些2、宏任务有哪些3、案例3.1 结论4、代码案例4.1 代码分析4.2 结论和运用的场景1、微任务有哪些 Promise await和async 2、
    2021-12-17
  • jQuery解决添加元素后不执行原有事件的方法

    jQuery解决添加元素后不执行原有事件的方法

    我们先来看下我的错误代码 html: <table border="1" id="best"> <tr> <td> <button class="change">修改</button>
    2021-12-17
  • .NET?6全新配置对象ConfigurationManager介绍

    .NET?6全新配置对象ConfigurationManager介绍

    介绍 本节为大家带来.NET 6新增的ConfigurationManager,很多人好奇为啥要讲这个,读取加载配置信息都随手就来了,我们往下看一下。 翻译:这
    2021-12-17
  • setup+ref+reactive实现vue3响应式功能

    setup+ref+reactive实现vue3响应式功能

    setup 是用来写组合式 api ,内部的数据和方法需要通过 return 之后,模板才能使用。在之前 vue2 中,data 返回的数据,可以直接进行双向绑定
    2021-12-17

最新评论