KnockOut 获取绑定数据的值并进行修改

文章讲述了如何在一个列表模型中实现全选/全不选功能,遇到的难点是基于样式而非传统checkbox的选中逻辑。作者通过JavaScript和jQuery解决点击事件触发样式变化,同时处理数据同步问题,最终实现预期功能并解决了数据一致性问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        业务需求: 为列表模型增加一个全选/全不选的功能,但功能奇葩的地方在于,列表的input实现并不是通过 type=checkbox 中checked的值 来做勾选判断的 而是添加了一个label用通过样式变化 来控制显示不同的伪元素::before(选中框) ::after(勾选图标√)来实现的...这导致我没办法通过jQuery来获取选中状态,所以只能另想他法

1.构思方案

        先从最简单的场景开始,在list初始化后,直接点击全选,效果应该是选中所有list,由于前面提到的神奇问题,所以单纯的通过遍历list获取 prop("checked") 是没办法解决了,所以我决定通过触发点击事件的方法来使css变化,达到展示选中样式的效果.

        首先,我自定义了一个属性ischecked,用于判断全选按钮的状态,以及默认值.

<input type='checkbox' class='allIpt' ischecked='false'/>

        然后为其绑定一个点击事件,这样我们得到了一个可以控制状态的按钮(别问为什么要加个属性,问就是在一坨上,宁添不改)

$(".allIpt").on("click", function (ev) {
    if ($(".allIpt").attr("ischecked") == 'false') {
        $(".allIpt").attr("ischecked", 'true');
    }
    else if ($(".allIpt").attr("ischecked") == 'true') {
        $(".allIpt").attr("ischecked", 'false');
    }
    console.log($(".allIpt").attr("ischecked"))
});

        接下来的问题是,如何获取到整个list的数据,以及如何修改它们的状态,因为项目是单页面项目 大部分的数据都通过 挂载在window的属性进行传递 且 使用knockout实现数据绑定,所以我自然想到用请求出来的数据作为全选后的值,反选则置空

        

let SelectedData = null;
//全选
SelectedData = window.FormListID.allList();
//全不选
SelectedData = []

  2.完善逻辑

        尝试了一下确实可以获取到数据,且反复切换也没有问题,于是决定开始完善功能,目前虽然全选按钮可以获取到数据了,但list的样式还没有切换,这里开始处理样式问题.

        要解决的问题有

  1. 每项被选中后的背景色
  2. label伪类切换实现的勾选样式
  3. 在有个别项被选中/未选中时,点击全选/全不选时 判断是否需要跳过此项

处理后关键代码

$(".allIpt").on("click", function (ev) {
    ev.stopPropagation();
    if ($(".allIpt").attr("ischecked") == 'false') {
        SelectedData = window.FormListID.datasource();
        $("#datalist tbody tr").each(function () {
            if (!$(this).hasClass("selected")) {
                $(this).find("input").click();//通过触发点击事件来切换css样式
                $(this).addClass("selected");
            }
        });
        $(".allIpt").attr("ischecked", 'true');
    }
    else if ($(".allIpt").attr("ischecked") == 'true') {
        SelectedData = [];
        $("#datalist tbody tr").each(function () {
            if ($(this).hasClass("selected")) {
                $(this).find("input").click();
                $(this).removeClass("selected");
            }
        });
        $(.allIpt").attr("ischecked", 'false');
    }
});

3.处理问题

        测试发现,基本上可以实现预期功能,但在 先全选-取消某项选择-全不选-再全选 情况下会出现全选后,样式上正常,但数据无法获取全部的问题.打印发现全选后,取消单项的选择后 ,列表绑定的数据window.FormListID.datasource()居然发生了变化,但我有需要使用它的值做操作,如何解决呢.

//原代码
SelectedData = window.FormListID.datasource();

//解决方案
SelectedData = window.FormListID.datasource().slice();

        使用slice()方法可以创建一个新的数组,其中包含原始数组的副本.这是因为slice()方法在创建副本时会复制原始数组的元素,并将它们放入新的数组中.

       由于这里只涉及到数据筛选,并不会去改变数组中项的值,所以直接使用了slice进行浅拷贝.实际上它们指向还是同一个对象.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值