订阅并处理对多个输入的更改
Subscribe to and process change to multiple inputs
我想向输入元素添加一个事件侦听器,其中元素 ID 已存储在列表中,然后获取它们的乘积。例如:
a = ['id1', 'id2', 'id3']
我想做这样的事情:
input element id1 = 0.5
input element id2 = 0.6
input element id3 = 1.0
return 0.5*0.6*1
并且我希望它随着用户更改输入框中的值而更新。
所以我从类似的东西开始:
function calcProduct(values){
var product = 1;
for(i=0; values.length; i++){
product = product*values[i];
}
return product
}
id_list = ['id1', 'id2', 'id3']
function calcProduct(id_list){
for(i=0; id_list.length; i++){
//how do I get the values as they change so I can feed it to calcProduct?
document.getElementById(id_list[i]).addEventListener("onchange", calcProduct(values) )
}
}
使用事件侦听器和 reduce()
您可以积累最终产品。注意:在事件侦听器中,省略 'on',因此使用 change
而不是 onchange
。为了方便起见,我使用了一个 className 作为将要计算的输入
window.addEventListener('load', () => {
document.querySelectorAll('.to-calc').forEach(el => el.addEventListener('change', calcProduct))
calcProduct()
})
function calcProduct(e) {
let output = [...document.querySelectorAll('.to-calc')].reduce((b, a) => b * +a.value, 1)
console.log(output.toFixed(2))
return output.toFixed(2)
}
<input class='to-calc' type='number' value='0.5'> <input class='to-calc' type='number' value='0.6'> <input class='to-calc' type='number' value='0.1'>
我会为此结合事件委托和反应式编程。
将事件侦听器附加到父节点并在事件传入时对其进行过滤:
- 当调度
input
事件时,父 <div>
会捕获它。
filter
运算符确保我们使用正确的事件。
scan
运算符将新值写入地图。
map
运算符将映射中的值相乘。
- 最终订阅者收到并展示了产品。
这样我们就可以处理多组数字。
(请注意地图如何对应 DOM 中的 ID 和值。)
const mult = nums =>
fromEvent(document.querySelector('div'), 'input') //1
.pipe( filter(e => e.target.id in nums) //2
, scan((acc, {target: {id, value}}) => (acc[id]=value, acc), nums) //3
, map(ns => Object.values(ns).reduce((p, n) => p * n, 1))); //4
mult({n1: 1, n2: 1, n3: 1}).subscribe(display('#p1')); //5
mult({n4: 1, n5: 1, n6: 1}).subscribe(display('#p2')); //5
mult({n7: 1, n8: 1, n9: 1}).subscribe(display('#p3')); //5
input{width:30px}
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/7.2.0/rxjs.umd.min.js" integrity="sha512-MlqMFvHwgWJ1vfts5fdC2WzxDaIXWfYuAd9Tb2lobtF61Gk+HIRDrbtxgasBSM9lZgOK9ilwK9LqFIYEV+k0IA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script>
const {fromEvent} = rxjs;
const {filter, map, scan} = rxjs.operators;
const display = sel => val => document.querySelector(sel).textContent = val;
</script>
<div>
<input id="n1" type="number" value="1"/> ×
<input id="n2" type="number" value="1"/> ×
<input id="n3" type="number" value="1"/> = <span id="p1">1</span>
<hr/>
<input id="n4" type="number" value="1"/> ×
<input id="n5" type="number" value="1"/> ×
<input id="n6" type="number" value="1"/> = <span id="p2">1</span>
<hr/>
<input id="n7" type="number" value="1"/> ×
<input id="n8" type="number" value="1"/> ×
<input id="n9" type="number" value="1"/> = <span id="p3">1</span>
</div>
我想向输入元素添加一个事件侦听器,其中元素 ID 已存储在列表中,然后获取它们的乘积。例如:
a = ['id1', 'id2', 'id3']
我想做这样的事情:
input element id1 = 0.5
input element id2 = 0.6
input element id3 = 1.0
return 0.5*0.6*1
并且我希望它随着用户更改输入框中的值而更新。
所以我从类似的东西开始:
function calcProduct(values){
var product = 1;
for(i=0; values.length; i++){
product = product*values[i];
}
return product
}
id_list = ['id1', 'id2', 'id3']
function calcProduct(id_list){
for(i=0; id_list.length; i++){
//how do I get the values as they change so I can feed it to calcProduct?
document.getElementById(id_list[i]).addEventListener("onchange", calcProduct(values) )
}
}
使用事件侦听器和 reduce()
您可以积累最终产品。注意:在事件侦听器中,省略 'on',因此使用 change
而不是 onchange
。为了方便起见,我使用了一个 className 作为将要计算的输入
window.addEventListener('load', () => {
document.querySelectorAll('.to-calc').forEach(el => el.addEventListener('change', calcProduct))
calcProduct()
})
function calcProduct(e) {
let output = [...document.querySelectorAll('.to-calc')].reduce((b, a) => b * +a.value, 1)
console.log(output.toFixed(2))
return output.toFixed(2)
}
<input class='to-calc' type='number' value='0.5'> <input class='to-calc' type='number' value='0.6'> <input class='to-calc' type='number' value='0.1'>
我会为此结合事件委托和反应式编程。
将事件侦听器附加到父节点并在事件传入时对其进行过滤:
- 当调度
input
事件时,父<div>
会捕获它。 filter
运算符确保我们使用正确的事件。scan
运算符将新值写入地图。map
运算符将映射中的值相乘。- 最终订阅者收到并展示了产品。
这样我们就可以处理多组数字。
(请注意地图如何对应 DOM 中的 ID 和值。)
const mult = nums =>
fromEvent(document.querySelector('div'), 'input') //1
.pipe( filter(e => e.target.id in nums) //2
, scan((acc, {target: {id, value}}) => (acc[id]=value, acc), nums) //3
, map(ns => Object.values(ns).reduce((p, n) => p * n, 1))); //4
mult({n1: 1, n2: 1, n3: 1}).subscribe(display('#p1')); //5
mult({n4: 1, n5: 1, n6: 1}).subscribe(display('#p2')); //5
mult({n7: 1, n8: 1, n9: 1}).subscribe(display('#p3')); //5
input{width:30px}
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/7.2.0/rxjs.umd.min.js" integrity="sha512-MlqMFvHwgWJ1vfts5fdC2WzxDaIXWfYuAd9Tb2lobtF61Gk+HIRDrbtxgasBSM9lZgOK9ilwK9LqFIYEV+k0IA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script>
const {fromEvent} = rxjs;
const {filter, map, scan} = rxjs.operators;
const display = sel => val => document.querySelector(sel).textContent = val;
</script>
<div>
<input id="n1" type="number" value="1"/> ×
<input id="n2" type="number" value="1"/> ×
<input id="n3" type="number" value="1"/> = <span id="p1">1</span>
<hr/>
<input id="n4" type="number" value="1"/> ×
<input id="n5" type="number" value="1"/> ×
<input id="n6" type="number" value="1"/> = <span id="p2">1</span>
<hr/>
<input id="n7" type="number" value="1"/> ×
<input id="n8" type="number" value="1"/> ×
<input id="n9" type="number" value="1"/> = <span id="p3">1</span>
</div>