JavaScript에서 변수 변경 청취


462

JS에서 특정 변수의 값이 변경 될 때 발생하는 이벤트를 가질 수 있습니까? JQuery가 허용됩니다.


@ BenjaminGruenbaum 아마 MutableObserver (DOM 용)라고 말하고 싶을 것입니다. 객체는 내가 기억하는 JS 객체에만 해당됩니다.
— HellBaby

2
@HellBaby이 질문은 변수가 아닌 DOM에 관한 것입니다.
— Benjamin Gruenbaum

9
@BenjaminGruenbaum에 따라 developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/... Object.observe 것은 폐기되었거나 사용되지 않습니다. 동일한 페이지에 대해 권장되는 대체 방법은 Proxy 객체입니다.
— stannius

4
에 대한 질문 만 variable있지만 여기에있는 모든 답변은에 해당합니다 property. local variable그래도 변경 사항을 들을 수 있을지 궁금합니다 .
— Thariq Nugrohotomo

1
이에 대한 답변이 있습니까? 나는 하나를 선택, 의미
— Braian 멜러에게

답변:


100

예, 이제 가능합니다!

나는이 오래된 스레드 알고 있지만 지금이 효과가 접근에게 (getter 및 setter)를 사용하여 가능하다 : 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/ 의 예를 참조하십시오.

단일 리스너 슬롯 대신 리스너 배열을 사용할 수도 있지만 가장 간단한 예를 들었습니다.


6
이것은 객체 당 많은 코드입니다. 더 재사용 할 수있는 방법이 있습니까?
— Vael Victus

코드는 어디에 있습니까? 새로운 질문을 시작 했습니까?
— Akira

객체에 새 속성이 추가되었거나 제거 된시기를 감지하는 방법은 어떻습니까?
— Michael

이것은 오래된 대답이지만 배열 값을 푸시하는 대신 배열 값을 설정하는 한 배열 값에 효과적이라고 덧붙이고 싶습니다.
— TabsNotSpaces

1
단일 리스너 대신 리스너 배열 만 this.aListener(val)있으면되고, 그냥 호출하는 대신 모든 리스너 함수를 반복하여 각 리스너를 호출해야합니다 val. 일반적으로이 메소드는 addListener대신에 호출 됩니다 registerListener.
— Akira

74

이 질문에 대한 대부분의 답변은 오래되었거나 비효율적이거나 큰 부풀린 라이브러리를 포함해야합니다.

  • Object.watch 및 Object.observe 는 더 이상 사용되지 않으며 사용해서는 안됩니다.
  • onPropertyChange 는 일부 IE 버전에서만 작동하는 DOM 요소 이벤트 핸들러입니다.
  • Object.defineProperty를 사용하면 객체 속성을 변경할 수 없도록하여 시도한 변경 사항을 감지 할 수 있지만 변경 사항도 차단할 수 있습니다.
  • setter 및 getter 정의 는 작동하지만 많은 설정 코드가 필요하며 새 특성을 삭제하거나 작성해야 할 때 제대로 작동하지 않습니다.

오늘, 당신은 지금 사용할 수있는 프록시 객체 객체에 대한 변경 모니터 (와 절편)에 있습니다. 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객체 의 유일한 단점은 다음 과 같습니다.

  1. Proxy객체 (예 : IE11 등) 이전 버전의 브라우저에서 사용할 수 없습니다와 polyfill 수 완전히 복제되지 Proxy기능을 제공합니다.
  2. 프록시 객체는 항상 특수 객체 (예 :)에서 예상대로 작동하지는 않습니다 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}}]

1
또 다른 단점을 추가하겠습니다. 실제로 대상 객체의 변경 사항을 보지 않고 프록시 객체에서만 변경 사항을 볼 수 있습니다. 어떤 경우에는, 당신은 단지 알고 싶어 할 때 대상 객체의 속성 변경 (예 target.hello_world = "test")
— 크리스티아누

2
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-를 Proxy사용하면 프록시의 주요 사용 사례 중 하나를 통해 이를 달성 할 수 있습니다 .
— Elliot B.

2
아니요. 타겟을 직접 수정하고 있기 때문입니다. 의 수정 사항을 관찰하려면 target프록시를 통해 수정 해야합니다. 그러나 proxy.hello_world = "test"프록시를 수정하고 프록시가 변경되지 않고 수정된다는 것을 의미하지는 않습니다 target(세트 핸들러가 그렇게 구성한 경우). 요점은 직접 관찰 할 수없는 것 같습니다 target.hello_world = "test". 사실입니다. 일반 변수 할당은 어떤 종류의 이벤트도 발생하지 않습니다. 그렇기 때문에이 질문에 대한 답변에서 설명한 것과 같은 도구를 사용해야합니다.
— Elliot B.

2
엘리엇 B. 감사합니다. It sounds like your point is that you cannot directly observe target.hello_world = "test". That is true.이것이 바로 제 요점입니다. 내 경우에는 다른 곳에서 객체를 만들고 다른 코드로 업데이트했습니다 ...이 경우 프록시는 변경 사항이 대상에서 수행되므로 유용하지 않습니다.
— Cristiano

1
@Cristiano Elliot이 말하려는 것은 실제 객체 대신 프록시 를 사용할 수 있다는 것입니다. 즉, 프록시가 객체 인 것처럼 프록시를 전달하고 응용 프로그램의 다른 부분이 프록시와 상호 작용하도록 할 수 있습니다. 프록시의 변경 사항은 실제 개체에 반영됩니다.
— Zoltán Matók

33

아니.

그러나 그것이 정말로 중요하다면, 두 가지 옵션이 있습니다 (첫 번째는 테스트되고 두 번째는 그렇지 않습니다)

먼저 setter와 getter를 사용하십시오.

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);

8
"보고"는 실제로 변경을 감지하지 않습니다. 이것은 이벤트 기반이 아니며, 곧 전체 앱의 속도가 매우 느려질 것입니다. 이러한 접근 방식은 IMHO가 실제 프로젝트의 일부가되어서는 안됩니다.
— Muhammad bin Yusrat

28

사용 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있지만 두 개의 인수가 필요하지만 예제의 일부는 value 매개 변수로만 호출되는 함수를 보여줍니다.
— Hlawuleka MAS

22

오래된 스레드를 가져 와서 죄송하지만 여기에 나와 같은 Eli Grey의 예제가 어떻게 작동하는지 보지 못하는 사람들을위한 약간의 매뉴얼이 있습니다.

var test = new Object();
test.watch("elem", function(prop,oldval,newval){
    //Your code
    return newval;
});

이것이 누군가를 도울 수 있기를 바랍니다.


9
현재 Chrome 또는 Safari에서 시계가 지원되지 않으며 Firefox 만 지원
— Paul McClean

5
mozilla 개발자 네트워크 당 권장하지 않습니다. Object.prototype.watch ()는 테스트 용으로 만 사용되었으며 프로덕션 코드에는 사용해서는 안됩니다. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
— Dennis Bartlett

4
@PaulMcClean이 답변은 Polyfill을 포함하는 Eli Grey의 답변에 대한 답변입니다. gist.github.com/eligrey/384583
— Hobbyist

2
Mozilla는 watch를 더 이상 사용하지 않습니다. 이 답변은 오도 될 수 있습니다.
— Arnaud

7

으로 누가 쉐퍼의 대답 ( 참고 :이 그의 원래의 게시물을 의미 있지만 요점은 여기에 편집 후 유효 ), 나 또한 가져 오기 한 쌍의 / 당신의 가치를 액세스 할 수있는 설정 방법을 제안합니다.

그러나 나는 약간의 수정을 제안 할 것입니다 (그리고 그것이 내가 게시하는 이유입니다 ...).

이 코드의 문제점 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
    };
})();

이제 Luke가 제안한 것과 동일한 방법으로 리스너를 작성하고 추가 할 수 있지만 a눈에 띄지 않게 읽거나 쓸 수있는 방법은 없습니다 .

프로그래밍 방식으로 캡슐화 된 필드 추가

여전히 Luke의 트랙에서 간단한 함수 호출을 통해 캡슐화 된 필드와 해당 getter / setter를 객체에 추가하는 간단한 방법을 제안합니다.

이것은 값 유형 에서만 올바르게 작동 합니다 . 와 작업이 들어 참조 형식 , 어떤 종류의 깊은 복사 (참조 구현되어야 할 것입니다 이 하나를 예를 들어).

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);

2
캡슐화 +1 그것은 처음 생각했지만, 결국 create_gets_sets 메소드를 추가하는 기능을 원했고, 무차별 적이기 때문에 값을 숨기는 것이 멋지지 않습니다. 내가 게시 한 코드는 대부분의 사람들에게 충분히 혼란 스럽다고 생각합니다. 어쩌면 전화가 필요한 경우 ...
— Luke Schafer

6

jQuery {UI} (모든 사람이 :-)를 사용해야하는 경우 숨겨진 <input /> 요소와 함께 .change ()를 사용할 수 있습니다.


7
잘 모르겠습니다. 숨겨진 <input/>요소에 변수를 어떻게 첨부 할 수 있습니까?
— Peter Lee

4
척은 jquery와 .change () 이벤트 리스너를 사용하여 입력 값을 설정할 수 있다고 제안합니다. 입력 값을 .val ()로 업데이트하면 .change () 이벤트 콜백이 시작됩니다.
— jarederaj

2
<input type="hidden" value="" id="thisOne" />와 jQuery로 $("#thisOne").change(function() { do stuff here });하고 $("#thisOne").val(myVariableWhichIsNew);다음 .change()의지 화재.
— khaverim

2
이것은 내 책에서 가장 좋은 솔루션입니다. 간단하고 쉽습니다. 예를 들어 코드에서 변수를 변경하는 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');
— Tom Walker

2
나와 같은 문제가있는 사람은 변경 이벤트가 트리거되지 않으면 $ ( "# thisOne"). val (myVariableWhichIsNew) .trigger ( 'change') 시도하십시오. 도움이
— 되길 바랍니다

6

AngularJS(이것은 JQuery아니지만 이것이 도움이 될 수 있음을 알고 있습니다. [순수 JS는 이론 상으로는 우수합니다]) :

$scope.$watch('data', function(newValue) { ..

여기서 "data"는 범위의 변수 이름입니다.

문서에 대한 링크가 있습니다.


불행히도 변수를 범위에 바인딩하도록 강요합니다
— ruX

그것은 $scope.$apply()실행될 때만 해고
— iamawebgeek


3

찾고있는 기능은 최신 브라우저에서만 사용할 수있는 "defineProperty ()"메소드를 사용하여 얻을 수 있습니다.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty

더 많은 브라우저 간 지원이 필요한 경우 비슷한 기능을 가진 jQuery 확장을 작성했습니다.

https://github.com/jarederaj/jQueue

변수, 객체 또는 키의 존재에 대한 대기 콜백을 처리하는 작은 jQuery 확장입니다. 백그라운드에서 실행중인 프로세스의 영향을받을 수있는 여러 데이터 포인트에 여러 개의 콜백을 할당 할 수 있습니다. jQueue는 사용자가 지정한 이러한 데이터가 수신 될 때까지 기다렸다가 해당 인수를 사용하여 올바른 콜백을 시작합니다.


2

직접적이지 않음 : 일종의 "addListener / removeListener"인터페이스 또는 NPAPI 플러그인이있는 페어 getter / setter가 필요합니다 (그러나 이것은 전혀 다른 이야기입니다).


1
//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);

1

다소 간단하고 간단한 해결책은 함수 호출을 사용하여 전역 변수의 값을 설정하고 직접 값을 설정하지 않는 것입니다. 이 방법으로 당신은 완전히 통제 할 수 있습니다 :

var globalVar;

function setGlobalVar(value) {
    globalVar = value;
    console.log("Value of globalVar set to: " + globalVar);
    //Whatever else
}

이를 시행 할 수있는 방법은 없습니다. 프로그래밍 규칙 만 있으면됩니다.하지만 grep코드를 사용하여 코드의 값을 직접 설정하는 곳이 없는지 확인할 수 있습니다 globalVar.

또는 객체와 사용자 getter 및 setter 메소드로 캡슐화 할 수 있습니다.


객체의 속성이 아닌 변수의 경우 varES6 모듈에서 선언 된 변수의 경우처럼 액세스 할 수 있는 유일한 방법입니다.
— amn

1

초기 질문은 변수가 아니라 변수에 대한 것임을 기억하십시오.)

위의 모든 답변 외에도 forTheWatch.js 라는 작은 lib를 만들었습니다.이 라이브러리 는 자바 스크립트에서 일반 전역 변수의 변경 사항을 포착하고 콜백하는 것과 동일한 방법을 사용합니다.

JQUERY 변수와 호환되며 OBJECTS를 사용할 필요가 없으며 필요한 경우 여러 변수의 ARRAY를 직접 전달할 수 있습니다.

도움이 될 수 있다면 ... : https://bitbucket.org/esabora/forthewatch
기본적으로 함수를 호출하면됩니다.
watchIt("theVariableToWatch", "varChangedFunctionCallback");

관련이없는 경우 사전에 죄송합니다.


1

이 답변 부터 시작하여 가장 쉬운 방법은 다음과 같습니다.

// 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

1

내 경우에는 프로젝트에 포함하고있는 라이브러리가 내 정의를 재정의하고 있는지 확인하려고했습니다 window.player. 따라서 코드를 시작할 때 방금 다음을 수행했습니다.

Object.defineProperty(window, 'player', {
  get: () => this._player,
  set: v => {
    console.log('window.player has been redefined!');
    this._player = v;
  }
});

0

직접 가능하지 않습니다.

그러나이 작업은 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']);

변수 username 및 userid의 변경 사항을 감지합니다.


0

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.val2로 변경 한 후에는 아무 것도 발생하지 않습니다 .

이제 리스너를 정의 해 봅시다. 우리는 네 청취자가 가능한 : beforeSet, beforeChange, afterChange, afterSet. money.val = newValue변수 값을 변경 하는 데 사용하면 다음이 순차적으로 발생합니다 .

  1. money.beforeSet (newValue, oldValue);
  2. money.beforeChange (newValue, oldValue); (값이 변경되지 않으면 생략됩니다)
  3. money.val = newValue;
  4. money.afterChange (newValue, oldValue); (값이 변경되지 않으면 생략됩니다)
  5. money.afterSet (newValue, oldValue);

이제 변경된 afterChange후에 만 트리거되는 리스너를 정의 합니다 (새 값이 이전 값과 동일한 경우에도 트리거 됨).money.valafterSet

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를 참조 하십시오 .


-2

이것은 오래된 스레드이지만 Angular를 사용하여 솔루션을 찾는 동안 두 번째로 높은 답변 (사용자 정의 리스너)을 발견했습니다. 솔루션이 작동하는 동안 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자식 버튼을 클릭 할 때마다 부모에서 업데이트 됩니다. 작업 스택


-3
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]);}
                    });
            }
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.