Ascolto di modifiche variabili in JavaScript


462

È possibile avere un evento in JS che si attiva quando cambia il valore di una determinata variabile? JQuery è accettato.


@BenjaminGruenbaum probabilmente vuoi dire MutableObserver (per DOM). L'oggetto è solo per oggetti JS da quello che ricordo.
HellBaby,

2
@HellBaby questa domanda riguarda le variabili, non il DOM.
Benjamin Gruenbaum,

9
@BenjaminGruenbaum secondo developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… Object.observe è obsoleto o obsoleto. La sostituzione consigliata (per quella stessa pagina) è l'oggetto Proxy.
stannius

4
La domanda fa solo domande variable, ma tutte le risposte qui si riferiscono property. Mi chiedo però se possiamo ascoltare i local variablecambiamenti.
Thariq Nugrohotomo,

1
c'è qualche risposta per questo? Voglio dire, selezionarne uno
Braian Mellor il

Risposte:


100

Sì, ora è completamente possibile!

So che questo è un vecchio thread, ma ora questo effetto è possibile utilizzando gli accessor (getter e setter): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Working_with_Objects#Defining_getters_and_setters

È possibile definire un oggetto come questo, in cui aInternalrappresenta il campo 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;
  }
}

Quindi è possibile registrare un listener utilizzando quanto segue:

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

Quindi ogni volta che qualcosa cambia il valore di x.a, la funzione listener verrà attivata. L'esecuzione della seguente riga porterà il popup di avviso:

x.a = 42;

Vedi un esempio qui: https://jsfiddle.net/5o1wf1bn/1/

Puoi anche utilizzare un array di listener invece di un singolo slot di ascolto, ma volevo darti l'esempio più semplice possibile.


6
Questa è una tonnellata di codice per oggetto, c'è un modo per renderlo più riutilizzabile?
Vael Victus,

Dov'è il tuo codice? Hai iniziato una nuova domanda da esso?
Akira,

Che dire di un modo per rilevare quando una nuova proprietà è stata aggiunta a un oggetto o se ne è stata rimossa una?
Michael,

Questa è una vecchia risposta, ma volevo aggiungere che funziona bene per i valori dell'array, purché tu imposti il ​​valore dell'array invece di spingerlo verso di esso.
TabsNotSpaces

1
Devi semplicemente avere un array di ascoltatori invece di uno solo e quindi invece di chiamare semplicemente this.aListener(val), dovresti scorrere tutte le funzioni dell'ascoltatore e chiamare ciascuna che passa val. In genere, il metodo viene chiamato addListenerinvece di registerListener.
Akira,

75

La maggior parte delle risposte a questa domanda sono obsolete, inefficaci o richiedono l'inclusione di librerie gonfiate di grandi dimensioni:

  • Object.watch e Object.observe sono entrambi deprecati e non devono essere utilizzati.
  • onPropertyChange è un gestore di eventi dell'elemento DOM che funziona solo in alcune versioni di IE.
  • Object.defineProperty ti consente di rendere immutabile una proprietà dell'oggetto, che ti permetterebbe di rilevare i tentativi di modifica, ma bloccherebbe anche eventuali cambiamenti.
  • La definizione di setter e getter funziona, ma richiede molto codice di installazione e non funziona bene quando è necessario eliminare o creare nuove proprietà.

Oggi è ora possibile utilizzare l' oggetto Proxy per monitorare (e intercettare) le modifiche apportate a un oggetto. È appositamente costruito per ciò che l'OP sta cercando di fare. Ecco un esempio di base:

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'

Gli unici inconvenienti Proxydell'oggetto sono:

  1. L' Proxyoggetto non è disponibile nei browser meno recenti (come IE11) e il polyfill non è in grado di replicare completamente la Proxyfunzionalità.
  2. Gli oggetti proxy non si comportano sempre come previsto con oggetti speciali (ad es. Date): L' Proxyoggetto è meglio abbinato a oggetti semplici o array.

Se è necessario osservare le modifiche apportate a un oggetto nidificato , è necessario utilizzare una libreria specializzata come Observable Slim (che ho pubblicato) che funziona in questo modo:

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
Aggiungerò anche un altro svantaggio, in realtà non si osservano le modifiche sull'oggetto target ma solo sull'oggetto proxy. In alcuni casi, vuoi solo sapere quando una proprietà cambia sull'oggetto target (es. target.hello_world = "test")
Cristiano

2
you don't actually watch changes on the target object but only on proxy object- non è del tutto esatto. L' Proxyoggetto non viene modificato - non ha una propria copia della destinazione. you just want to know when a property change on the target object- puoi farlo con a Proxy, questo è uno dei casi d'uso principali per i proxy.
Elliot B.

2
No, perché stai modificando direttamente l'obiettivo. Se si desidera osservare la modifica target, è necessario farlo tramite un proxy. Tuttavia, proxy.hello_world = "test"ciò non significa che si sta modificando il proxy, il proxy rimane invariato, targetviene modificato (se il gestore set è configurato per farlo). Sembra che il tuo punto sia che non puoi osservare direttamente target.hello_world = "test". Questo è vero. Le assegnazioni di variabili semplici non generano alcun tipo di evento. Ecco perché dobbiamo usare strumenti come quelli descritti nelle risposte a questa domanda.
Elliot B.

2
Grazie Elliot B. It sounds like your point is that you cannot directly observe target.hello_world = "test". That is true.questo è esattamente il mio punto. Nel mio caso ho creato un oggetto da qualche altra parte e sono stato aggiornato da qualche altro codice ... un proxy, in questo caso, non è utile poiché le modifiche verranno eseguite sulla destinazione.
Cristiano,

1
@Cristiano Immagino che Elliot stia cercando di dire che puoi usare il proxy invece dell'oggetto reale, il che significa che puoi passare il proxy come se fosse il tuo oggetto e far interagire le altre parti dell'app con il tuo proxy. Le modifiche al proxy si rifletteranno sull'oggetto reale.
Zoltán Matók,

33

No.

Ma, se è davvero così importante, hai 2 opzioni (la prima è testata, la seconda no):

Innanzitutto, usa setter e getter, in questo modo:

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

allora puoi fare qualcosa del tipo:

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

quindi imposta l'ascoltatore come:

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

In secondo luogo, in realtà ho dimenticato, presenterò mentre ci penso :)

EDIT: Oh, mi ricordo :) Potresti dare un'occhiata al valore:

Dato myobj sopra, con 'a' su di esso:

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
"guardare" in realtà non sta rilevando un cambiamento. Questo non è basato su eventi e certamente rallenterebbe molto presto l'intera app. Questi approcci IMHO non dovrebbero mai far parte di un vero progetto.
Muhammad bin Yusrat,

28

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

Altro esempio

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


Il secondo esempio è un po 'fuorviante, varwrichiede 2 argomenti ma parte del tuo esempio mostra la funzione chiamata con solo il parametro value.
Hlawuleka MAS,

22

Mi dispiace di avere un vecchio thread, ma ecco un piccolo manuale per coloro che (come me!) Non vedono come funziona l'esempio di Eli Grey:

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

Spero che questo possa aiutare qualcuno


9
Al momento, Watch non è supportato su Chrome o Safari, solo Firefox
Paul McClean,

5
Per la rete di sviluppatori Mozilla, questo non è raccomandato. Object.prototype.watch () era destinato esclusivamente ai test e non deve essere utilizzato nel codice di produzione. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Dennis Bartlett,

4
@PaulMcClean questa risposta era in risposta alla risposta di Eli Grey che conteneva un Polyfill. gist.github.com/eligrey/384583
Hobbyist,

2
l'orologio è stato deprecato da Mozilla. Questa risposta potrebbe essere fuorviante.
Arnaud,

7

Come la risposta di Luke Schafer ( nota : questo si riferisce al suo post originale; ma l'intero punto qui rimane valido dopo la modifica ), suggerirei anche un paio di metodi Get / Set per accedere al tuo valore.

Tuttavia suggerirei alcune modifiche (ed è per questo che sto postando ...).

Un problema con quel codice è che il campo adell'oggetto myobjè direttamente accessibile, quindi è possibile accedervi / modificarne il valore senza innescare i listener:

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!

incapsulamento

Quindi, per garantire che gli ascoltatori siano effettivamente chiamati, dovremmo vietare l'accesso diretto al campo a. Come si fa? Usa una chiusura !

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

Ora puoi usare lo stesso metodo per creare e aggiungere gli ascoltatori come proposto da Luca, ma puoi essere certo che non c'è modo di leggere o scrivere per apassare inosservato!

Aggiunta di campi incapsulati a livello di codice

Sempre sulla pista di Luke, propongo ora un modo semplice per aggiungere campi incapsulati e rispettivi getter / setter agli oggetti mediante una semplice chiamata di funzione.

Si noti che funzionerà correttamente solo con tipi di valore . Affinché ciò funzioni con i tipi di riferimento , dovrebbe essere implementato un tipo di copia profonda (vedi questo , per esempio).

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

Funziona come prima: creiamo una variabile locale su una funzione, quindi creiamo una chiusura.

Come usarlo? Semplice:

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

2
+1 per l'incapsulamento. Questo è stato il mio primo pensiero, ma volevo la possibilità di aggiungere il metodo create_gets_sets alla fine, e poiché è indiscriminato, nascondere i valori non è bello :) possiamo fare un passo avanti e scrivere alcune cose per nascondere i valori, ma Penso che il codice che ho pubblicato sia abbastanza confuso per la maggior parte delle persone ... forse se ce ne fosse bisogno ...
Luke Schafer,

6

Se stai usando jQuery {UI} (che tutti dovrebbero usare :-)), puoi usare .change () con un elemento <input /> nascosto.


7
Non capisco bene. Come puoi associare una variabile a un <input/>elemento nascosto ?
Peter Lee,

4
Penso che Chuck stia suggerendo che puoi impostare il valore dell'input usando jquery e quindi e un listener di eventi .change (). Se si aggiorna il valore dell'input con .val (), verrà attivato il callback dell'evento .change ().
jarederaj,

2
<input type="hidden" value="" id="thisOne" />e con jQuery $("#thisOne").change(function() { do stuff here });e $("#thisOne").val(myVariableWhichIsNew);poi il .change()fuoco della volontà.
Khaverim,

2
Questa è la migliore soluzione nei miei libri. Semplice, facile. Invece di modificare la variabile nel tuo codice, ad esempio var1 = 'new value';, imposterai invece il valore di questo input nascosto, quindi aggiungi un listener per modificare la variabile. $("#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
Per chiunque abbia lo stesso problema, se l'evento change non si attiva, prova $ ("# thisOne"). Val (myVariableWhichIsNew) .trigger ('change'). Spero che questo aiuti
Alator

6

AngularJS(So ​​che non lo è JQuery, ma ciò potrebbe aiutare. [Pure JS è buono solo in teoria]):

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

dove "data" è il nome della variabile nell'ambito.

C'è un collegamento a doc.


Sfortunatamente ti costringe a legare la variabile all'ambito
ruX

viene sparato solo quando $scope.$apply()viene lanciato
iamawebgeek


3

La funzionalità che stai cercando può essere raggiunta attraverso l'uso del metodo "defineProperty ()", che è disponibile solo per i browser moderni:

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

Ho scritto un'estensione jQuery che ha alcune funzionalità simili se hai bisogno di più supporto tra browser:

https://github.com/jarederaj/jQueue

Una piccola estensione jQuery che gestisce i callback in coda per l'esistenza di una variabile, un oggetto o una chiave. È possibile assegnare un numero qualsiasi di richiamate a qualsiasi numero di punti dati che potrebbero essere interessati dai processi in esecuzione in background. jQueue ascolta e attende la data di esistenza di questi dati specificati, quindi avvia il callback corretto con i relativi argomenti.


2

Non direttamente: hai bisogno di una coppia getter / setter con un'interfaccia "addListener / removeListener" di qualche tipo ... o un plug-in NPAPI (ma questa è tutta un'altra storia).


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

o

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

o

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

Una soluzione piuttosto semplice e semplicistica consiste nell'utilizzare semplicemente una chiamata di funzione per impostare il valore della variabile globale e non impostarne mai direttamente il valore. In questo modo hai il controllo totale:

var globalVar;

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

Non c'è modo di imporre questo, richiede solo una disciplina di programmazione ... anche se puoi usare grep(o qualcosa di simile) per verificare che in nessun punto il tuo codice imposta direttamente il valore diglobalVar .

Oppure potresti incapsularlo in un oggetto e metodi getter e setter dell'utente ... solo un pensiero.


Per una variabile che non è una proprietà di un oggetto è possibile accedere - come nel caso delle variabili dichiarate con varnei moduli ES6 - questa è l' unica soluzione.
AMN

1

Per favore, ragazzi, ricordate che la domanda iniziale era per VARIABLES, non per OBJECTS;)

oltre a tutte le risposte sopra, ho creato una piccola lib chiamata forTheWatch.js , che usa lo stesso modo per catturare e richiamare le modifiche nelle normali variabili globali in javascript.

Compatibile con le variabili JQUERY, non è necessario utilizzare OBJECTS e, se necessario, è possibile passare direttamente un ARRAY di più variabili.

Se può essere utile ...: https://bitbucket.org/esabora/forthewatch
Fondamentalmente devi solo chiamare la funzione:
watchIt("theVariableToWatch", "varChangedFunctionCallback");

E scusa in anticipo se non pertinente.


1

Il modo più semplice che ho trovato, partendo da questa risposta :

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

E poi:

state.pageNumber = 0;
// watch the console

state.pageNumber = 15;
// watch the console

1

Nel mio caso, stavo cercando di scoprire se qualsiasi libreria che stavo includendo nel mio progetto stava ridefinendo la mia window.player. Quindi, all'inizio del mio codice, ho appena fatto:

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

0

Non è direttamente possibile.

Tuttavia, questo può essere fatto utilizzando CustomEvent: https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent

Il metodo seguente accetta una matrice di nomi di variabili come input e aggiunge un listener di eventi per ciascuna variabile e attiva l'evento per eventuali modifiche al valore delle variabili.

Il metodo utilizza il polling per rilevare la modifica del valore. È possibile aumentare il valore per il timeout in millisecondi.

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

Chiamando il metodo:

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

Rileverà le modifiche alle variabili username e userid.


0

Con l'aiuto di getter e setter , puoi definire una classe JavaScript che fa una cosa del genere.

Innanzitutto, definiamo la nostra classe chiamata 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;
  }
}

Supponiamo di voler ascoltare le moneymodifiche, creiamo un'istanza di MonitoredVariablecon soldi iniziali 0:

const money = new MonitoredVariable(0);

Quindi potremmo ottenere o impostare il suo valore usando money.val:

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

Dal momento che non abbiamo definito alcun listener per questo, non succede nulla di speciale dopo le money.valmodifiche a 2.

Ora definiamo alcuni ascoltatori. Abbiamo quattro ascoltatori disponibili: beforeSet, beforeChange, afterChange, afterSet. Quanto segue avverrà in sequenza quando si utilizzamoney.val = newValue per modificare il valore della variabile:

  1. money.beforeSet (newValue, oldValue);
  2. money.beforeChange (newValue, oldValue); (Verrà ignorato se il suo valore non viene modificato)
  3. money.val = newValue;
  4. money.afterChange (newValue, oldValue); (Verrà ignorato se il suo valore non viene modificato)
  5. money.afterSet (newValue, oldValue);

Ora definiamo afterChangelistener che verrà attivato solo dopo che money.valè stato modificato (mentre afterSetverrà attivato anche se il nuovo valore è uguale a quello precedente):

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

Ora imposta un nuovo valore 3e guarda cosa succede:

money.val = 3;

Vedrai quanto segue nella console:

Money has been changed from 2 to 3

Per il codice completo, consultare https://gist.github.com/yusanshi/65745acd23c8587236c50e54f25731ab .


-2

Questo è un vecchio thread ma mi sono imbattuto nella seconda risposta più alta (ascoltatori personalizzati) mentre cercavo una soluzione usando Angular. Mentre la soluzione funziona, angular ha un modo migliore per risolverlo usando@Output emettitori di eventi. Uscendo dall'esempio nella risposta del listener personalizzato:

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

Questo ora verrà aggiornato nsul genitore ogni volta che si fa clic sul pulsante figlio. Stackblitz funzionante


-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]);}
                    });
            }
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.