专栏首页大前端技术沙龙vue作用域插槽,你真的懂了吗?

vue作用域插槽,你真的懂了吗?

前言

在网上搜了很多关于作用域插槽的解释,感觉没有写得很具体的吧,我认为应该对组件化有很深的理解才会触及到这个问题吧,这里也分享下我自己对于slot-scope的一点理解。

01

vue插槽的简单介绍

NO.1

slot大家看看文档都懂了,无非就是在子组件中挖个坑,坑里面放什么东西由父组件决定。

// 子组件
<template>
  <slot>来啊,我这里挖了个坑</slot>
</template>

// 父组件
<template>
  <child>
   <!-- 传入子组件的自定义内容,会填入到子组件的slot插槽中 -->
    <span>我在这放个span,乐意的话,放个组件都行</span>
  </child>
</template>

slot填充普通文本

slot填充组件

NO.2

具名插槽也很简单,比如有多个插槽,我作为父组件,肯定想区别子组件中的几个插槽,那就要用slot标签的name属性来标识了,而父组件要决定在什么插槽里面放什么内容,就要将name的值赋值给slot属性传递给对应的插槽。如果slot没有name属性,就是匿名插槽了,而父组件中不指定slot属性的内容,就会被丢到匿名插槽中。

// 子组件
<template>
    <section>
        <slot name="article-title">这里放标题</slot>
        <slot>这里放作者</slot>
        <slot name="article-content">这里放文章内容</slot>
    </section>
</template>

// 父组件
<template>
    <section>
        <slot-child>
            <h1 slot="article-title">vue作用域插槽,你真的懂了吗?</h1>
            <p slot="article-content">好像有点懂了</p>
            <div>王五</div>
        </slot-child>
    </section>
</template>

NO.3

最难理解的是作用域插槽。看了文档说明的朋友可能还会有点晕,大概是说在作用域插槽内,父组件可以拿到子组件的数据。子组件可以在slot标签上绑定属性如nickName,而父组件通过slot-scope绑定的对象下拿到nickName的值。

// 子组件
<slot :nickName="'Tusi'"></slot>

// 父组件
<template>
    <section>
        <slot-child>
            <template slot-scope="scope">
                <div>{{scope.nickName}}</div>
            </template>
        </slot-child>
    </section>
</template>

这里大家应该都有疑问。这有什么用?我在子组件用$emit向父组件传递数据不就行了?

关于作用域插槽的一点理解

1

假设第一个场景,需要你写一个商品卡片组件,并通过循环去展示多个卡片,并且要求能响应每个卡片上的图片或者其他内容的点击事件而跳转到商品详情页,你会怎么写?

我会使用如下的处理方式,首先将商品卡片写成一个组件Commodity.vue,而在CommodityList.vue中用一个v-for来处理商品卡片列表的展示。

<commodity v-for="(item,index) in commodities" @clickCommodity="onCommodityClick"></commodity>

Commodity组件通过$emit像父组件传递clickCommodity事件,并携带商品数据,父组件即可在onCommodityClick方法中得到数据,进行业务处理,这样便完成了一个基本的由子到父的数据传递。

2

如果再往上抽象一下呢?比如我有多个运营栏目,像淘宝首页有“有好货”,“爱逛街”这样两个栏目,每个栏目下都需要有一个商品卡片列表,那么商品卡片列表CommodityList.vue就要抽成组件了。而这个包含多个运营栏目的vue组件我假设它叫ColumnList.vue,在其中通过v-for调用了CommodityList组件。

注意:业务来了,我希望把点击商品卡片的业务放在ColumnList.vue中处理。你们想象一下要怎么做?一种土办法就是商品按钮点击时,Commodity组件\emit通知CommodityList.vue,而CommodityList接着把事件用\emit往上抛,那么ColumnList.vue就能处理这个点击事件了。这样做完全没有问题,但是显得子组件很不纯粹,跟业务都扯上关系了。

那么如何优雅地解决这个问题呢?这个时候,作用域插槽真正派上用场了。

通过作用域插槽将本应该由CommodityList处理的商品卡片点击业务onCommodityClick提升到ColumnList处理。

<el-row :gutter="20">
        <el-col :span="12" v-for="(column, index) in columnList" :key="index">
            <el-card class="box-card card-column">
                <div slot="header" class="clearfix">
                    <span>{{column.columnName}}</span>
                </div>
                <commodity-list :commodities="column.commodityList">
                    <template slot-scope="scope">
                    <!-- 这里只需要给Commodity组件传入数据,响应Commodity组件的clickCommodity事件即可。
                        事件不必携带参数,完全符合父到子的数据流向,而不会发生子组件又给父组件反向发数据的情况 -->
                        <commodity :modityData="scope.row" @clickCommodity="onCommodityClick(scope.row)"></commodity>
                    </template>
                </commodity-list>
            </el-card>
        </el-col>
</el-row>

而CommodityList组件内部应该是改造成这样,slot接收来自父组件的商品卡片组件,这里面不涉及关于商品组件的业务,只关注其他业务和布局即可。最终就实现了组件和业务的剥离,这也是组件化的精髓所在吧。不知道有没有帮到您呢?

<el-row :gutter="20">
        <el-col :span="8" v-for="(item, index) in commodities" :key="index" style="margin-top:20px;">
            <slot :row="item"></slot>
        </el-col>
</el-row>

这是我实现的效果,忽略样式吧,原理都懂了,做个漂亮的卡片有多难?

总结一下

作用域插槽适合的场景是至少包含三级以上的组件层级,是一种优秀的组件化方案!

本文分享自微信公众号 - 大前端技术沙龙(is_coder),作者:Tusi

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-03-10

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 关于数据类型的一些小疑惑 ​

    上期在阅读《Javascript权威指南》第六版类型转换这一章节的时候,我虽然搞清楚了之前留下的很多疑问,比如说数据类型转换的基本规则,对象到原始值的转换规则等...

    Tusi
  • 从部署上做到前后端分离

    记得在让Nodejs支持H5 History模式(connect-history-api-fallback源码分析)一文中提到了 HTML5 的 History...

    Tusi
  • 从零到部署:用 Vue 和 Express 实现迷你全栈电商应用(三)

    这篇文章中,我们将讲解 Vue 实例的 Props 和 Methods,接着我们又讲解了最常见的 Vue 模板语法,并通过实例的方式将这些模板语法都实践了一番,...

    Tusi
  • Vue中的slot、slot-scope和v-slot

    插槽,也就是slot,是组件的一块HTML模板,这块模板显示不显示、以及怎样显示由父组件来决定。值得注意的是:内容要写在父组件中,然后分给需要的子组件,当slo...

    刘亦枫
  • 组件插槽

    星辰_大海
  • Vue插槽slot

    使用了那么久的vue,到现在才知道vue自带的组件插槽slot,说真的,插槽的作用在一些场景下非常有用。

    wade
  • vue组件-template和slot插槽详细介绍

    vue项目,组件应用非常广泛,感觉只要能被多个地方复用的代码,都可以写成组件,这样不用做重复的工作。github上面也有很多大牛制造了n个轮子,方便大家使用。之...

    Javanx
  • 前端开发:插槽(slot)的使用

    在Vue.js开发过程中,插槽的使用也是非常常见的,对于刚入门的新手来说对于这种概念性的知识的认识还是不是太清楚,那么本篇博文就来分享一下关于插槽的使用。

    三掌柜
  • 前端开发:插槽(slot)的使用

    在Vue.js开发过程中,插槽的使用也是非常常见的,对于刚入门的新手来说对于这种概念性的知识的认识还是不是太清楚,那么本篇博文就来分享一下关于插槽的使用。

    三掌柜
  • MPM 卖场可视化搭建系统 — 要素设计

    当组织团队达到一定的开发规模时,页面可视化搭建是一个减少冗复开发、释放生产力的最有效方案。由于专人专责,在平时的实际工作中,我们接触的大多都是一些比较固定的业务...

    WecTeam

扫码关注云+社区

领取腾讯云代金券