Vue组件开发实践之scopedSlot的传递
收录待用,修改转载已取得腾讯云授权
导语
现今的前端开发都讲究模块化组件化,即把公共的交互和功能封装到一个个的组件之中,在开发整体界面的时候就能像搭积木一样快速清晰高效。在使用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实现很轻松:
<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结构示意:
<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结构示意:
<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函数),看看有什么奥秘:
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里那么自然的书写
v-popper:third.click
而是需要workaround:
Pass everything as an object via value, e.g. v-name={{ value, modifier: true }}
Use the raw vnode directive data format:
上面的例子中就是用了方法二。
v-model
render函数(JSX也是写在render函数中)中没有与v-model
相应的api -
你必须自己来实现相应的逻辑。即通过value属性传递值,并通过绑定input事件来响应变化。
没有template 中的v-if
和 v-for
:
这意味着我们需要在render函数或者JSX的表达式中手写if-else逻辑判断。或者如本例中使用三目表达式来实现。
这就是深入底层要付出的,尽管麻烦了一些,但你可以更灵活地控制。
希望这边文章能让我们在开发Vue组件的时候少走一些弯路,如果有大神有更好的办法或直接在template中实现传递scoped slot的功能,请多多指教!
原文链接:https://www.qcloud.com/community/article/693017
Vue组件开发实践之scopedSlot的传递的更多相关文章
- vue前端开发那些事——vue组件开发
vue的学习曲线不是很陡(相比其它框架,如anglarjs),官方文档比较全面,分为基础篇和高级篇.我们刚开始学习的时候,肯定像引用jquery那样,先把vue的js引进来,然后学习基础内容.如果仅仅 ...
- COM组件开发实践(八)---多线程ActiveX控件和自动调整ActiveX控件大小(下)
源代码下载:MyActiveX20081229.rar 声明:本文代码基于CodeProject的文章<A Complete ActiveX Web Control Tutorial>修改 ...
- [vue]webpack&vue组件工程化实践
[vue]全局组件和局部组件(嵌套+props引用父组件数据) [vue]组件篇 [vue]组件的创建(componet)和销毁(keep-alive缓存)和父子dom同步nextTick [vue] ...
- Vue组件开发实例(详细注释)
Vue组件开发实例: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> &l ...
- vue组件最佳实践
看了老外的一篇关于组件开发的建议(强烈建议阅读英文原版),感觉不错翻译一下加深理解. 这篇文章制定一个统一的规则来开发你的vue程序,以至于达到一下目的. 1.让开发者和开发团队更容易发现一些事情. ...
- Vue (三) --- Vue 组件开发
------------------------------------------------------------------好心情,会让你峰回路转. 5. 组件化开发 5.1 组件[compo ...
- vue 组件开发、vue自动化工具、axios使用与router的使用(3)
一. 组件化开发 1.1 组件[component] 在网页中实现一个功能,需要使用html定义功能的内容结构,使用css声明功能的外观样式,还要使用js定义功能的特效,因此就产生了一个功能先关的代码 ...
- 三: vue组件开发及自动化工具vue-cli
一: 组件化开发 1 组件 1: 组件(Component)是自定义封装的功能.在前端开发过程中,经常出现多个网页的功能是重复的,而且很多不同的网站之间,也存在同样的功能. 2: 什么是组件 而在网页 ...
- vue 开发系列(三) vue 组件开发
概要 vue 的一个特点是进行组件开发,组件的优势是我们可以封装自己的控件,实现重用,比如我们在平台中封装了自己的附件控件,输入控件等. 组件的开发 在vue 中一个组件,就是一个独立的.vue 文件 ...
随机推荐
- NOIP2011 D1 T2选择客栈
上题目: 题目描述 丽江河边有n 家很有特色的客栈,客栈按照其位置顺序从 1 到n 编号.每家客栈都按照某一种色调进行装饰(总共 k 种,用整数 0 ~ k-1 表示),且每家客栈都设有一家咖啡店,每 ...
- cogs——2478. [HZOI 2016]简单的最近公共祖先
2478. [HZOI 2016]简单的最近公共祖先 ★☆ 输入文件:easy_LCA.in 输出文件:easy_LCA.out 简单对比时间限制:2 s 内存限制:128 MB [题 ...
- JavaScript with JSONPath
<html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>JavaScript JSO ...
- python语言特性总结
一直想学习python,虽然编程写了不少,但有时仍不得要领.这篇blog主要是记录python的一些主要特性. 前言 python学习总结,包括python的一些基本语法,高级特性,函数式编程,面向对 ...
- MySQL笔记(一)之新建数据库和数据表
创建数据库 CREATE DATABASE database_name 创建数据表 CREATE TABLE table_name ( 列1 数据类型, 列2 数据类型, 列3 数据类型, .... ...
- web项目启动执行方法
近期在项目中需要将用户在web启动时就查询出来,当作缓存使用. 一.首先需要实现 ServletContextListener 接口 public class UserCacheUtils imple ...
- Hibernate 单项一对多的关联映射
在上一篇中我们简单介绍了多对一的关联映射,本文介绍hibernate中一对多的关联映射. 1.设计表结构 虽然关联关系由多对一变为一对多,但是我们表结构不会发生改变,只是指向变了. 2.创建stude ...
- 【BZOJ 3482】 3482: [COCI2013]hiperprostor (dij+凸包)
3482: [COCI2013]hiperprostor Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 277 Solved: 81 Descrip ...
- [Codeforces #201] Tutorial
Link: 传送门 代码量很少的一套思维题 A: 试一试发现最后状态一定是所有$min,max$间$gcd$的倍数 直接判断数量的奇偶性即可 #include <bits/stdc++.h> ...
- 《时间序列分析——基于R》王燕,读书笔记
笔记: 一.检验: 1.平稳性检验: 图检验方法: 时序图检验:该序列有明显的趋势性或周期性,则不是平稳序列 自相关图检验:(acf函数)平稳序列具有短期相关性,即随着延迟期数k的增加 ...