JavaScript'te değişken değişiklikleri dinleme


463

JS'de belirli bir değişkenin değeri değiştiğinde tetiklenen bir olay olabilir mi? JQuery kabul edilir.


@BenjaminGruenbaum muhtemelen MutableObserver (DOM için) demek istersiniz. Nesne sadece hatırladığım JS nesneleri içindir.
HellBaby

2
@HellBaby Bu soru değişkenlerle ilgili - DOM değil.
Benjamin Gruenbaum

9
@BenjaminGruenbaum göre developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/... Object.observe eskimiş veya önerilmemektedir. Önerilen değiştirme (aynı sayfa başına) Proxy nesnesidir.
stannius

4
Soru sadece soruyor variable, ancak buradaki tüm cevaplar atıfta bulunuyor property. local variableDeğişiklikleri dinleyip dinleyemeyeceğimizi merak ediyorum .
Thariq Nugrohotomo

1
Bunun cevabı var mı? Yani, birini seçmek için
Braian Mellor

Yanıtlar:


100

Evet, bu artık tamamen mümkün!

Bu eski bir iş parçacığı olduğunu biliyorum ama şimdi bu etki erişimciler (alıcılar ve ayarlayıcılar) kullanarak mümkündür: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Working_with_Objects#Defining_getters_and_setters

aInternalAlanı temsil eden şöyle bir nesne tanımlayabilirsiniz 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;
  }
}

Ardından aşağıdakileri kullanarak bir dinleyici kaydedebilirsiniz:

x.registerListener(function(val) {
  alert("Someone changed the value of x.a to " + val);
});

Böylece, herhangi bir değer değerini değiştirdiğinde, x.adinleyici işlevi tetiklenir. Aşağıdaki satırı çalıştırmak uyarı açılır penceresini getirecektir:

x.a = 42;

Buradaki bir örneğe bakın: https://jsfiddle.net/5o1wf1bn/1/

Tek bir dinleyici yuvası yerine bir dizi dinleyici de kullanabilirsiniz, ancak size mümkün olan en basit örneği vermek istedim.


6
Bu, nesne başına bir ton kod, bunu daha yeniden kullanılabilir hale getirmenin bir yolu var mı?
Vael Victus

Kodunuz nerede? Ondan yeni bir soru başlattınız mı?
Akira

Bir nesneye yeni bir özellik eklendiğinde veya bir nesne kaldırıldığında algılama yolu nedir?
Michael

Bu eski bir cevap, ama dizi değeri için de işe yaradığı gibi dizi değerini ayarlamak sürece bu iyi çalışır eklemek istiyorum.
TabsNotSpaces

1
Tek bir yerine bir dinleyici dizisine sahip olmanız ve daha sonra sadece this.aListener(val)aramak yerine, tüm dinleyici işlevleri arasında dolaşmanız ve her birini çağırmanız gerekir val. Genellikle, yöntem addListeneryerine çağrılır registerListener.
Akira

75

Bu soruya verilen cevapların çoğu eski, etkisizdir veya büyük şişirilmiş kütüphanelerin dahil edilmesini gerektirir:

Bugün, artık bir nesnede yapılan değişiklikleri izlemek (ve kesmek) için Proxy nesnesini kullanabilirsiniz . OP'nin yapmaya çalıştığı amaç için üretilmiştir. İşte temel bir örnek:

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'

ProxyNesnenin tek dezavantajı :

  1. ProxyNesne (örneğin IE11 gibi) eski tarayıcılarda kullanılamaz ve polyfill can tamamen çoğaltmak değil Proxyişlevsellik.
  2. Proxy nesneleri her zaman özel nesnelerle (örn. Date) Beklendiği gibi davranmaz - Proxynesne en iyi şekilde düz Nesneler veya Dizilerle eşleştirilir.

Yuvalanmış bir nesnede yapılan değişiklikleri gözlemlemeniz gerekiyorsa, aşağıdaki gibi Gözlenebilir İnce (yayınladığım) gibi özel bir kitaplık kullanmanız gerekir :

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
Başka bir dezavantaj ekleyeceğim, aslında hedef nesnede değil, yalnızca proxy nesnesinde değişiklikleri izliyorsunuz. Bazı durumlarda, sadece hedef nesnede bir özellik değiştiğini bilmek istersiniz (örn. target.hello_world = "test")
Cristiano

2
you don't actually watch changes on the target object but only on proxy object- bu pek doğru değil. ProxyNesne değiştirilmez - bu hedefin o kendi kopyasını yoktur. you just want to know when a property change on the target object- bunu a ile yapabilirsiniz Proxy, bu proxy'ler için birincil kullanım durumlarından biridir.
Elliot

2
Hayır, çünkü hedefi doğrudan değiştiriyorsunuz. Değişikliği gözlemlemek targetistiyorsanız, bir proxy üzerinden yapmanız gerekir. Bununla birlikte proxy.hello_world = "test", proxy'yi değiştirdiğiniz anlamına gelmez, proxy değişmeden kalır, targetdeğiştirilir (ayarlanan işleyiciniz bunu yapacak şekilde yapılandırılmışsa). Demek istediğin, doğrudan gözlemleyemediğin gibi geliyor target.hello_world = "test". Bu doğru. Basit değişken atamaları herhangi bir olay yayınlamaz. Bu yüzden bu sorunun cevaplarında açıklananlar gibi araçlar kullanmalıyız.
Elliot

2
Teşekkürler Elliot B. It sounds like your point is that you cannot directly observe target.hello_world = "test". That is true.Bu benim amacım. Benim durumumda başka bir yerde oluşturulan ve başka bir kod tarafından güncellenen bir nesnem var ... bu durumda, değişiklikler hedefe yapılacak çünkü bir proxy, yararlı değil.
Cristiano

1
@Cristiano Elliot'un söylemeye çalıştığı şey , gerçek nesne yerine proxy'yi kullanabilmenizdir , yani proxy'yi nesnenizmiş gibi geçirebilir ve uygulamanın diğer bölümlerini proxy'nizle etkileşime sokabilirsiniz. Proxy'deki değişiklikler asıl nesneye yansıtılacaktır.
Zoltán Matók

33

Hayır.

Ancak, gerçekten bu kadar önemliyse, 2 seçeneğiniz var (ilk test edilir, ikincisi değil):

İlk olarak ayarlayıcıları ve alıcıları aşağıdaki gibi kullanın:

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

o zaman şöyle bir şey yapabilirsiniz:

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

sonra dinleyiciyi aşağıdaki gibi ayarlayın:

listen_to(myobj, "a", function(oldval, newval) {
    alert("old : " + oldval + " new : " + newval);
}

İkincisi, aslında unuttum, düşünürken göndereceğim :)

EDIT: Oh, hatırlıyorum :) Sen değerine bir saat koyabilirsiniz:

Yukarıda 'm' ile myobj verildiğinde:

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
"izlemek" aslında bir değişiklik algılamıyor. Bu olay tabanlı değildir ve kesinlikle çok yakında tüm uygulamayı yavaşlatır. Bu yaklaşımlar IMHO asla gerçek bir projenin parçası olmamalıdır.
Muhammed bin Yusrat

28

Kullanarak Prototype: https://developer.mozilla.org/tr-TR/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>

Diğer örnek

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


İkinci örnek biraz yanıltıcıdır, varw2 argüman gerektirir , ancak örneğinizin bir kısmı sadece value parametresiyle çağrılan işlevi gösterir.
Hlawuleka MAS

22

Eski bir konu açtığım için üzgünüm, ama işte (benim gibi!) Eli Grey'in örneğinin nasıl çalıştığını görmeyenler için küçük bir kılavuz:

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

Umarım bu birine yardımcı olabilir


9
Saat şu anda Chrome veya Safari'de desteklenmiyor, yalnızca Firefox
Paul McClean

5
Mozilla geliştirici ağı başına bu önerilmez. Object.prototype.watch () yalnızca test amaçlıdır ve üretim kodunda kullanılmamalıdır. developer.mozilla.org/tr-TR/docs/Web/JavaScript/Reference/…
Dennis Bartlett

4
@PaulMcClean bu cevap Eli Grey'in bir Polyfill içeren cevabına cevabıydı. gist.github.com/eligrey/384583
Hobisi

2
Saat Mozilla tarafından kullanımdan kaldırıldı. Bu cevap yanıltıcı olabilir.
Arnaud

7

As Luke Schafer cevabı ( not : bu onun orijinal yayına gelir; ancak bütün mesele burada düzenleme sonrasında geçerli kalır ), ben de al bir çift / değerinizi erişmek için set yöntemleri öneririm.

Ancak bazı değişiklikler öneriyorum (ve bu yüzden gönderiyorum ...).

Bu kodla ilgili bir sorun a, nesnenin alanına myobjdoğrudan erişilebilmesidir, bu nedenle dinleyicileri tetiklemeden ona erişmek / değerini değiştirmek mümkündür:

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!

kapsülleme

Bu nedenle, dinleyicilerin gerçekten çağrıldığını garanti etmek için, alana doğrudan erişimi yasaklamak zorundayız a. Nasıl yapılır? Bir kapak kullanın !

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

Artık Luke'un önerdiği dinleyicileri oluşturmak ve eklemek için aynı yöntemi kullanabilirsiniz, ancak afark edilmeden okumak veya yazmak için olası bir yol olmadığından emin olabilirsiniz !

Programlanmış kapsüllenmiş alanları ekleme

Hala Luke'un yolunda, şimdi basit bir fonksiyon çağrısı ile kapsüllenmiş alanları ve ilgili alıcıları / ayarlayıcıları nesnelere eklemenin basit bir yolunu öneriyorum.

Bunun yalnızca değer türleriyle düzgün çalışacağını unutmayın . İle çalışmalarına Bunun için başvuru türleri , bir tür derin kopya (bkz uygulanacak olurdu bu bir örneğin).

function addProperty(obj, name, initial) {
    var field = initial;
    obj["get_" + name] = function() { return field; }
    obj["set_" + name] = function(val) { field = val; }
}

Bu, öncekiyle aynı şekilde çalışır: bir işlev üzerinde yerel bir değişken oluştururuz ve sonra bir kapanış oluştururuz.

Bu nasıl kullanılır? Basit:

var myobj = {};
addProperty(myobj, "total", 0);
window.alert(myobj.get_total() == 0);
myobj.set_total(10);
window.alert(myobj.get_total() == 10);

2
Kapsülleme için +1. Bu benim ilk düşüncemdi, ama sonunda create_gets_sets yöntemini ekleme yeteneğini istedim ve gelişigüzel olduğu için değerleri gizlemek hoş değil :) bir adım daha ileri gidebilir ve değerleri gizlemek için bazı şeyler yazabiliriz, ancak Gönderdiğim kodun çoğu insan için yeterince kafa karıştırıcı olduğunu düşünüyorum ... belki de eğer çağrı varsa ...
Luke Schafer

6

JQuery {UI} (herkesin :-) kullanması gerekir) kullanıyorsanız, gizli bir <input /> öğesi ile .change () kullanabilirsiniz.


7
Tam olarak anlamıyorum. Gizli bir <input/>öğeye nasıl değişken ekleyebilirsiniz ?
Peter Lee

4
Ben Chuck jquery ve sonra ve bir .change () olay dinleyicisi kullanarak giriş değerini ayarlayabilirsiniz öneririz. Girişin değerini .val () ile güncellerseniz, .change () olayı geri çağrısı tetiklenir.
jarederaj

2
<input type="hidden" value="" id="thisOne" />ve jQuery $("#thisOne").change(function() { do stuff here });ile $("#thisOne").val(myVariableWhichIsNew);ve sonra .change()irade ateş.
khaverim

2
Kitaplarımdaki en iyi çözüm bu. Basit, kolay. Kodunuzdaki değişkeni değiştirmek yerine, örneğin var1 = 'new value';, bu gizli girişin değerini ayarlayacak ve daha sonra değişkeni değiştirmek için bir dinleyici ekleyeceksiniz. $("#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
Değişim olayı doesnt tetik $ çalışırsanız, benimle aynı sorunu yaşıyor herkese ( "# thisOne") için val (myVariableWhichIsNew) .trigger ( 'değişim') .Hope bu yardımcı olur.
Alator

6

AngularJS(Bunun olmadığını biliyorum JQuery, ama bu yardımcı olabilir. [Pure JS sadece teoride iyidir]):

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

burada "veri", kapsamdaki değişkeninizin adıdır.

Doc bağlantısı var .


Ne yazık ki değişkenleri kapsama bağlamaya zorlar
ruX

sadece $scope.$apply()çalıştırıldığında
kovulur


3

Aradığınız işlevsellik, yalnızca modern tarayıcılar tarafından kullanılabilen "defineProperty ()" yöntemini kullanarak elde edilebilir:

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

Daha fazla çapraz tarayıcı desteğine ihtiyacınız varsa benzer işlevlere sahip bir jQuery uzantısı yazdım:

https://github.com/jarederaj/jQueue

Değişken, nesne veya anahtarın varlığına sıraya giren geri çağrıları işleyen küçük bir jQuery uzantısı. Arka planda çalışan işlemlerden etkilenebilecek herhangi bir sayıda veri noktasına istediğiniz sayıda geri arama atayabilirsiniz. jQueue dinlediğinizi belirttiğiniz bu verileri dinler ve bekler ve ardından argümanlarıyla doğru geri aramayı başlatır.


2

Doğrudan değil: bir çeşit "addListener / removeListener" arayüzüne sahip bir çift alıcı / ayarlayıcıya ihtiyacınız var ... veya bir NPAPI eklentisi (ama bu tamamen başka bir hikaye).


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

veya

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

veya

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

Oldukça basit ve basit bir çözüm, global değişkenin değerini ayarlamak için sadece bir işlev çağrısı kullanmak ve değerini asla doğrudan ayarlamamaktır. Bu şekilde tam kontrole sahip olursunuz:

var globalVar;

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

Bunu zorlamanın bir yolu yoktur, sadece programlama disiplini gerektirir ... ancak grepkodunuzun hiçbir yerde doğrudan değerini ayarlamadığını kontrol etmek için kullanabilirsiniz (veya benzer bir şey) globalVar.

Ya da bir nesneyi ve kullanıcı alıcı ve ayarlayıcı yöntemlerini içine alabilirsin ... sadece bir düşünce.


Bir nesnenin özelliği olmayan bir değişken için var, ES6 modüllerinde bildirilen değişkenlerde olduğu gibi, bu tek çözümdür.
amn

1

Lütfen ilk sorunun NESNELER için değil DEĞİŞKENLER için olduğunu unutmayın;)

Yukarıdaki tüm cevaplara ek olarak , javascript normal küresel değişkenlerdeki değişiklikleri yakalamak ve geri çağırmak için aynı yolu kullanan forTheWatch.js adlı küçük bir lib oluşturdum .

JQUERY değişkenleriyle uyumludur, NESNELER kullanmaya gerek yoktur ve gerekirse birkaç değişkenin doğrudan bir ARRAY'ini geçirebilirsiniz.

Yararlı olabilirse ...: https://bitbucket.org/esabora/forthewatch
Temel olarak sadece işlevi çağırmanız gerekir:
watchIt("theVariableToWatch", "varChangedFunctionCallback");

Ve ilgili değilse önceden peşin üzgünüm.


1

Bu cevaptan başlayarak bulduğum en kolay yol :

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

Ve sonra:

state.pageNumber = 0;
// watch the console

state.pageNumber = 15;
// watch the console

1

Benim durumumda, projeme dahil ettiğim herhangi bir kütüphanenin yeniden tanımlanıp tanımlanmadığını öğrenmeye çalışıyordum window.player. Yani, kodumun başında, ben sadece yaptım:

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

0

Doğrudan mümkün değil.

Ancak, bu CustomEvent kullanılarak yapılabilir: https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent

Aşağıdaki yöntem, değişken adları dizisini girdi olarak kabul eder ve her değişken için olay dinleyicisi ekler ve değişkenin değerinde herhangi bir değişiklik olması için olayı tetikler.

Yöntem, değerdeki değişikliği algılamak için yoklama kullanır. Zaman aşımı değerini milisaniye cinsinden artırabilirsiniz.

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

Yöntemi çağırarak:

watchVariables(['username', 'userid']);

Kullanıcı adı ve kullanıcı kimliği değişkenlerindeki değişiklikleri tespit edecektir.


0

Alıcı ve ayarlayıcı yardımıyla böyle bir şey yapan bir JavaScript sınıfı tanımlayabilirsiniz.

İlk olarak, sınıfımızı şöyle tanımlarız 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;
  }
}

moneyDeğişiklikleri dinlemek istediğimizi varsayalım, MonitoredVariableilk parayla bir örnek oluşturalım 0:

const money = new MonitoredVariable(0);

Sonra değerini kullanarak veya ayarlayabiliriz money.val:

console.log(money.val); // Get its value
money.val = 2; // Set its value

Bunun için herhangi bir dinleyici tanımlamadığımızdan, money.val2'de yapılan değişikliklerden sonra özel bir şey olmaz .

Şimdi bazı dinleyicileri tanımlayalım. Biz dört dinleyici mevcut vardır: beforeSet, beforeChange, afterChange, afterSet. money.val = newValueDeğişkenin değerini değiştirmek için kullandığınızda aşağıdakiler sırayla gerçekleşir :

  1. money.beforeSet (newValue, oldValue);
  2. money.beforeChange (newValue, oldValue); (Değeri değişmezse atlanacaktır)
  3. money.val = yeniDeğer;
  4. money.afterChange (newValue, oldValue); (Değeri değişmezse atlanacaktır)
  5. money.afterSet (newValue, oldValue);

Şimdi afterChangesadece money.valdeğiştikten sonra tetiklenecek dinleyiciyi tanımlıyoruz ( afterSetyeni değer eskisiyle aynı olsa bile tetiklenecek):

money.afterChange = (newValue, oldValue) => {
  console.log(`Money has been changed from ${oldValue} to ${newValue}`);
};

Şimdi yeni bir değer belirleyin 3ve neler olduğunu görün:

money.val = 3;

Konsolda aşağıdakileri göreceksiniz:

Money has been changed from 2 to 3

Kodun tamamı için bkz. Https://gist.github.com/yusanshi/65745acd23c8587236c50e54f25731ab .


-2

Bu eski bir konu ama Angular kullanarak bir çözüm ararken ikinci en yüksek cevaba (özel dinleyiciler) rastladım. Çözüm çalışırken, açısal bu kullanımı @Outputve olay yayıcıları çözmek için daha iyi bir şekilde inşa edilmiştir . Özel dinleyici yanıtında örnekten vazgeçme:

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

Bu n, alt düğmeye her tıklandığında ebeveyn üzerinde güncellenecektir . Çalışma yığı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]);}
                    });
            }
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.