首页 > 其他分享 >聊聊vue中的vue中的slot与slot-scope

聊聊vue中的vue中的slot与slot-scope

时间:2024-03-29 14:22:43浏览次数:20  
标签:slot vue 插槽 html 菜单 组件 scope 模板

前言:

  vue中关于插槽的文档说明很短,语言又写的很凝练,再加上其和methods,data,computed等常用选项使用频率、使用先后上的差别,这就有可能造成初次接触插槽的开发者容易产生“算了吧,回头再学,反正已经可以写基础组件了”,于是就关闭了vue说明文档。

  

实际上,插槽的概念很简单,下面通过分三部分来讲。这个部分也是按照vue说明文档的顺序来写的。

进入三部分之前,先让还没接触过插槽的同学对什么是插槽有一个简单的概念:插槽,也就是slot,是组件的一块HTML模板,这块模板显示不显示、以及怎样显示由父组件来决定。 实际上,一个slot最核心的两个问题这里就点出来了,是显示不显示和怎样显示。

由于插槽是一块模板,所以,对于任何一个组件,从模板种类的角度来分,其实都可以分为非插槽模板和插槽模板两大类。
非插槽模板指的是html模板,指的是‘div、span、ul、table’这些,非插槽模板的显示与隐藏以及怎样显示由插件自身控制;插槽模板是slot,它是一个空壳子,因为它显示与隐藏以及最后用什么样的html模板显示由父组件控制。但是插槽显示的位置确由子组件自身决定,slot写在组件template的哪块,父组件传过来的模板将来就显示在哪块。

 

单个插槽 | 默认插槽 | 匿名插槽

首先是单个插槽,单个插槽是vue的官方叫法,但是其实也可以叫它默认插槽,或者与具名插槽相对,我们可以叫它匿名插槽。因为它不用设置name属性。

单个插槽可以放置在组件的任意位置,但是就像它的名字一样,一个组件中只能有一个该类插槽。相对应的,具名插槽就可以有很多个,只要名字(name属性)不同就可以了。

下面通过一个例子来展示。

父组件:

<template>
    <div class="father">
        <h3>这里是父组件</h3>
        <child>
            <div class="tmpl">
              <span>菜单1</span>
              <span>菜单2</span>
              <span>菜单3</span>
              <span>菜单4</span>
              <span>菜单5</span>
              <span>菜单6</span>
            </div>
        </child>
    </div>
</template>

子组件:

<template>
    <div class="child">
        <h3>这里是子组件</h3>
        <slot></slot>
    </div>
</template>

 在这个例子里,因为父组件在<child></child>里面写了html模板,那么子组件的匿名插槽这块模板就是下面这样。也就是说,子组件的匿名插槽被使用了,是被下面这块模板使用了。

<div class="tmpl">
  <span>菜单1</span>
  <span>菜单2</span>
  <span>菜单3</span>
  <span>菜单4</span>
  <span>菜单5</span>
  <span>菜单6</span>
</div>

最终的渲染结果如图所示:

 注:所有demo都加了样式,以方便观察。其中,父组件以灰色背景填充,子组件都以浅蓝色填充。

具名插槽

匿名插槽没有name属性,所以是匿名插槽,那么,插槽加了name属性,就变成了具名插槽。具名插槽可以在一个组件中出现N次。出现在不同的位置。下面的例子,就是一个有两个具名插槽和单个插槽的组件,这三个插槽被父组件用同一套css样式显示了出来,不同的是内容上略有区别。

父组件:

<template>
  <div class="father">
    <h3>这里是父组件</h3>
    <child>
      <div class="tmpl" slot="up">
        <span>菜单1</span>
        <span>菜单2</span>
        <span>菜单3</span>
        <span>菜单4</span>
        <span>菜单5</span>
        <span>菜单6</span>
      </div>
      <div class="tmpl" slot="down">
        <span>菜单-1</span>
        <span>菜单-2</span>
        <span>菜单-3</span>
        <span>菜单-4</span>
        <span>菜单-5</span>
        <span>菜单-6</span>
      </div>
      <div class="tmpl">
        <span>菜单->1</span>
        <span>菜单->2</span>
        <span>菜单->3</span>
        <span>菜单->4</span>
        <span>菜单->5</span>
        <span>菜单->6</span>
      </div>
    </child>
  </div>
</template>

子组件:

<template>
  <div class="child">
    // 具名插槽
    <slot name="up"></slot>
    <h3>这里是子组件</h3>
    // 具名插槽
    <slot name="down"></slot>
    // 匿名插槽
    <slot></slot>
  </div>
</template>

显示结果如图:

 

可以看到,父组件通过html模板上的slot属性关联具名插槽。没有slot属性的html模板默认关联匿名插槽。

作用域插槽 | 带数据的插槽

最后,就是我们的作用域插槽。这个稍微难理解一点。官方叫它作用域插槽,实际上,对比前面两种插槽,我们可以叫它带数据的插槽。什么意思呢,就是前面两种,都是在组件的template里面写

匿名插槽
<slot></slot>
具名插槽
<slot name="up"></slot>

但是作用域插槽要求,在slot上面绑定数据。也就是你得写成大概下面这个样子。

<slot name="up" :data="data"></slot>
 export default {
    data: function(){
      return {
        data: ['zhangsan','lisi','wanwu','zhaoliu','tianqi','xiaoba']
      }
    },
}

我们前面说了,插槽最后显示不显示是看父组件有没有在child下面写模板,像下面那样。

<child>
   html模板
</child>

写了,插槽就总得在浏览器上显示点东西,东西就是html该有的模样,没写,插槽就是空壳子,啥都没有。
OK,我们说有html模板的情况,就是父组件会往子组件插模板的情况,那到底插一套什么样的样式呢,这由父组件的html+css共同决定,但是这套样式里面的内容呢?

正因为作用域插槽绑定了一套数据,父组件可以拿来用。于是,情况就变成了这样:样式父组件说了算,但内容可以显示子组件插槽绑定的。

我们再来对比,作用域插槽和单个插槽和具名插槽的区别,因为单个插槽和具名插槽不绑定数据,所以父组件是提供的模板要既包括样式由包括内容的,上面的例子中,你看到的文字,“菜单1”,“菜单2”都是父组件自己提供的内容;而作用域插槽,父组件只需要提供一套样式(在确实用作用域插槽绑定的数据的前提下)。

下面的例子,你就能看到,父组件提供了三种样式(分别是flex、ul、直接显示),都没有提供数据,数据使用的都是子组件插槽自己绑定的那个人名数组。

父组件:

<template>
  <div class="father">
    <h3>这里是父组件</h3>
    <!--第一次使用:用flex展示数据-->
    <child>
      <template slot-scope="user">
        <div class="tmpl">
          <span v-for="item in user.data">{{item}}</span>
        </div>
      </template>
 
    </child>
 
    <!--第二次使用:用列表展示数据-->
    <child>
      <template slot-scope="user">
        <ul>
          <li v-for="item in user.data">{{item}}</li>
        </ul>
      </template>
 
    </child>
 
    <!--第三次使用:直接显示数据-->
    <child>
      <template slot-scope="user">
       {{user.data}}
      </template>
 
    </child>
 
    <!--第四次使用:不使用其提供的数据, 作用域插槽退变成匿名插槽-->
    <child>
      我就是模板
    </child>
  </div>
</template>

子组件:

<template>
  <div class="child">
 
    <h3>这里是子组件</h3>
    // 作用域插槽
    <slot  :data="data"></slot>
  </div>
</template>
 
 export default {
    data: function(){
      return {
        data: ['zhangsan','lisi','wanwu','zhaoliu','tianqi','xiaoba']
      }
    }
}

结果如图所示:

 

p.s slot 与 slots 的区别:

slot用来定义插槽,slots相当于refs的用法,用来获取vue组件中定义的slot,实现内容分发。

eg.

html

<div id="app6">
    <child6>
        <h2 slot="header">人工智能识别人体姿态的秘密</h2>
        <p>人体姿态识别成为人工智能最新渗透的领域。据国外媒体报道,英国曼彻斯特大学和西班牙马德里大学的合作研究团队最新AI步态识别技术识别准确率高达93%,是目前AI步态识别的最高水平。日本电信公司NTT
            East和科技公司Earth eye合作开发的AI
            Guardsman系统则可以通过肢体动作识别,实时追踪顾客购物行为,帮助经营者及时发现商店中的小偷。瑞士洛桑联邦理工学院生物机器人实验室的步态识别系统可以精确计算走路时所消耗的卡路里,未来将搭载在一套可穿戴设备上,提醒用户调整最佳走路姿势,保护身体关节或更好地通过走路燃烧卡路里。</p>
        <div slot="footer">Copyright © Deniro</div>
    </child6>
</div>

js

Vue.component('child6', {
    template: '\
    <div class="page">\
        <div class="header">\
            <slot name="header"></slot>\
                <div class="main>">\
                <slot></slot>\
                </div>\
                <div class="footer">\
                    <slot name="footer"></slot>\
                </div>\
         </div>\
     </div>',
    mounted: function () {
        var header = this.$slots.header;
        console.log("header:" + header);
        console.log("headerInnerHTML:" + header[0].elm.innerHTML);

        var main=this.$slots.default;
        console.log("main:" + main);
        console.log("mainInnerHTML:" + main[1].elm.innerHTML);
    }
});
var app6 = new Vue({
    el: '#app6',
    data: {}
});

输出结果:

 

一般在开发独立组件的过程中,会用到 slot 访问操作。

 

标签:slot,vue,插槽,html,菜单,组件,scope,模板
From: https://www.cnblogs.com/caihongmin/p/18103766

相关文章

  • 基于Java+Vue的企业采购系统(供应商、询价、招投标)(附文档+源码)
      前言:供应商招投标管理系统是一个综合性的管理平台,旨在规范供应商的招投标流程,确保采购过程的透明度和公正性,同时提高采购效率。以下是对您提到的各个环节的详细解释:一、供应商准入供应商准入是招投标管理系统的首要环节,它负责审核和管理潜在供应商的资质。具体流程包括......
  • 一个vue3指令,兼容pc与移动端的拖动tab切换,鼠标拖动与触摸拖动触控监听
    <Viewclass="app-tabs-container":class="{appear:state.showTabsTrans}"v-tabs-pointer-event:[state.hasMove]="handleProductChange"><router-viewv-slot="{Component}"><KeepAlive>......
  • Pinia及其优化:Vue状态管理的解决方案
    pinia及其优化目录1.pinia状态管理库2.pinia的使用步骤2.1安装2.2使用pinia2.3定义store2.4使用store3.axios请求拦截器(优化pinia)3.1问题缘由3.2优化方法4.Pinia持久化插件-persist4.1安装4.2使用1.pinia状态管理库Pinia是Vue的专属状态管理库,它......
  • Vue:实现子组件和父组件数据的双向绑定案例和sync修饰符简化
    实现子组件和父组件数据的双向绑定(实现App.vue中的selectId和子组件选中的数据进行双向绑定)代码案例BaseSelect.vue<template><div><select:value="selectId"@change="selectCity"><optionvalue="101">北京</option><op......
  • MybatisPlus多参数分页查询,黑马程序员SpringBoot3+Vue3教程第22集使用MP代替pagehelpe
    前言:视频来源1:黑马程序员SpringBoot3+Vue3全套视频教程,springboot+vue企业级全栈开发从基础、实战到面试一套通关视频来源2:黑马程序员最新MybatisPlus全套视频教程,4小时快速精通mybatis-plus框架创作理由:网上MP实现分页查询功能的帖子易读性太差,具体实现看下面。根据视频完成......
  • Vue+.Net6部署日记
    一.准备工作vue编译后以dist文件夹在iis新建一个网站,.Net6发布后同样的建站但是要注意把应用程序池设置为无托管模式二.配置反向代理IIS给前端方向代理需要以下两个组件:1.ARR2.Url重写;这两个组件都可以在www.iis.net搜到,在搜索栏输入关键词然后一个个找就好,先确保下......
  • 在vue中 使用v-if时它的响应式系统会作哪些优化
    前言:有时我们没在一个组件做初始化数据的工作,只是在template下的根元素加了个v-if控制显示,这样一来也能达到初始化数据的目的。但其背后的原理是什么? 在Vue2.x中,当你使用v-if指令将一个组件或元素的条件设置为false,使得它在DOM中不可见时,Vue的响应式系统会进行一些......
  • vue3项目数字金额转大写
    consttoUpperCaseAmount=(value)=>{ //将数字金额转换为大写的逻辑 constdigitUppercase=['零','壹','贰','叁','肆','伍','陆','柒','捌','玖']; constunit=[......
  • 免费分享一套SpringBoot+Vue个人健康管理系统,帅呆了~~
    大家好,我是java1234_小锋老师,看到一个不错的SpringBoot+Vue个人健康管理系统,分享下哈。项目视频演示【免费】SpringBoot+Vue个人健康管理系统Java毕业设计_哔哩哔哩_bilibili【免费】SpringBoot+Vue个人健康管理系统Java毕业设计项目来自互联网,免费开源分享,严禁商业。更多......
  • Ant Design Vue Tree 选中子节点同时半选中父级节点
    需要实现的效果:1、子菜单如果不是全部选中,一级菜单半选。2、子菜单全选,一级菜单选中。3、一级菜单选择,二级菜单全选。4、没有二级菜单,则只控制一级菜单。主要用到的属性是checked和halfCheckedKeys,通过手动控制那些菜单选中,那些半选中实现功能。**页面截图:**完整代码如......