效果:聆听所有表单元素的更改,以将所有动态属性与新数据同步

时间:2019-06-11 18:12:02

标签: javascript mvvm javascript-framework

有一个简单的表格:

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

任务是:仅当选中复选框时,才显示电子邮件字段;仅当电子邮件< / strong>已填充

所以,我决定像这样实现它:

  1. 电子邮件按钮必须具有显示条件的data-visible属性
  2. 复选框电子邮件输入必须听取更改
  3. 任何复选框电子邮件更改都应运行检查以根据条件显示|隐藏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

因此,实际上,这仅仅是一种方法,还必须根据表单数据的更改来切换必需/禁用/类属性

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

在现实生活中,事实证明,所有形式元素中的〜20个可能会被监听,并且每次更改都会一次评估所有〜20个条件,以设置/取消某些属性

因此,值得关注的是-它会引起一些严重的内存/ CPU问题吗?还是一切正常,而MVVM-frameworks做得差不多?我可以去吗?

1 个答案:

答案 0 :(得分:1)

我之前做过类似的事情,不推荐您当前所走的路径。

原因:

  • 您正在使用eval -有一个表达式:“ eval是邪恶的”,这基本上是正确的,并且只有在没有其他选择的情况下才应使用eval。
  • 您每次都遍历所有输入,即使大多数输入没有变化。如前所述,这将对浏览器造成不必要的负担

有关解决方案:

  • 尝试将字段放入HTML内的JSON编码的块中,例如:

<input data-visible="{ 'checkbox-id': { 'prop': 'checked', 'regex': true } }" ... >

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

在这里摆弄着您想要的东西js-fiddle

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