前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >浅谈 Checkbox Group 的双向数据绑定

浅谈 Checkbox Group 的双向数据绑定

作者头像
叙帝利
发布于 2021-01-20 11:31:20
发布于 2021-01-20 11:31:20
2.2K00
代码可运行
举报
文章被收录于专栏:前端新视界前端新视界
运行总次数:0
代码可运行

前言

Checkbox 作为表单中最常见的一类元素,使用方式分为单值和多值,其中单值的绑定很简单,就是 truefalse,但是多值(Checkbox Group)的绑定就有一点复杂了。在实际工作中发现很多组件库关于 checkbox-group 的双向绑定一直很别扭,或者说多多少少都有一些瑕疵。

开始本文之前,我们先假定有如下需求:

数据列表和输出值都是对象数组。能否只用一个双向绑定就完成数据的输入输出,而不是在得到绑定的数据之后再使用数组的 filtermap 这些方法去过滤和筛选。

着急的同学可以直接看最终的实现方案:Checkbox Group

现有组件库的实现及缺陷

调研一下市面上的组件库会发现,checkbox-group 并不是一个通用组件,很多组件库并没有这个组件,其中 Ant Design 的 checkbox-group 的设计方案算是比较完善的。简单看一下 Ant Design 是如何设计这个组件的。

1、Ant Design React 版的实现:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<Checkbox.Group options={options} defaultValue={['Pear']} onChange={onChange} />

optionsdefaultValue 的类型定义如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
interface Option {
  label: string;
  value: string;
  disabled?: boolean;
}

defaultValue: string[];

2、Ant Design Angular 版的实现:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<nz-checkbox-group [(ngModel)]="options" (ngModelChange)="log(checkOptions)">
</nz-checkbox-group>

其中双向绑定的数据类型如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
options : Array<{ label: string; value: string; checked?: boolean; disabled?: boolean; }>

问题剖析

不管是 React 版还是 Angular 版,它们的 checkbox-group 都有一个共同点或者说缺陷,那就是 Option 的类型是固定的,假设需要绑定的数据如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
cars = [
    { id: 1, name: 'Ford' },
    { id: 2, name: 'Chevrolet' },
    { id: 3, name: 'Dodge' },
];

那我们必须先将这个 cars 数组 map 成 Option 类型,然后才能绑定渲染。

另外,React 版和 Angular 版的输出值类型也是固定的,其中 React 版输出的是一个关于 value 的字符串数组,Angular 版是则是一个双向绑定 checked 的原数组(个人觉得 Angular 版的绑定比 React 版的要灵活,至少从原数组取值更容易一点)。

还是以上面的 cars 数组为例,如果后端同事告诉我们想要一个完整的对象数组,比如下面这样:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
selectedCars = [
    { id: 2, name: 'Chevrolet' }
];

那我们就必须再遍历一次 selectedCars 数组才能得到需要的数据。也就是说,对于上面展示的这种情况,我们必须要做一些额外的数据处理工作才能完成目标,但是这对于双向绑定功能来说显得有些繁琐。

那到底应该怎样设计 checkbox-group 的双向数据绑定才能更灵活的使用呢?

如何设计 Checkbox Group

在介绍如何设计之前,我们先尝试能否从其它组件设计中找到灵感。

Checkbox 与 Select 的共性

Checkbox Group 和 Multiple Select 除了很细小的交互差异之外,几乎看不出太大的不同。大多数情况下两者可以相互替换,所以很多人总是困惑两种组件到底应该如何选择。这里 有篇文章 专门对比了两种组件的交互场景,甚至使用 A/B test 去分析用户的偏好。

好像有点跑题了,言归正传,基于这种相似性,我们完全可以仿照 Select 的双向绑定机制去设计 Checkbox Group。

Select 的双向数据绑定

下面我们看一下 Material Select 和 Ng-Select 是如何设计双向绑定的,数据就以上面的 cars 为例。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
cars = [
    { id: 1, name: 'Ford' },
    { id: 2, name: 'Chevrolet' },
    { id: 3, name: 'Dodge' },
];

selectedCars = [
    { id: 2, name: 'Chevrolet' }
];

1、Material Select

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<mat-select multiple [(ngModel)]="selectedCars" [compareWith]="compareWith">
  <mat-option *ngFor="let car of cars" [value]="car">{{car.name}}</mat-option>
</mat-select>

2、Ng-Select

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<ng-select [multiple]="true" [items]="cars" bindLabel="name" 
           [(ngModel)]="selectedCars" [compareWith]="compareWith">
</ng-select>

Material Select 和 Ng-Select 在设计上稍微有一些差别。Material Select 完全基于模板渲染,Ng-Select 则是属性配置优先,两者的数据回显都是通过 compareWith。它们的双向绑定都非常简单,我们没有写任何多余的代码就按规定的格式完成了数据的输入输出,这种设计思路同样可以用在 Checkbox Group 上面。

Checkbox Group 的设计实现

看完上面关于 Select 的两个例子,或许已经不需要我再多说什么了,最终设计的 Checkbox Group 代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<mtx-checkbox-group [items]="cars"
                    bindLabel="name"
                    [(ngModel)]="selectedCars"
                    [compareWith]="compareWith">
</mtx-checkbox-group>

线上 DEMO

上面的代码没有任何多余的过滤筛选就完成了开篇提出的需求,对数据的操作全都隐藏在双向绑定的内部。

如果后端同事希望 selectedCars 是一个 id 数组,比如 selectedCars=[2],那么只需要设置一下 bindValue 就可以了。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<mtx-checkbox-group [items]="cars"
                    bindLabel="name"
                    bindValue="id"
                    [(ngModel)]="selectedCars">
</mtx-checkbox-group>

非对象数据的回显就不用 compareWith 了。

总结

这篇文章拖沓了非常久,一方面是自己工作很忙,另一方面做开源项目占据了大部分时间。

从最开始考虑 Checkbox Group 的重构方案到最终实现差不多用了半年多的时间,不过实际开发时间大概也就一周吧。相比之前借鉴 Ant Design 的方案来说,现在的方案更加灵活,有效减少了数据操作的代码,不过仍然有很大的优化和提升空间。

如果大家发现本文有不当之处,欢迎交流指正!

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021-01-13 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

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

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Angular—都2019了,你还对双向数据绑定念念不忘
双向数据绑定是AngularJs的一大卖点,当初问世时开发人员无不惊讶,“Wow, it's so crazy"。但是用过AngularJs的,都对它又爱又恨,爱的是它确实给开发提供了一定的便利,恨的是基于‘脏检查’的变更检测机制会随着watch的数据量的增加拖慢应用运行的速度。于是乎,goolge在2016年推出了angular彻底改变了检测机制,这次并没有大力吆喝双向数据绑定,但仍会有人习惯的问一句,“有没双向数据绑定?”。如果你只是随口一问,我会告诉你,有。如果你仍然“死缠烂打”的追问倒底有没有,我会告诉你,**没有**。
拓荒者IT
2021/03/05
4.4K0
Angular核心概念:数据绑定
测试:在NG表达式可以执行哪些代码?(Y表示可以,N表示不可以) 算术运算:Y。比较运算:Y。逻辑运算:Y。三目运算:Y。 调用函数:Y。创建对象:N。JSON序列化:N。 NG表达式禁止出现new关键字。NG表达式中JSON是undefined。 结果展示:
用户9857551
2022/06/28
3.7K0
Angular核心概念:数据绑定
Angular 中的数据绑定
从组件(数据)到视图:绑定组件数据到视图上,我们使用插值 Interpolation 和属性 Property 绑定。
Jimmy_is_jimmy
2024/03/09
4210
Angular Material 的设计之美
Angular Material 作为 Angular 的官方组件库,无论是设计交互还是易用性都有着极高的质量。正如官方所说其目的就是构建基于 Angular 和 TypeScript 的高质量组件库。
叙帝利
2019/09/29
5.2K0
Angular Material 的设计之美
Vue3 | 双向绑定 及其 多种指令、修饰符的实践
如下代码,input的内容 与 testString字段的数据 双向绑定, 文本显示了 testString字段的数据的内容, 此时, 手动改动 testString字段的值, input的内容会跟着改变; 手动输入改变input的内容, testString字段的值也会跟着改变(体现在{{testString}}这里); 所谓 双向绑定:
凌川江雪
2021/03/08
2.5K0
第217天:深入理解Angular双向数据绑定的原理
双向绑定是新的前端框架中频繁出现的一个新词汇,也是mvvm的核心原理。angularjs五条核心信念中的数据驱动,便是由双向绑定进行完成。
半指温柔乐
2018/09/11
3.8K0
第217天:深入理解Angular双向数据绑定的原理
前端MVC学习总结(一)——MVC概要与angular概要、模板与数据绑定
张果
2018/01/04
15.6K0
前端MVC学习总结(一)——MVC概要与angular概要、模板与数据绑定
Angular学习资料大全和常用语法汇总(让后端程序员轻松上手)
  首先为什么要写这样的一篇文章呢?主要是因为前段时间写过一些关于Angualr的相关实战文章,有些爱学习的小伙伴对这方面比较感兴趣,但是又不知道该怎么入手(因为认识我的大多数小伙伴都是后端的同学),所以今天准备出一篇Angular学习资料汇总和日常开发中使用比较频繁的语法总结。让更多的后端程序员更好的了解学习Angualr,拓展自己的技术栈。
追逐时光者
2021/01/29
5.5K0
浅谈 Angular 项目实战
我不是 Angular 的布道者,但如今自称 Angular 派,使用 Angular 做项目让我有一种兴奋感。目前的三大主流前端框架都研究过,博客中也有三者的相关教程,最早接触的是 React,但是并没有实际的项目经验,只做过一些 Demo 。使用 Vue 做过一个比较复杂的移动端大数据项目,技术栈采用 Framework7 + Vue + Vuex,整体效果还是满意的。
叙帝利
2018/07/31
4.8K0
vue双向数据绑定原理
目前几种主流的mvc(vm)框架都实现了单向数据绑定,而我所理解的双向数据绑定无非就是在单向绑定的基础上给可输入元素(input、textare等)添加了change(input)事件,来动态修改model和 view,并没有多高深。所以无需太过介怀是实现的单向或双向绑定。 实现数据绑定的做法有大致如下几种:
念念不忘
2019/03/29
2.2K0
vue双向数据绑定原理
Angular 2 表单(下)
接下来我们使用 ngModel 进行双向数据绑定,通过监听 DOM 事件,来实现更新组件的属性。
陈不成i
2021/07/26
1.8K0
Ng-Matero V9 正式发布!
距离 Ng-Matero 第一版发布已经过去了半年多,该项目获得了越来越多的关注及喜爱,甚至得到了外国友人的赞助。借此项目也认识了很多对 Angular 和 Material 感兴趣的朋友,如今对项目的维护已经不单单是兴趣,更多的是一种责任。
叙帝利
2020/03/21
1.3K0
Ng-Matero V9 正式发布!
Angular 从入坑到挖坑 - 表单控件概览
angular 入坑记录的笔记第三篇,介绍 angular 中表单控件的相关概念,了解如何在 angular 中创建一个表单,以及如何针对表单控件进行数据校验。
程序员宇说
2020/03/19
19.4K0
(8/30)Blazor系列:CSS样式修改和数据绑定详述
现在每次启动项目,预设路径都会是/,但我们目前没有Component套用这个路由,要自己切换到Post实在有些麻烦,另外Menu的图案也跟名称不符,我们来调整一下。
沙漠尽头的狼
2021/12/16
2.8K0
(8/30)Blazor系列:CSS样式修改和数据绑定详述
VUE中的模板语法以及过滤器和双向数据绑定
Vue.js 使用了基于 HTML 的模板语法,允许开发者声明式地将 DOM 绑定至底层 Vue 实例的数据。所有 Vue.js 的模板都是合法的 HTML ,所以能被遵循规范的浏览器和 HTML 解析器解析。vue将模板编译成虚拟dom, 结合响应系统,Vue 能够智能地计算出最少需要重新渲染多少组件,并把 DOM 操作次数减到最少。
用户10196776
2022/11/22
1.8K0
Angular 6.x 表单快速入门
本文主要介绍 Template Driven Forms (模板驱动式表单)的基础知识,相关的知识点会以问答的形式进行介绍。
阿宝哥
2019/11/05
4.9K0
从零开始学VUE之模板语法(表单数据绑定)
v-model <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="../../../js/vue.js"></script> </head> <body> <div id="app"> <div> <!--数据双向绑定修改 输入框的值 可以修改name的值--> <div> <s
彼岸舞
2021/06/07
9010
Ng-Matero v15 正式发布
前言 Angular 按照既定的发版计划在 11 月中旬发布了 v15 版本。推迟了一个月(几乎每个版本都是这个节奏😳),Ng-Matero 也终于更新到了 v15。其实 Ng-Matero 本身的更新非常简单,但是同步维护的 Material Extensions 这个库要先于 Ng-Matero 发布,所以大部分精力都耗费在组件库上面了。 我已经很久没有写关于 Ng-Matero 的发版文章了。上次介绍发版还是 v10 版本,竟然已经是两年前的事情了。在这两年的开源生涯中,主要精力都在 Materi
叙帝利
2022/12/31
5.6K0
Ng-Matero v15 正式发布
从单向到双向数据绑定
用户最满意的,无非就是界面的操作能实事反应到数据。而实现这种的可以有双向数据绑定、单向数据流的形式。双向数据绑定是,ui行为改变model层的数据,model层的数据变了也能反映到ui上面。比如点击按钮,数字data+1,如果我们自己在控制台再给data+1,那么v层也能马上看见这个变化。而单向数据流就不同了,我们只有ui行为改变,data就改变并马上反馈到v层,而我们自己在控制台改变data这个值,v层居然不变(model是已经变了并没有反应),只能等到下一次ui行为改变,带上这个data结果一起处理。仅仅在V层的单向数据,真的能满足用户需求?数据很庞大的时候,双绑性能如何?其实,每一种都有每一种的适用场景,还是那句话,脱离实际场景谈性能,就是扯淡
lhyt
2022/09/21
3.7K0
基于 Angular Material 的 Data Grid 设计实现
距离 Extensions Data Grid 重构已经过去了两个多月,因工作忙碌而迟迟没有介绍 Extensions Data Grid 的细节。这几天又重构了一下官网示例,目前的 API 文档放在了 gitbook 上,暂时还没有和官网整合,国内访问会比较慢。本文会介绍 Data Grid 的使用方法及比较好的一些功能实现。说点题外话,开发一款插件最大的难度不在于功能的实现,而在于如何去设计插件。
叙帝利
2020/06/29
5.2K0
基于 Angular Material 的 Data Grid 设计实现
相关推荐
Angular—都2019了,你还对双向数据绑定念念不忘
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验