性能:侦听所有表单元素更改以将所有动态属性与新数据同步
Performance: listen to all form elements changes to sync all dynamic attributes with new data
有一个简单的形式:
<form>
<input type="checkbox" name="checkbox"> Checkbox
<input type="email" name="email">
<button>Submit</button>
</form>
任务是:email 字段只有在选中 checkbox 且 button[=54= 时才必须显示] 仅当 email filled
时才必须显示所以,我决定这样实现:
- email 和 button 必须有
data-visible
属性 with display conditions - checkbox 和 email 输入必须收听更改
- 任何 checkbox 和 email 更改都应 运行 检查以根据条件显示|隐藏
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 个条件以 set/unset 某些属性
所以,问题是 - 它会导致一些严重的 memory/cpu 问题吗?或者一切都很好,MVVM 框架做的几乎一样?我可以一起去吗?
我以前也做过类似的事情,不推荐你现在走的路。
原因:
- 您正在使用 eval -- 有一个表达式:"eval is evil" 这大部分是正确的,您应该只在没有其他选择的情况下使用 eval。
- 您每次都在遍历所有输入,即使其中大部分没有任何变化。如您所述,这将对浏览器造成不必要的负载
解决方法:
- 尝试将字段放入 HTML 内的 JSON 编码块中 - 如:
<input data-visible="{ 'checkbox-id': { 'prop': 'checked', 'regex': true } }" ... >
- 以上允许对每个元素进行多次检查(您可以选择 AND/OR 它们一起)
- 使用JSON.Parse 解析数据
- 根据任何给定输入的 ID 构建反向查找对象——查找所有依赖于输入的对象(如果这是动态的,这部分将是一个小问题)
- 在输入更改时递归地循环遍历所有依赖项并show/hide它们
这是一个 fiddle 实现的类似于您正在寻找的东西:js-fiddle
如果这不是您要找的,请告诉我。