性能:监听所有表单元素的变化,将所有动态属性与新数据同步

Posted

技术标签:

【中文标题】性能:监听所有表单元素的变化,将所有动态属性与新数据同步【英文标题】:Performance: listen to all form elements changes to sync all dynamic attributes with new data 【发布时间】:2019-10-26 05:15:29 【问题描述】:

有一个简单的形式:

<form>
    <input type="checkbox" name="checkbox"> Checkbox
    <input type="email" name="email">
    <button>Submit</button>
</form>

任务是:email字段必须在checkbox被选中时显示,按钮必须在email 填充

所以,我决定这样实现:

    emailbutton 必须具有 data-visible 属性和显示条件 checkboxemail 输入必须听取更改 任何 checkboxemail 更改都应运行检查以根据条件显示|隐藏 data-visible 元素

结果是:

// inputs to listen based on id attr (temp solution)
let inputs = form.querySelectorAll('[id]');

// elements to set/unset visibility
let visibles = form.querySelectorAll('[data-visible]');

// Loop all data-visible elements to toggle display: block|none based on evaluated condition
function sync() 
    for (let v of visibles) 
        if(eval(v.getAttribute('data-visible'))) 
            v.style.display = 'block';
         else 
            v.style.display = 'none';
        
    


// Listen to all inputs changes and sync with new data
for (let input of inputs) 
    input.addEventListener('change', function(e) 
        sync()
    );


sync() // Hide everything that must be hidden on init
<form id="form">
    <input type="checkbox" name="checkbox" id="checkbox"> Checkbox
    <input data-visible="checkbox.checked" type="email" name="email" id="email">
    <button data-visible="email.value">Submit</button>
</form>

或codepen

所以,实际上,这只是一种方法,required/disabled/class 属性也必须根据表单数据的变化进行切换

基本上,我想要实现的 - 是实现简单的类似 MVVM 的方法,但依赖于表单数据而不是 JS 模型

事实证明,在现实生活中的任务中,大约 20 个表单元素可能会被监听以了解它们的所有更改,并且每次更改都会同时评估所有大约 20 个条件以设置/取消设置某些属性

所以,问题是 - 它会导致一些严重的内存/cpu 问题吗?还是一切正常,MVVM 框架几乎一样?我可以去吗?

【问题讨论】:

【参考方案1】:

我之前做过类似的事情,不推荐你目前正在走的路。

原因:

您正在使用 eval - 有一个表达式:“eval is evil”,这在很大程度上是正确的,只有在别无选择时才应使用 eval。 您每次都在循环所有输入,即使它们中的大多数都没有发生任何变化。如您所述,这将导致浏览器出现不必要的负载

解决方案:

尝试将字段放入 html 内的 JSON 编码块中 - 例如:

&lt;input data-visible=" 'checkbox-id': 'prop': 'checked', 'regex': true " ... &gt;

以上内容允许对每个元素进行多项检查(您可以选择对它们进行 AND/OR 组合) 使用 JSON.Parse 解析数据 根据任何给定输入的 ID 构建反向查找对象 - 查找所有依赖输入的对象(如果这是动态的,这部分将是一个小问题) 关于输入更改循环遍历所有依赖项并显示/隐藏它们

这是一个实现你正在寻找的东西的小提琴:js-fiddle

如果这不是您要找的,请告诉我。

【讨论】:

非常感谢您分享您的经验。据我所知 - 只有当我们评估用户提交的一些数据时,浏览器 JS 中的“eval is evil”。顺便说一句,JSON.Parse 方法看起来很有前途,得花点时间玩一下。再多谢你一次,玩完沙盒我会回来的) @MaxCore 在这种情况下 eval 不好的唯一原因是它也会对浏览器造成压力,因为它无法优化你正在做的任何事情。也享受 - 这是一个非常有趣的问题! @MaxCore 还有一件事——您可以通过检查子项在递归部分之前是否已经隐藏来进一步优化子项检查。我会把这部分留给你。 如果你有兴趣,你不会相信,但我遵循了你的方法,找到了避免 evals(和 jsons)的解决方案,使代码更干净,并且只设置那些真正受影响的属性(通过如你所说的反向查找对象)并以“天才”ucssjs.github.io =)结束 @MaxCore 我也创建了类似的东西:github.com/james-wasson/MewJS - BTW 非常酷的项目 MaxCore

以上是关于性能:监听所有表单元素的变化,将所有动态属性与新数据同步的主要内容,如果未能解决你的问题,请参考以下文章

动态数据绑定之监听对象变化

vue-watch监听动态表单的数据

2020-09-13 浅谈: Vue watch监听deep、immediate属性

深度监听(vue中watch的deep)

vue清空表单数据后显示所有列表内容

jquery 动态添加表单元素