摘要:概述库用的是是我们非常常用的组件。有一个特征是选中之后无法取消。现实中取消的需求是常见且可以理解的。所以看到这个需求之后第一尝试在组件之上搞一搞,这一搞就入坑了,现在就来理一理我的入坑之路吧。
概述
ui库用的是iview .
radio、radioGroup是我们非常常用的组件。radio有一个特征是选中之后无法取消。现实中取消radio的需求是常见且可以理解的。
所以看到这个需求之后第一尝试 在iview组件之上搞一搞,这一搞就入坑了,现在就来理一理我的入坑之路吧。
首先我们来看一下在 vue 中使用原生的radio组件如何使用取消。 原生radio取消选中的文章非常多,随便拎一篇看看就行,比如 取消radio的三种方法。
嗯,原理就是给radio元素的checked属性赋值为 false。
具体在 vue 中使用是这样的:
const { name, value } = data;this.radioGroupChange(value, name)} /> {name}; // 方法 radioGroupChange (value, name) { if (this.checked === value) { // 取消选中 this.$refs[name].checked = false; // 当前选中值为空 this.checked = ""; } else { this.checked = value; } }
这样就OK了。大概唯一区别是 在 vue中通过 ref取到真实 dom。
2. iview中radio取消之路借鉴原生的radio,看来取消也不难嘛,监听radio或者 radio的change事件嘛。然而你会发现,重复点选某一个 radio的时候,iview中的on-change函数跟本木有响应。这是为什么呢? 去 iview 源码中看一看
2.1 iview组件radio源码探究先上代码为敬:
先看下 radio.vue的 template
再看下 change的响应函数
change (event) { // debugger if (this.disabled) { return false; } const checked = event.target.checked; this.currentValue = checked; const value = checked ? this.trueValue : this.falseValue; this.$emit("input", value); if (this.group) { if (this.label !== undefined) { this.parent.change({ value: this.label, checked: this.value }); } } else { this.$emit("on-change", value); this.dispatch("FormItem", "on-form-change", value); } },
一开始怀疑 change事件中对 value做了处理,只有 不一样的时候才
emit,仔细看,change函数中并没有这部分处理。
问题在于 input 这里监听的 change 事件而不是 click事件,所以反复点击同一个 radio的时候没有 响应是正常的。
看到上面是不是就想 我在 radio上绑定一个click 事件就可以了;事实证明是不可以的,想一下就知道了,因为 iview并没有监听click事件自然也没有把click事件 emit到父组件,所以是无法监听click的。
既然 Radio 不支持click,那就想办法在能让元素响应 click 呗
这里的思路是在 RadioGroup的Radio 外包裹一层 div/span,在这个元素上绑定 click 函数,这个元素肯定会响应 click,在响应函数中判断 当前 选中的 value(这个变量通常会维护在data中,暂且用 this.value 表示) 和点击元素包裹的 value 值是否相同,相同则将 this.value 置为空,则可以达到取消的效果。
经过实践,该方法是可行的。 值得注意的是这种情况下需要取消RadioGroup的on-change事件监听,否则radio改变了this.value,会触发RadioGroup的on-change事件,导致无法取消。 还有一个弊端是 需要给 Radio增加一个包裹元素,可能还需要对元素写个样式,不要影响到原Radio 元素布局, 那么还有没有更好的方法呢?
vue中提供了监听原生事件的修饰符,在jsx形式的vue监听原生事件的写法如下:
{label}
所以我们不用增加元素也能监听到click事件,接下里就可以在响应函数中 处理取消/选中的逻辑了。
2.2.3 Radio 怎么响应了2次?嗯, 终于找到一个很好的绑定 click的方法,然而测试的时候,却发现 点击一次却响应了 两次点击函数,百思不得其解吗? 这时候 baidu 或者google给了我们答案: 一个文章说的特别好,解释了两次的原因:
如下文章链接:
触发的事件源分别为input和label;
触发条件很简单:
1、监听的是label和input的上层元素click事件
2、label和input关联(for或者input在label下)
问题原因::
点击label的时候,事件冒泡一次,同时会触发关联的input的click事件,导致事件再次冒泡。
解决办法:
方法有很中拉,
2次响应由 label造成,那我们不要label了,这对于使用iview的情况下是不可能的,因为iview就是使用 label 和 input 做的
响应函数里判断event的 tagName ,如果 tagName 为 label则不做处理,这中方法问题很多,要做 event的浏览器兼容,还有判断label有没有关联 input等,稍显复杂
根据通过事件触发的时间戳来判断,相隔太近则认为是一次点击。
2.3 Radio/RadioGroup 可取消完整方案有了上面的分析,下面我们完整是总结一下 让radio可以取消的步骤:
注意: 我下面写的是 vue的jsx 形式,所以如果是vue形式,请自行修改。
首先: template
{label} {label}
data 和 methods:
data() { return { value: "" } } methods: { handleRadioClick (value) { let now = +new Date(); if (now- this.evTimeStamp < 100) { return; } this.evTimeStamp = now; value = this.value === value ? "" : value; this.update(value); // 可以理解为vuex 通知更新 this.value }, }
限于本身实现还有其他关联部分,这里没有加上 更新 this.value具体代码,但是我相信看到这里应该已经知在使用 ui 库的情况如何 是 radio 可以取消了。
遇到问题欢迎评论提问,不足之处也欢迎指正。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/109184.html
摘要:如图所示还有其它很多项的更新,比如新增属性,可以设置面板展开时默认显示的日期。目前最新版本支持键盘可访问性的组件有。期待你的加入下个版本预告下个版本计划重构组件,以全面支持表单组件的键盘可访问性,敬请期待。 在过去的两个多月里,iView 陆续发布了 2.9.0 和 2.10.0 两个重要版本。这两个版本总共有 255 个 commit,超过 40 项更新。来看一下,iView 具体都...
摘要:相当于可以编辑问卷并提供问卷展示,数据统计的这么一个平台。极大的节省了需要进行表单样式修改的时间,同时,让动态渲染表单成为一件可能且容易的事情。表单动态渲染刚好在项目之前,有过一次动态配置表单的尝试通过字段自动生成表单及验证。 近几天来了个紧急项目,想要做一个内部版本的问卷星。相当于可以编辑问卷并提供问卷展示,数据统计的这么一个平台。整个项目耗时不长,本着积淀和积累的原则,将过程中的...
阅读 1317·2021-10-27 14:14
阅读 3573·2021-09-29 09:34
阅读 2476·2019-08-30 15:44
阅读 1715·2019-08-29 17:13
阅读 2569·2019-08-29 13:07
阅读 866·2019-08-26 18:26
阅读 3341·2019-08-26 13:44
阅读 3209·2019-08-26 13:37