当前位置: 首页 > news >正文

Vue学习---插槽篇

Vue插槽

    • 1. 初步了解插槽
    • 2. 插槽的分类
      • 2.1 默认插槽
      • 2.2 具名插槽
      • 2.3 作用域插槽(待更新吧)

1. 初步了解插槽

什么是插槽?


插槽就是子组件提供给父组件使用的一个占位符,可以通俗理解为“占坑作用”。有了该占位符,父组件可以在该占位符中填充任何模板,不仅限于传递数据,也可以填充如HTML、组件、template模板、标签等。填充后,内容替换子组件的标签

为什么要使用插槽?
在组件通信中(详情见文章:Vue组件学习、组件通信),我们了解到组件之间如何传递数据。那父组件在复用子组件的时候除了想给子组件传递数据,还想更改子组件的内容和样式时,怎么办呢?
一般来说,父组件是没办法更改子组件的内容和样式的,总结就是“你可以用我但是不可以更改我”。
就像买车一样 不能自己去决定车的配置、外观、性能、尺寸,这些都是厂家自己设计好然后批量生产的 ,大家买下都是一样的。

如果你真的想更改子组件,那就使用插槽。
插槽的作用就是使得父组件可以改造子组件,让父组件提供内容,在子组件中展示

使用场景:

  • 使用插槽让用户拓展组件,更好地复用组件和对其做定制化处理。
  • 当一个子组件被父组件复用时,或许在不同情况下需要被更改,此时如果去重写组件是 一件不明智的事情,此时通过slot插槽向子组件内部指定位置传递内容,是一个更好的选择。
  • 在布局组件、表格列、下拉框、弹框显示内容中常用。

2. 插槽的分类

2.1 默认插槽

案例场景:以下是一个组件的复用(一个蓝色的div即是一个组件),该组件在页面中复用了3次,我想对某一个组件实现私人定制,比如,美食组件我只想放一张图片,电影组件中我想放一个视频,如何做?
在这里插入图片描述
由上方效果变成下面这样的:
请添加图片描述
制定子组件Category.vue:
这是没有使用插槽的情况,组件不能实现定制化:

<template>
  <div class="category">
    <h3>{{title}}</h3>    
    <ul>
      <li v-for="(item,index) in listData" :key="index">{{item}}</li>
    </ul>
  </div>
</template>
<script>
  export default{
    name:"Category",
    // 接收父组件传过来的值
    props:['listData','title']
  }
</script>
<style>
  .category{
    background-color: skyblue;
    width: 200px;
    height: 300px;
  }
  h3{
    text-align: center;
    background-color: orange;
  }
</style>

在App.vue中使用Category.vue:

<template>
  <div id="app">
    <!-- 复用子组件 静态传输标题,动态传输数组-->
   <Category title="美食" :listData="foods" />
   <Category title="书籍" :listData="books"/>
   <Category title="电影" :listData="films"/>
  </div>
</template>

<script scope="this api replaced by slot-scope in 2.5.0+">
import Category from './components/Category.vue';
export default {
  name: 'App',
  components: {
    Category,
  },
  data(){
    return{
      // 定义数据
      foods:['火锅','重庆火锅','小龙虾','牛排'],
      books:['语文','数学','英语','化学'],
      films:['重庆森林','七龙珠','犬夜叉','心灵捕手'],
    }
  }
}
</script>

<style>
#app {
  display: flex;
  justify-content: space-around;
}
</style>

以上复用只能出现第一个页面效果,见下图:
在这里插入图片描述
如果不使用作用域插槽,仅在App.vue更改组件中内容,子组件是不会将内容渲染的
在App.vue中更改子组件内容,此时子组件中无插槽!!!

   <Category title="美食" >
    <img src="@/assets/hotpot.jpg" alt="">
  </Category>
   <Category title="书籍" :listData="books"/>
   <Category title="电影" :listData="films"/>

子组件无法渲染在父组件中更改的页面结构,如下图:
在这里插入图片描述
下面使用默认插槽:
在子组件Category.vue中定义一个默认插槽:

<template>
  <div class="category">
    <h3>{{title}}</h3>
    <!-- 定义一个插槽 组件的页面结构完全交给父组件去定义-->
    <slot>默认值,当父组件没有出现时,我会出现</slot>
  </div>
</template>
<script>
  export default{
    name:"Category",
    // 接收父组件传过来的值
    props:['title']
  }
</script>
<style>
  .category{
    background-color: skyblue;
    width: 200px;
    height: 300px;
  }
  h3{
    text-align: center;
    background-color: orange;
  }
</style>

App.vue:

<template>
  <div id="app">
    <!-- 复用子组件 静态传输标题,动态传输数据 -->
   <Category title="美食" >
    <img src="@/assets/hotpot.jpg" alt="">
  </Category>

   <!-- <Category title="书籍" :listData="books"/> -->
   <Category title="书籍">
    <ul>
      <li v-for="(item,index) in books" :key="index">{{item}}</li>
    </ul>
  </Category>

   <!-- <Category title="电影" :listData="films"/> -->
   <Category title="电影">
    <video src="@/assets/1.mp4" controls></video>
  </Category>
  </div>
</template>

<script scope="this api replaced by slot-scope in 2.5.0+">
import Category from './components/Category.vue';
export default {
  name: 'App',
  components: {
    Category,
  },
  data(){
    return{
      // 定义数据
      foods:['火锅','重庆火锅','小龙虾','牛排'],
      books:['语文','数学','英语','化学'],
      films:['重庆森林','七龙珠','犬夜叉','心灵捕手'],
    }
  }
}
</script>

<style>
#app {
  display: flex;
  justify-content: space-around;
}
img{
  width: 100%;
}
video{
  width: 100%;
}
</style>

注意:对样式的定义,可以定义在父组件也可以定义在子组件。
区别:

  • 定义在父组件,结构先编译好样式再传给子组件;
  • 定义在子组件中,结构传给子组件,再由子组件编译。
<style>
img{
  width: 100%;
}
video{
  width: 100%;
}
</style>

2.2 具名插槽

上诉案例中,提高需求,我想在分割线下添加一个跳转链接(分割线以上的都是默认插槽区域),如何做?
在这里插入图片描述
使用默认插槽和使用作用域插槽的区别:
在这里插入图片描述

具名插槽就是把父组件想要更改的元素插在子组件的某个位置上,并且只接受对应名字的更改元素,而默认插槽则会把父组件的更改元素全盘接收。
使用vue2.6的新语法时,建议使用template模板包裹元素

Category.vue

<template>
  <div class="category">
    <h3>{{title}}</h3>
    <!-- 定义一个插槽 -->
    <slot>默认值,当父组件没有出现时,我会出现</slot>
    -------------------------
    <!-- 声明一个具名插槽 -->
    <slot name="link"></slot>
    <!-- <ul>
      <li v-for="(item,index) in listData" :key="index">{{item}}</li>
    </ul> -->
  </div>
</template>

App.vue

<template>
  <div id="app">
    <!-- 复用子组件 静态传输标题,动态传输数据 -->
    <Category title="美食" >
    <img src="@/assets/hotpot.jpg" alt="">
     <!-- 将元素插入指定名字插槽内 -->
    <!-- vue对具名插槽的新写法 简写形式:#插槽名 -->
    <template >
      <div class="foot"><a href="">更多美食</a></div>
    </template>
  </Category>

   <!-- <Category title="书籍" :listData="books"/> -->
   <Category title="书籍">
    <ul>
      <li v-for="(item,index) in books" :key="index">{{item}}</li>
    </ul>
    <!-- 将元素插入指定名字插槽内 -->
    <!-- 传统用法:slot="插槽名" -->
    <div class="foot" slot="link" >
      <a href="https://www.taobao.com/" >去淘宝</a>
      <a href="https://www.taobao.com/" >去京东</a>
    </div>
    
    <br>
    <!--<a href="https://www.taobao.com/">去淘宝</a>
    <br>
    <a href="https://www.taobao.com/">去淘宝</a> -->
  </Category>

   <!-- <Category title="电影" :listData="films"/> -->
   <Category title="电影">
    <video src="@/assets/1.mp4" controls></video>
    <!-- 将元素插入指定名字插槽内-->
    <!-- vue对具名插槽的新写法,v-slot:插槽名-->
    <template v-slot:link>
      <div class="foot">
        <a href="">经典</a>
        <a href="">热门</a>
        <a href="">推荐</a>
      </div>
      <h4>欢迎前来观影</h4>
    </template>
  </Category>
  </div>
</template>

<script scope="this api replaced by slot-scope in 2.5.0+">
import Category from './components/Category.vue';
export default {
  name: 'App',
  components: {
    Category,
  },
  data(){
    return{
      // 定义数据
      foods:['火锅','重庆火锅','小龙虾','牛排'],
      books:['语文','数学','英语','化学'],
      films:['重庆森林','七龙珠','犬夜叉','心灵捕手'],
    }
  }
}
</script>

<style >
#app,.foot{
  display: flex;
  justify-content: space-around;
}
img{
  width: 100%;
}
video{
  width: 100%;
}
h4{
  text-align: center;
}
</style>

2.3 作用域插槽(待更新吧)

相关文章:

  • .NET教程 - 字符串 编码 正则表达式(String Encoding Regular Express)
  • Yii - [新]项目开发流程指南
  • 优秀的你在哪里?《阿里云SLS团队2023校园招聘》
  • 【图像分类】基于matlab多种特征结合支持向量机脑MRI肿瘤分类【含Matlab源码 2149期】
  • 06-使用pytorch实现手写数字识别
  • 高级特效开发阶段学习总结
  • WPF 简单的ComboBox自定义样式。
  • Servlet 规范和 Servlet 容器
  • 切面的优先级、基于XML的AOP实现
  • 【Java面试宝典】常用类中的方法重写|equals方法与逻辑运算符==的区别
  • 重构的原则
  • Restyle起来!
  • 【Unity3D日常BUG】Unity3D中出现“unsafe code 不安全的代码”的错误时的解决方法
  • Node中实现一个简易的图片验证码流程
  • java-Lambda表达式
  • 【Leetcode】101. 对称二叉树
  • JS 中的深拷贝与浅拷贝
  • @angular/forms 源码解析之双向绑定
  • 11111111
  • Asm.js的简单介绍
  • create-react-app项目添加less配置
  • css的样式优先级
  • gops —— Go 程序诊断分析工具
  • HTML-表单
  • java正则表式的使用
  • Js基础知识(一) - 变量
  • Spark学习笔记之相关记录
  • Spring Cloud(3) - 服务治理: Spring Cloud Eureka
  • tensorflow学习笔记3——MNIST应用篇
  • 大型网站性能监测、分析与优化常见问题QA
  • 分享几个不错的工具
  • 盘点那些不知名却常用的 Git 操作
  • 前端学习笔记之原型——一张图说明`prototype`和`__proto__`的区别
  • 入口文件开始,分析Vue源码实现
  • 数据仓库的几种建模方法
  • ​二进制运算符:(与运算)、|(或运算)、~(取反运算)、^(异或运算)、位移运算符​
  • #stm32整理(一)flash读写
  • #我与Java虚拟机的故事#连载15:完整阅读的第一本技术书籍
  • (二)springcloud实战之config配置中心
  • (附源码)springboot教学评价 毕业设计 641310
  • (附源码)小程序 交通违法举报系统 毕业设计 242045
  • (十八)devops持续集成开发——使用docker安装部署jenkins流水线服务
  • .cn根服务器被攻击之后
  • .md即markdown文件的基本常用编写语法
  • .net core 实现redis分片_基于 Redis 的分布式任务调度框架 earth-frost
  • .net 调用php,php 调用.net com组件 --
  • .net(C#)中String.Format如何使用
  • .NET/C# 编译期能确定的字符串会在字符串暂存池中不会被 GC 垃圾回收掉
  • .NET/C# 反射的的性能数据,以及高性能开发建议(反射获取 Attribute 和反射调用方法)
  • .netcore 获取appsettings
  • .net连接MySQL的方法
  • .NET命名规范和开发约定
  • .NET设计模式(2):单件模式(Singleton Pattern)
  • /etc/fstab 只读无法修改的解决办法
  • [BZOJ] 1001: [BeiJing2006]狼抓兔子