前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Vue 组件开发实践之 scopedSlot 的传递

Vue 组件开发实践之 scopedSlot 的传递

原创
作者头像
谭伟华
修改于 2017-06-19 11:02:53
修改于 2017-06-19 11:02:53
12.3K10
代码可运行
举报
文章被收录于专栏:谭伟华的专栏谭伟华的专栏
运行总次数:0
代码可运行

导语

现今的前端开发都讲究模块化组件化,即把公共的交互和功能封装到一个个的组件之中,在开发整体界面的时候就能像搭积木一样快速清晰高效。在使用Vue开发我们的vhtml-ui的组件库的过程中遇到了组件嵌套组件时需要传递scopedSlot的情况,官方的文档和教程目前还没有比较明确的指引,所以摸着石头过河,调通了想要的效果。记录下来方便大家和自己。

在Vue中,为了让组件可以组合,我们使用Slot来混合父组件的内容与子组件自己的模板。这样就实现了Vue的内容分发。

Scoped Slot(作用域插槽)是在Vue 2.1引入的更进阶的功能,它是一种特殊类型的slot,用作使用一个(能够传递数据到)可重用模板替换已渲染元素。我的理解就是使用scoped slot能在插槽里自定义模板并且使用组件传递过来的context。这大大提高了组件开发的灵活性。

Select组件一期

在开发我们的select组件时很自然就用上了scoped slot这一特性。我们需要遍历数据中的选项数组,渲染成界面上的下拉选项列表。如果是比较复杂的允许自定义的list item,在组件里写死dom结构就行不通了,比如:

有了scoped slot实现很轻松:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制

    <v-select kind="popup" :options="options4">
        <template slot="listItem" scope="props">
            <div>
                <div><span>{{ props.item.text }}<span> | <span>{{ props.item.value }}<span></div><div>{{ props.item.area }}</div>
                <div>{{ props.item.url }}</div>
            </div>
        </template>
    </v-select>

很好,非常好,现在有一个新需求:这个列表有的时候想要脱离select使用,比如就直接展示在页面上,不需要通过下拉弹出。

select-list组件

这好办啊,作为组件开发的老司机们自然能想到把这个list独立做成一个组件,页面可以直接调用,select组件也可以在它之上再封装一层。

完美!

开干!

select-list template结构示意:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    <ul class="v-select-list">
        <li class="v-select-list__item" v-for="(item, index) in options">
            <slot name="listItem" :item="item">
                <span>{{ item.text }}</span>
            </slot>
        </li>
    </ul>

select template结构示意:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    <div class="v-select">
        <v-popper>
            <v-select-list>
                <slot name="listItem">
                </slot>
            </v-select-list>
        </v-popper>
    </div>

然后问题来了,最里层的select-list组件并没有接收到用户自定义的scoped slot。通过查找Vue官方文档以及谷歌,也没有找到使用template方式传递scoped slot的介绍和例子。

Render函数和JSX

人总不能让尿给憋死,一条路走不通我们就看看有没有其他办法。在Vue的官方文档上有这么一句话:

“ Vue 推荐在绝大多数情况下使用 template 来创建你的 HTML。然而在一些场景中,你真的需要 JavaScript 的完全编程的能力,这就是 render 函数,它比 template 更接近编译器。”

查看文档,通过render函数确实能够传递scoped slot,以下图的方式

把scoped slot作为createElement方法的第二参数(data object)的一个属性传递到子组件中。

但是render函数的缺点就是不灵活,特别是在定义你的组件的dom结构模板的时候,如果写很多 render 函数,可能会觉得痛苦。它比较适用于外层组件仅仅是对内层组件的一次逻辑封装,而渲染的模板结构变化扩展不多的情况。

还好我们还有最后一把杀手锏--JSX。它可以让我们回到于更接近模板的语法上。具体关于JSX的使用不是本文的主题,我们可以阅读使用文档 ,学习关于 JSX 映射到 JavaScript的用法。

JSX实现上文的嵌套例子

通过参阅文档及不断地摸索,最终实现了自己想要的功能。我们直接上关键代码(select的render函数),看看有什么奥秘:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
render(h) {
        let directives = [{
            name: 'popper',
            arg: 'selector',
            modifiers: { click: true }
        }];

        return (
            <div
                class={{ 'v-select': true, 'is-open': this.isPopperShown, 'is-disabled': this.disabled }}>
                <v-popper
                    ref="selector"
                    placement="bottom-start"
                    onVisibleChange={this.togglePopper}>
                    <v-select-list
                        class="v-select__options"
                        onChange={this.handleChange}
                        multiple={this.multiple}
                        value={this.currentValue}
                        onInput={this.handleListInput}
                        scopedSlots={{listItem: this.$scopedSlots.listItem}} >
                    </v-select-list>
                </v-popper>
                <div
                    class="v-select__header"
                    { ...{directives} }>
                    {
                        this.currentIndex !== -1 && this.$scopedSlots.headItem ? this.$scopedSlots.headItem(this.current)
                            : (<span>{this.currentText}</span>)
                    }
                    <v-icon
                        class="v-select__header-arrow"
                        name="v-arrow_dropdown">
                    </v-icon>
                </div>
            </div>
        )
    }

关键点:

  • 在子组件的标签上通过scopedSlots 属性可以向其传递自己的scoped slot;
  • 自身的scoped slot可以通过this.$scopedSlots 对象获取,默认就是default,具名slot就是它的名字。本例为“listItem”;
  • 如果不在标签上传递而是需要使用表达式传递,也可以通过 this.$scopedSlots对象。并且一个具体的scoped slot对象其实就是一个函数,其内部的scope可以在参数中传入。比如本例中的this.$scopedSlots.headItem(this.current)

JSX中对template常用点的转换

上面的介绍涵盖了基本的用法,但是我们在组件中往往会用一些不基本但常用的vue特性。我们接下来一起看看。

细心地小伙伴可能发现了上面的代码中已经出现了这些用法

directives

如果我们在组件中使用了directives,那么jsx里就不能想之前在template里那么自然的书写

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
v-popper:third.click

而是需要workaround:

  1. Pass everything as an object via value, e.g. v-name={{ value, modifier: true }}
  2. Use the raw vnode directive data format:

上面的例子中就是用了方法二。

v-model

render函数(JSX也是写在render函数中)中没有与v-model相应的api - 你必须自己来实现相应的逻辑。即通过value属性传递值,并通过绑定input事件来响应变化。

没有template 中的v-ifv-for:

这意味着我们需要在render函数或者JSX的表达式中手写if-else逻辑判断。或者如本例中使用三目表达式来实现。

这就是深入底层要付出的,尽管麻烦了一些,但你可以更灵活地控制。

希望这边文章能让我们在开发Vue组件的时候少走一些弯路,如果有大神有更好的办法或直接在template中实现传递scoped slot的功能,请多多指教!

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
1 条评论
热度
最新
一整块的代码能share下,整体看下
一整块的代码能share下,整体看下
回复回复点赞举报
推荐阅读
编辑精选文章
换一批
Vue 2x 中使用 render 和 jsx 的最佳实践 (3)
通过对上面的代码进行分析,不难发现,Vue模板中的每一个元素编译之后都会对应一个createElement。
默默的成长
2022/10/29
4.1K0
Vue之render渲染函数和JSX的应用
我们需要createElement方法,就会想到可以编写个函数组件,将createElement方法传递出来
TimothyJia
2019/11/12
9390
怎么在Vue中写jsx语法,以及render函数
最近遇到一个项目,是对element-ui进行了二次封装,做了一些自己的组件库,其中很多实现都是render函数配合template模板实现的,还有就是表单这块是一块比较复杂的业务逻辑,里面用到了jsx语法,我也抽时间研究了jsx在vue中怎么使用,所以记录下自己写的demo,后面好进行查漏补缺。
玖柒的小窝
2021/10/31
3.3K0
怎么在Vue中写jsx语法,以及render函数
vue源码分析-插槽原理
插槽的原理,贯穿了整个组件系统编译到渲染的过程,所以首先需要回顾一下对组件相关编译渲染流程,简单总结一下几点:
yyzzabc123
2022/10/18
7610
Vue 中 JSX 的基本用法
首先需要约定一下,使用JSX组件命名采用首字母大写的驼峰命名方式,样式可以少的可以直接基于vue-styled-components写在同一个文件中,复杂的建议放在单独的Styles.js文件中,当然也可以不采用CSS-IN-JS的方式,使用Less/Sass来写,然后在文件中import进来。
CRMEB商城源码
2022/06/08
1.2K0
vue2升级vue3:Vue2/3插槽——vue3的jsx组件插槽slot怎么处理
vue 在 2.6 版本中,对插槽使用 v-slot 新语法,取代了旧语法的 slot 和 slot-scope,并且之后的 Vue 3.0 也会使用新语法,这并不是仅写法的不同,还包括了性能的提升
周陆军博客
2022/06/24
2.3K0
学会使用Vue JSX,一车老干妈都是你的
连续几篇文章,每篇都有女神,被掘友给吐槽了,今天不提了女神了,反正女神都是别人的(扎心了)。这两天小编看了腾讯与老干妈的事情,晚上馒头夹老干妈吃起来都感觉很带劲。今天这篇文章将给大家小编在项目中使用JSX的一些实战经验。其实一般情况下写Vue还是比较推荐template的写法的,但是有时候我们真的需要更灵活的去做一些功能,这时候就需要用到JSX了。
前端进击者
2021/07/27
2.9K0
在vue中使用jsx
vue2的:https://cn.vuejs.org/v2/guide/render-function.html#JSX
阿超
2022/08/21
6020
Vue.js render函数那些事儿
大多时候,我会使用template, vue单文件去渲染组件。虽然知道Vue中有个render函数,但却很少在项目中去主动使用它。使用最多的地方是在使用一些UI框架的时候,比如iview table中的按钮操作,会使用到render函数。另外平时在阅读一些Vue UI框架源码的时候,也时常能遇到使用render函数的地方,这也激发了自己研究学习的欲望。如果你也感兴趣,那就继续阅读吧。
前端知否
2020/04/07
2.4K0
Vue.js render函数那些事儿
请你说说 Vue 中 slot 和 slot-scope 的原理(2.6.11 深度解析)
Vue 中的 slot 和 slot-scope 一直是一个进阶的概念,对于我们的日常的组件开发中不常接触,但是却非常强大和灵活。
ssh_晨曦时梦见兮
2020/04/11
1.7K0
Vue 进阶必学之高阶组件 HOC(保姆式教学,冲击20k必备)
高阶组件这个概念在 React 中一度非常流行,但是在 Vue 的社区里讨论的不多,本篇文章就真正的带你来玩一个进阶的骚操作。
ssh_晨曦时梦见兮
2020/04/11
5.5K0
全面了解 Vue.js 函数式组件
如果你是一位前端开发者,又在某些机会下阅读过一些 Java 代码,可能会在后者中看到一种类似 ES6 语法中箭头函数的写法
江米小枣
2021/11/02
2.9K0
Vue核心api和组件开发实践
看完本讲内容,大多数前端初学者就会自以为是地可以在简历写自己"熟练(精通)vue开发“了,最不济也会给自己加个“熟悉掌握vue业务逻辑”的帽子。而对这门课程来说,一切刚刚开始。
一粒小麦
2019/07/18
2.1K0
Vue核心api和组件开发实践
vue之jsx
可以通过 this.$slots 访问静态插槽的内容,每个插槽都是一个 VNode 数组:
hss
2022/02/25
8660
Vue.js-渲染函数 & JSX 原
Vue推荐在绝大多数情况下使用template来创建你的Html,然而在一些场景中,你真的需要JavaScript的完全编程的能力,这就是、render函数,它比template更接近编译器 使用template例子
tianyawhl
2019/04/04
2.6K0
Vue组件开发-高级玩法
在文章《Vue组件开发三板斧:prop、event、slot》中聊了常用的组件开发常用API和一些采坑心得,这里,再说说一些可能不太常用的高级玩法,可参考https://cn.vuejs.org/v2/api/。
娜姐
2020/09/22
2.4K0
Vue组件开发-高级玩法
请你说说 Vue 中 slot 和 slot-scope 的原理(2.6.11 深度解析)
Vue 中的 slot 和 slot-scope 一直是一个进阶的概念,对于我们的日常的组件开发中不常接触,但是却非常强大和灵活。
ssh_晨曦时梦见兮
2024/01/26
5620
渲染函数-深入 data 对象 原
我们平时在家是很少看电视的,最近看了几期最强大脑,真的被震惊到了,为什么他们的大脑容量那么大呢?并且非常机敏。海量的信息可以在很短的时间内记住,真是最遥远的距离莫过于我还没弄明白题目,别人已经答案出来了。感觉对他们来说,考上清华北大真是太容易了。我就想纵然我不能记住很多的信息,难道我认真些,努力些还不能记住几行代码吗?
tianyawhl
2019/04/04
5140
Vue 2.x折腾记 - (20) JSX在业务中的具体实践以及跟React书写的差异化
Vue的jsx,能够支持部分vue独有的特性,比如拿到computed, 指令及自定义事件;
CRPER
2019/05/31
7390
一个合格的中级前端工程师应该掌握的 20 个 Vue 技巧
之前写过一篇文章,关于 Vue 属性透传的,文章中我列举了很多种方法去实现属性透传。其中包括直接设置 props,v-bind="$attrs",render function 等方式。感兴趣,详情看 【Vue 进阶】——如何实现组件属性透传?
GopalFeng
2020/09/24
6.2K0
一个合格的中级前端工程师应该掌握的 20 个 Vue 技巧
相关推荐
Vue 2x 中使用 render 和 jsx 的最佳实践 (3)
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验