是否有可能在JS中有一个事件,当某个变量的值发生变化时触发?JQuery被接受。
当前回答
请记住,最初的问题是针对变量的,而不是针对对象的;)
除了上面所有的答案,我创建了一个名为thewatch .js的小库, 在javascript中使用相同的方法来捕捉和回调普通全局变量的变化。
与JQUERY变量兼容,不需要使用object,如果需要,可以直接传递几个变量的ARRAY。
如果有帮助的话……: https://bitbucket.org/esabora/forthewatch基本上你只需要调用这个函数: watchIt(“theVariableToWatch”、“varChangedFunctionCallback”);
如果不相关,先说句抱歉。
其他回答
最近我发现自己也有同样的问题。想要监听变量的变化并在变量变化时做一些事情。
有人提出了一个使用setter设置值的简单解决方案。
声明一个简单的对象来保存变量的值:
var variableObject = {
value: false,
set: function (value) {
this.value = value;
this.getOnChange();
}
}
对象包含一个set方法,通过该方法可以更改值。但是它也调用了一个getOnChange()方法。将定义它。
variableObject.getOnChange = function() {
if(this.value) {
// do some stuff
}
}
现在,每当我做variableObject.set(true)时,getOnChange方法就会触发,如果值被设置为所需的值(在我的例子中:true), if块也会执行。
这是我发现的最简单的方法。
我搜索了JavaScript双向数据绑定库,发现了这个库。
我没有成功地使它在DOM到变量的方向上工作,但在变量到DOM的方向上它是工作的,这就是我们在这里需要的。
我稍微重写了一下,因为原始代码(对我来说)很难阅读。它使用 object。defineproperty,这是Eliot b给出的第二多赞的答案,至少有部分错误。
<!DOCTYPE html>
<html>
<head>
<title>TODO supply a title</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script>
const dataBind = (function () {
const getElementValue = function (selector) {
let element = document.querySelectorAll(selector)[0];
return 'value' in element ? element.value : element.innerHTML;
};
const setElementValue = function (selector, newValue) {
let elementArray = document.querySelectorAll(selector);
for (let i = 0; i < elementArray.length; i++) {
let element = elementArray[i];
if ('value' in element) {
element.value = newValue;
if (element.tagName.toLowerCase() === 'select'){
let options = element.querySelectorAll('option');
for (let option in options){
if (option.value === newValue){
option.selected = true;
break;
}
}
}
} else {
element.innerHTML = newValue;
}
}
};
const bindModelToView = function (selector, object, property, enumerable) {
Object.defineProperty(object, property, {
get: function () {
return getElementValue(selector);
},
set: function (newValue) {
setElementValue(selector, newValue);
},
configurable: true,
enumerable: (enumerable)
});
};
return {
bindModelToView
};
})();
</script>
</head>
<body>
<div style="padding: 20%;">
<input type="text" id="text" style="width: 40px;"/>
</div>
<script>
let x = {a: 1, b: 2};
dataBind.bindModelToView('#text', x, 'a'); //data to dom
setInterval(function () {
x.a++;
}, 1000);
</script>
</body>
</html>
JSFiddle.
JSFiddle原始代码。
在提供的示例中,对象x的属性由setInterval更新,文本输入的值也会自动更新。如果这还不够,并且事件是你想要的,你可以在上面的输入中添加onchange监听器。如果需要,输入也可以被隐藏。
这是不可能的。
但是,这可以使用CustomEvent: https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent来完成
下面的方法接受一个变量名数组作为输入,并为每个变量添加事件侦听器,并在变量值发生任何更改时触发事件。
该方法使用轮询来检测值的变化。您可以以毫秒为单位增加timeout的值。
function watchVariable(varsToWatch) {
let timeout = 1000;
let localCopyForVars = {};
let pollForChange = function () {
for (let varToWatch of varsToWatch) {
if (localCopyForVars[varToWatch] !== window[varToWatch]) {
let event = new CustomEvent('onVar_' + varToWatch + 'Change', {
detail: {
name: varToWatch,
oldValue: localCopyForVars[varToWatch],
newValue: window[varToWatch]
}
});
document.dispatchEvent(event);
localCopyForVars[varToWatch] = window[varToWatch];
}
}
setTimeout(pollForChange, timeout);
};
let respondToNewValue = function (varData) {
console.log("The value of the variable " + varData.name + " has been Changed from " + varData.oldValue + " to " + varData.newValue + "!!!");
}
for (let varToWatch of varsToWatch) {
localCopyForVars[varToWatch] = window[varToWatch];
document.addEventListener('onVar_' + varToWatch + 'Change', function (e) {
respondToNewValue(e.detail);
});
}
setTimeout(pollForChange, timeout);
}
通过调用方法:
watchVariables(['username', 'userid']);
它将检测变量username和userid的更改。
如果你正在使用jQuery {UI}(每个人都应该使用:-)),你可以使用.change()和一个隐藏的<input/>元素。
不是直接的:你需要一个“addListener/removeListener”接口的一对getter/setter…或者一个NPAPI插件(但这完全是另一个故事)。