เป็นไปได้ไหมที่จะมีเหตุการณ์ใน JS ที่เริ่มทำงานเมื่อค่าของตัวแปรเปลี่ยนแปลงไป? ได้รับการยอมรับ JQuery
variable
property
ฉันสงสัยว่าเราสามารถฟังlocal variable
การเปลี่ยนแปลงได้หรือไม่
เป็นไปได้ไหมที่จะมีเหตุการณ์ใน JS ที่เริ่มทำงานเมื่อค่าของตัวแปรเปลี่ยนแปลงไป? ได้รับการยอมรับ JQuery
variable
property
ฉันสงสัยว่าเราสามารถฟังlocal variable
การเปลี่ยนแปลงได้หรือไม่
คำตอบ:
ใช่ตอนนี้เป็นไปได้อย่างสมบูรณ์!
ฉันรู้ว่านี่เป็นเธรดเก่า แต่ตอนนี้เอฟเฟกต์นี้เป็นไปได้โดยใช้ accessors (getters และ setters): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Working_with_Objects#Defining_getters_and_setters
คุณสามารถกำหนดวัตถุเช่นนี้ซึ่งaInternal
แสดงถึงเขตข้อมูลa
:
x = {
aInternal: 10,
aListener: function(val) {},
set a(val) {
this.aInternal = val;
this.aListener(val);
},
get a() {
return this.aInternal;
},
registerListener: function(listener) {
this.aListener = listener;
}
}
จากนั้นคุณสามารถลงทะเบียนผู้ฟังโดยใช้สิ่งต่อไปนี้:
x.registerListener(function(val) {
alert("Someone changed the value of x.a to " + val);
});
ดังนั้นเมื่อใดก็ตามที่มีการเปลี่ยนแปลงค่าของx.a
ฟังก์ชั่นฟังจะถูกไล่ออก การรันบรรทัดต่อไปนี้จะทำให้ป๊อปอัปแจ้งเตือน:
x.a = 42;
ดูตัวอย่างได้ที่นี่: https://jsfiddle.net/5o1wf1bn/1/
คุณสามารถใช้อาร์เรย์ของผู้ฟังแทนการฟังสล็อตเดียว แต่ฉันต้องการให้ตัวอย่างที่ง่ายที่สุดที่เป็นไปได้
this.aListener(val)
, val
คุณจะต้องห่วงผ่านฟังก์ชั่นฟังทั้งหมดและเรียกแต่ละคนผ่าน โดยปกติแล้ววิธีการที่เรียกว่าแทนaddListener
registerListener
คำตอบส่วนใหญ่สำหรับคำถามนี้อาจล้าสมัยไม่มีประสิทธิภาพหรือต้องมีห้องสมุดขนาดใหญ่ป่อง:
วันนี้คุณสามารถใช้วัตถุพร็อกซีเพื่อตรวจสอบการเปลี่ยนแปลง (และสกัดกั้น) ที่เกิดขึ้นกับวัตถุ มันมีวัตถุประสงค์เพื่อสร้างสิ่งที่ OP พยายามทำ นี่คือตัวอย่างพื้นฐาน:
var targetObj = {};
var targetProxy = new Proxy(targetObj, {
set: function (target, key, value) {
console.log(`${key} set to ${value}`);
target[key] = value;
return true;
}
});
targetProxy.hello_world = "test"; // console: 'hello_world set to test'
ข้อเสียเดียวของProxy
วัตถุคือ:
Proxy
วัตถุไม่สามารถใช้ได้ในเบราว์เซอร์รุ่นเก่า (เช่น IE11) และpolyfillไม่สามารถทำซ้ำได้อย่างเต็มที่Proxy
การทำงานDate
) - Proxy
วัตถุนั้นจับคู่กับวัตถุหรืออาร์เรย์ธรรมดาได้ดีที่สุดหากคุณต้องการสังเกตการเปลี่ยนแปลงที่เกิดขึ้นกับวัตถุที่ซ้อนกันคุณจะต้องใช้ไลบรา เฉพาะเช่นObservable Slim (ซึ่งฉันได้เผยแพร่)ซึ่งทำงานเช่นนี้:
var test = {testing:{}};
var p = ObservableSlim.create(test, true, function(changes) {
console.log(JSON.stringify(changes));
});
p.testing.blah = 42; // console: [{"type":"add","target":{"blah":42},"property":"blah","newValue":42,"currentPath":"testing.blah",jsonPointer:"/testing/blah","proxy":{"blah":42}}]
target.hello_world = "test"
)
you don't actually watch changes on the target object but only on proxy object
- นั่นไม่ค่อยแม่นยำ Proxy
วัตถุไม่ได้แก้ไข - มันไม่ได้มันเป็นสำเนาตัวเองของเป้าหมาย you just want to know when a property change on the target object
- คุณสามารถทำสิ่งนั้นได้ด้วย a Proxy
ซึ่งเป็นหนึ่งในกรณีการใช้งานหลักสำหรับพร็อกซี่
target
คุณต้องทำผ่านพร็อกซี อย่างไรก็ตามproxy.hello_world = "test"
ไม่ได้หมายความว่าคุณกำลังแก้ไขพร็อกซีพร็อกซียังคงไม่เปลี่ยนแปลงtarget
รับการแก้ไข (หากตั้งค่าตัวจัดการชุดของคุณให้ทำ) target.hello_world = "test"
มันเสียงเหมือนจุดของคุณคือการที่คุณไม่สามารถสังเกตได้โดยตรง นั่นเป็นความจริง. การกำหนดตัวแปรธรรมดาไม่ปล่อยเหตุการณ์ใด ๆ นั่นเป็นเหตุผลที่เราต้องใช้เครื่องมือเช่นที่อธิบายไว้ในคำตอบของคำถามนี้
It sounds like your point is that you cannot directly observe target.hello_world = "test". That is true.
นั่นคือประเด็นของฉัน ในกรณีของฉันฉันมีวัตถุที่สร้างขึ้นที่อื่นและได้รับการปรับปรุงโดยรหัสอื่น ... พร็อกซีในกรณีนี้ไม่มีประโยชน์เนื่องจากการเปลี่ยนแปลงจะเกิดขึ้นกับเป้าหมาย
เลขที่
แต่ถ้าสำคัญจริง ๆ คุณมี 2 ตัวเลือก (ทดสอบครั้งแรกไม่ใช่วินาที):
ก่อนอื่นใช้ setters และ getters ดังนี้:
var myobj = {a : 1};
function create_gets_sets(obj) { // make this a framework/global function
var proxy = {}
for ( var i in obj ) {
if (obj.hasOwnProperty(i)) {
var k = i;
proxy["set_"+i] = function (val) { this[k] = val; };
proxy["get_"+i] = function () { return this[k]; };
}
}
for (var i in proxy) {
if (proxy.hasOwnProperty(i)) {
obj[i] = proxy[i];
}
}
}
create_gets_sets(myobj);
จากนั้นคุณสามารถทำสิ่งที่ชอบ:
function listen_to(obj, prop, handler) {
var current_setter = obj["set_" + prop];
var old_val = obj["get_" + prop]();
obj["set_" + prop] = function(val) { current_setter.apply(obj, [old_val, val]); handler(val));
}
จากนั้นตั้งค่าผู้ฟังที่ชอบ:
listen_to(myobj, "a", function(oldval, newval) {
alert("old : " + oldval + " new : " + newval);
}
ประการที่สองฉันลืมฉันจะส่งในขณะที่ฉันคิด :)
แก้ไข: โอ้ฉันจำได้ :) คุณสามารถใส่ค่าดู:
ให้ myobj ข้างต้นด้วย 'a' กับมัน:
function watch(obj, prop, handler) { // make this a framework/global function
var currval = obj[prop];
function callback() {
if (obj[prop] != currval) {
var temp = currval;
currval = obj[prop];
handler(temp, currval);
}
}
return callback;
}
var myhandler = function (oldval, newval) {
//do something
};
var intervalH = setInterval(watch(myobj, "a", myhandler), 100);
myobj.set_a(2);
การใช้Prototype
: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty
// Console
function print(t) {
var c = document.getElementById('console');
c.innerHTML = c.innerHTML + '<br />' + t;
}
// Demo
var myVar = 123;
Object.defineProperty(this, 'varWatch', {
get: function () { return myVar; },
set: function (v) {
myVar = v;
print('Value changed! New value: ' + v);
}
});
print(varWatch);
varWatch = 456;
print(varWatch);
<pre id="console">
</pre>
// Console
function print(t) {
var c = document.getElementById('console');
c.innerHTML = c.innerHTML + '<br />' + t;
}
// Demo
var varw = (function (context) {
return function (varName, varValue) {
var value = varValue;
Object.defineProperty(context, varName, {
get: function () { return value; },
set: function (v) {
value = v;
print('Value changed! New value: ' + value);
}
});
};
})(window);
varw('varWatch'); // Declare
print(varWatch);
varWatch = 456;
print(varWatch);
print('---');
varw('otherVarWatch', 123); // Declare with initial value
print(otherVarWatch);
otherVarWatch = 789;
print(otherVarWatch);
<pre id="console">
</pre>
varw
ต้องใช้อาร์กิวเมนต์ 2 ตัว แต่ตัวอย่างส่วนหนึ่งของคุณแสดงฟังก์ชันที่ถูกเรียกด้วยพารามิเตอร์พารามิเตอร์
ขออภัยที่จะนำเธรดเก่าออกมา แต่นี่เป็นคู่มือเล็กน้อยสำหรับผู้ที่ (เช่นฉัน!) ไม่เห็นตัวอย่างการทำงานของ Eli Grey:
var test = new Object();
test.watch("elem", function(prop,oldval,newval){
//Your code
return newval;
});
หวังว่าสิ่งนี้จะช่วยให้ใครบางคน
ในฐานะที่เป็นคำตอบของลุคชาเชเฟอร์ ( หมายเหตุ : นี่หมายถึงโพสต์ต้นฉบับของเขา แต่จุดทั้งหมดที่นี่ยังคงใช้ได้หลังจากการแก้ไข ) ฉันขอแนะนำวิธีการรับ / ตั้งค่าคู่หนึ่งเพื่อเข้าถึงค่าของคุณ
อย่างไรก็ตามฉันขอแนะนำการแก้ไขบางอย่าง (และนั่นเป็นสาเหตุที่ฉันโพสต์ ... )
ปัญหาของรหัสนั้นคือฟิลด์a
ของวัตถุmyobj
นั้นสามารถเข้าถึงได้โดยตรงดังนั้นจึงเป็นไปได้ที่จะเข้าถึงมัน / เปลี่ยนค่าของมันโดยไม่ทริกเกอร์ผู้ฟัง:
var myobj = { a : 5, get_a : function() { return this.a;}, set_a : function(val) { this.a = val; }}
/* add listeners ... */
myobj.a = 10; // no listeners called!
ดังนั้นเพื่อรับประกันว่าผู้ฟังจะได้รับการเรียกจริงเราจะต้องห้ามการเข้าถึงสนามa
โดยตรง ทำอย่างไร ใช้การปิด !
var myobj = (function() { // Anonymous function to create scope.
var a = 5; // 'a' is local to this function
// and cannot be directly accessed from outside
// this anonymous function's scope
return {
get_a : function() { return a; }, // These functions are closures:
set_a : function(val) { a = val; } // they keep reference to
// something ('a') that was on scope
// where they were defined
};
})();
ตอนนี้คุณสามารถใช้วิธีเดียวกันในการสร้างและเพิ่มผู้ฟังตามที่ลุคเสนอ แต่คุณสามารถมั่นใจได้ว่าไม่มีวิธีที่เป็นไปได้ที่จะอ่านหรือเขียนจากการa
ไม่สนใจ!
ยังอยู่ในการติดตามของลุคฉันเสนอวิธีง่ายๆในการเพิ่มฟิลด์ที่ถูกห่อหุ้มและตัวเชื่อมต่อ / ตัวเซ็ตที่เกี่ยวข้องไปยังวัตถุโดยใช้การเรียกฟังก์ชันอย่างง่าย
ทราบว่านี้จะทำงานอย่างถูกต้องกับประเภทค่า สำหรับการทำงานกับประเภทของการอ้างอิง , ชนิดของสำเนาลึกจะต้องมีการดำเนินการ (ดูคนนี้เป็นต้น)
function addProperty(obj, name, initial) {
var field = initial;
obj["get_" + name] = function() { return field; }
obj["set_" + name] = function(val) { field = val; }
}
สิ่งนี้ใช้งานได้เหมือนเมื่อก่อน: เราสร้างตัวแปรโลคอลในฟังก์ชั่นแล้วสร้างการปิด
วิธีการใช้งาน ง่าย:
var myobj = {};
addProperty(myobj, "total", 0);
window.alert(myobj.get_total() == 0);
myobj.set_total(10);
window.alert(myobj.get_total() == 10);
หากคุณใช้ jQuery {UI} (ซึ่งทุกคนควรใช้ :-)) คุณสามารถใช้. change () พร้อมอิลิเมนต์ <input /> ที่ซ่อนอยู่
<input/>
องค์ประกอบที่ซ่อนอยู่ได้อย่างไร
<input type="hidden" value="" id="thisOne" />
และกับ jQuery $("#thisOne").change(function() { do stuff here });
และ$("#thisOne").val(myVariableWhichIsNew);
แล้ว.change()
ไฟประสงค์
var1 = 'new value';
คุณจะตั้งค่าของอินพุตที่ถูกซ่อนแทนจากนั้นเพิ่มผู้ฟังเพื่อเปลี่ยนตัวแปร $("#val1").on('change', function(){ val1 = this.val(); ... do the stuff that you wanted to do when val1 changed... }); $("#val1").val('new value');
AngularJS
(ฉันรู้ว่านี่ไม่ใช่JQuery
แต่อาจช่วยได้ [JS บริสุทธิ์เป็นสิ่งที่ดีในทางทฤษฎีเท่านั้น]):
$scope.$watch('data', function(newValue) { ..
โดยที่ "data" เป็นชื่อของตัวแปรของคุณในขอบเขต
$scope.$apply()
ทำงานเมื่อถูกเรียกใช้เท่านั้น
สำหรับการปรับจูนในสองสามปีต่อมา:
โซลูชันสำหรับเบราว์เซอร์ส่วนใหญ่ (และ IE6 +) พร้อมใช้งานที่ใช้เหตุการณ์ onpropertychange และ define specProperty ที่ใหม่กว่า สิ่งที่จับได้เล็กน้อยคือคุณจะต้องทำให้ตัวแปรของคุณเป็นวัตถุโดม
รายละเอียดแบบเต็ม:
http://johndyer.name/native-browser-get-set-properties-in-javascript/
ฟังก์ชั่นที่คุณกำลังมองหาสามารถทำได้โดยใช้วิธี "defineProperty ()" ซึ่งใช้ได้เฉพาะเบราว์เซอร์สมัยใหม่เท่านั้น:
ฉันเขียนส่วนขยาย jQuery ที่มีฟังก์ชั่นคล้ายกันบ้างถ้าคุณต้องการการสนับสนุนข้ามเบราว์เซอร์เพิ่มเติม:
https://github.com/jarederaj/jQueue
นามสกุล jQuery ขนาดเล็กที่จัดการการโทรกลับเพื่อรอคิวการมีอยู่ของตัวแปรวัตถุหรือคีย์ คุณสามารถกำหนดจำนวนการเรียกกลับไปยังจำนวนจุดข้อมูลใด ๆ ที่อาจได้รับผลกระทบจากกระบวนการที่ทำงานในพื้นหลัง jQueue รอฟังและรอข้อมูลเหล่านี้ที่คุณระบุว่ามีอยู่จริงจากนั้นจะทำการปิดการเรียกกลับที่ถูกต้องด้วยอาร์กิวเมนต์
ไม่ใช่โดยตรง: คุณต้องการคู่ getter / setter ที่มีอินเทอร์เฟซ "addListener / removeListener" ของการเรียงลำดับบางอย่าง ... หรือปลั๊กอิน NPAPI (แต่นั่นเป็นอีกเรื่องหนึ่ง)
//ex:
/*
var x1 = {currentStatus:undefined};
your need is x1.currentStatus value is change trigger event ?
below the code is use try it.
*/
function statusChange(){
console.log("x1.currentStatus_value_is_changed"+x1.eventCurrentStatus);
};
var x1 = {
eventCurrentStatus:undefined,
get currentStatus(){
return this.eventCurrentStatus;
},
set currentStatus(val){
this.eventCurrentStatus=val;
//your function();
}
};
หรือ
/* var x1 = {
eventCurrentStatus:undefined,
currentStatus : {
get : function(){
return Events.eventCurrentStatus
},
set : function(status){
Events.eventCurrentStatus=status;
},
}*/
console.log("eventCurrentStatus = "+ x1.eventCurrentStatus);
x1.currentStatus="create"
console.log("eventCurrentStatus = "+ x1.eventCurrentStatus);
x1.currentStatus="edit"
console.log("eventCurrentStatus = "+ x1.eventCurrentStatus);
console.log("currentStatus = "+ x1.currentStatus);
หรือ
/* global variable ku*/
var jsVarEvents={};
Object.defineProperty(window, "globalvar1", {//no i18n
get: function() { return window.jsVarEvents.globalvarTemp},
set: function(value) { window.window.jsVarEvents.globalvarTemp = value; }
});
console.log(globalvar1);
globalvar1=1;
console.log(globalvar1);
วิธีแก้ปัญหาที่ค่อนข้างง่ายและง่ายคือเพียงแค่ใช้การเรียกใช้ฟังก์ชันเพื่อตั้งค่าตัวแปรส่วนกลางและไม่เคยตั้งค่าโดยตรง วิธีนี้คุณสามารถควบคุมได้ทั้งหมด:
var globalVar;
function setGlobalVar(value) {
globalVar = value;
console.log("Value of globalVar set to: " + globalVar);
//Whatever else
}
ไม่มีทางที่จะบังคับใช้สิ่งนี้มันแค่ต้องมีวินัยในการเขียนโปรแกรม ... แม้ว่าคุณจะสามารถใช้grep
(หรือบางอย่างที่คล้ายกัน) เพื่อตรวจสอบว่าไม่มีที่ไหนที่รหัสของคุณจะตั้งค่าโดยตรงglobalVar
เพื่อตรวจสอบว่าไม่มีที่ไหนรหัสของคุณโดยตรงตั้งค่าของ
หรือคุณสามารถแค็ปซูลในวัตถุและวิธีการทะเยอทะยานของผู้ใช้และผู้ตั้งค่า ... แค่คิด
var
ในโมดูล ES6 - นี่เป็นวิธีแก้ปัญหาเดียว
ได้โปรดจำไว้ว่าคำถามเริ่มต้นมีไว้สำหรับตัวแปรไม่ใช่สำหรับวัตถุประสงค์;)
นอกเหนือจากคำตอบทั้งหมดข้างต้นฉันได้สร้าง lib เล็ก ๆ ชื่อforTheWatch.jsซึ่งใช้วิธีเดียวกันในการตรวจจับและติดต่อกลับสำหรับการเปลี่ยนแปลงในตัวแปรทั่วโลกในจาวาสคริปต์
เข้ากันได้กับตัวแปร JQUERY ไม่จำเป็นต้องใช้ OBJECTS และคุณสามารถผ่าน ARRAY ของตัวแปรหลายตัวได้โดยตรงหากจำเป็น
หากเป็นประโยชน์ ... :
https://bitbucket.org/esabora/forthewatch
โดยทั่วไปคุณเพียงแค่เรียกใช้ฟังก์ชัน:
watchIt("theVariableToWatch", "varChangedFunctionCallback");
และขออภัยล่วงหน้าหากไม่เกี่ยวข้อง
วิธีที่ง่ายที่สุดที่ฉันค้นพบเริ่มต้นจากคำตอบนี้ :
// variable holding your data
const state = {
count: null,
update() {
console.log(`this gets called and your value is ${this.pageNumber}`);
},
get pageNumber() {
return this.count;
},
set pageNumber(pageNumber) {
this.count = pageNumber;
// here you call the code you need
this.update(this.count);
}
};
แล้ว:
state.pageNumber = 0;
// watch the console
state.pageNumber = 15;
// watch the console
window.player
ในกรณีของผมผมพยายามที่จะหาว่าฉันห้องสมุดรวมทั้งในโครงการของฉันถูกกําหนดของฉัน ดังนั้นเมื่อเริ่มต้นรหัสของฉันฉันเพิ่งทำ:
Object.defineProperty(window, 'player', {
get: () => this._player,
set: v => {
console.log('window.player has been redefined!');
this._player = v;
}
});
มันเป็นไปไม่ได้โดยตรง
อย่างไรก็ตามสามารถทำได้โดยใช้ CustomEvent: https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent
วิธีการด้านล่างยอมรับอาร์เรย์ของชื่อตัวแปรเป็นอินพุตและเพิ่มฟังเหตุการณ์สำหรับแต่ละตัวแปรและทริกเกอร์เหตุการณ์สำหรับการเปลี่ยนแปลงใด ๆ กับค่าของตัวแปร
วิธีนี้ใช้การสำรวจความคิดเห็นเพื่อตรวจสอบการเปลี่ยนแปลงค่า คุณสามารถเพิ่มค่าการหมดเวลาเป็นมิลลิวินาที
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']);
มันจะตรวจจับการเปลี่ยนแปลงตัวแปรชื่อผู้ใช้และหมายเลขผู้ใช้
ด้วยความช่วยเหลือของgetterและsetterคุณสามารถกำหนดคลาส JavaScript ที่ทำสิ่งนั้นได้
อันดับแรกเรากำหนดคลาสของเราที่เรียกว่าMonitoredVariable
:
class MonitoredVariable {
constructor(initialValue) {
this._innerValue = initialValue;
this.beforeSet = (newValue, oldValue) => {};
this.beforeChange = (newValue, oldValue) => {};
this.afterChange = (newValue, oldValue) => {};
this.afterSet = (newValue, oldValue) => {};
}
set val(newValue) {
const oldValue = this._innerValue;
// newValue, oldValue may be the same
this.beforeSet(newValue, oldValue);
if (oldValue !== newValue) {
this.beforeChange(newValue, oldValue);
this._innerValue = newValue;
this.afterChange(newValue, oldValue);
}
// newValue, oldValue may be the same
this.afterSet(newValue, oldValue);
}
get val() {
return this._innerValue;
}
}
สมมติว่าเราต้องการฟังmoney
การเปลี่ยนแปลงลองสร้างตัวอย่างของMonitoredVariable
เงินเริ่มต้น0
:
const money = new MonitoredVariable(0);
จากนั้นเราจะได้รับหรือตั้งค่าโดยใช้money.val
:
console.log(money.val); // Get its value
money.val = 2; // Set its value
เนื่องจากเราไม่ได้กำหนดผู้ฟังใด ๆ จึงไม่มีอะไรพิเศษเกิดขึ้นหลังจากmoney.val
การเปลี่ยนแปลงเป็น 2
ทีนี้เรามานิยามผู้ฟังกัน beforeSet
เรามีสี่ฟังที่ใช้ได้: beforeChange
, afterChange
, afterSet
, สิ่งต่อไปนี้จะเกิดขึ้นตามลำดับเมื่อคุณใช้money.val = newValue
เพื่อเปลี่ยนค่าของตัวแปร:
ตอนนี้เรากำหนดafterChange
ฟังซึ่งจะถูกเรียกหลังจากmoney.val
มีการเปลี่ยนแปลง (ในขณะที่afterSet
จะถูกเรียกแม้ว่าค่าใหม่จะเหมือนกันกับคนเก่า):
money.afterChange = (newValue, oldValue) => {
console.log(`Money has been changed from ${oldValue} to ${newValue}`);
};
ตอนนี้ตั้งค่าใหม่3
และดูว่าเกิดอะไรขึ้น:
money.val = 3;
คุณจะเห็นสิ่งต่อไปนี้ในคอนโซล:
Money has been changed from 2 to 3
สำหรับรหัสเต็มดูhttps://gist.github.com/yusanshi/65745acd23c8587236c50e54f25731ab
นี่เป็นเธรดเก่า แต่ฉันพบคำตอบที่สูงที่สุดอันดับสอง (ผู้ฟังกำหนดเอง) ในขณะที่มองหาวิธีแก้ปัญหาโดยใช้ Angular ในขณะที่วิธีการแก้ปัญหาการทำงานเชิงมุมมีวิธีที่ดีกว่าในการแก้ไขปัญหาการใช้งาน@Output
และตัวปล่อยเหตุการณ์ การเลิกใช้ตัวอย่างในคำตอบที่ผู้ฟังกำหนดเอง:
ChildComponent.html
<button (click)="increment(1)">Increment</button>
ChildComponent.ts
import {EventEmitter, Output } from '@angular/core';
@Output() myEmitter: EventEmitter<number> = new EventEmitter<number>();
private myValue: number = 0;
public increment(n: number){
this.myValue += n;
// Send a change event to the emitter
this.myEmitter.emit(this.myValue);
}
ParentComponent.html
<child-component (myEmitter)="monitorChanges($event)"></child-component>
<br/>
<label>{{n}}</label>
ParentComponent.ts
public n: number = 0;
public monitorChanges(n: number){
this.n = n;
console.log(n);
}
ตอนนี้จะอัปเดตn
กับผู้ปกครองทุกครั้งที่มีการคลิกปุ่มลูก การทำงานของstackblitz
Utils = {
eventRegister_globalVariable : function(variableName,handlers){
eventRegister_JsonVariable(this,variableName,handlers);
},
eventRegister_jsonVariable : function(jsonObj,variableName,handlers){
if(jsonObj.eventRegisteredVariable === undefined) {
jsonObj.eventRegisteredVariable={};//this Object is used for trigger event in javascript variable value changes ku
}
Object.defineProperty(jsonObj, variableName , {
get: function() {
return jsonObj.eventRegisteredVariable[variableName] },
set: function(value) {
jsonObj.eventRegisteredVariable[variableName] = value; handlers(jsonObj.eventRegisteredVariable[variableName]);}
});
}