Прослушивание изменений переменных в JavaScript

462

Возможно ли иметь событие в JS, которое срабатывает при изменении значения определенной переменной? JQuery принимается.

rashcroft22
источник
@BenjaminGruenbaum, вероятно, вы хотите сказать, MutableObserver (для DOM). Объект только для объектов JS из того, что я помню.
HellBaby
2
@ HellBaby, этот вопрос о переменных, а не о DOM.
Бенджамин Грюнбаум
9
@BenjaminGruenbaum в соответствии с developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… Object.observe устарел или устарел. Рекомендуемой заменой (для этой же страницы) является объект Proxy.
Станниус
4
Вопрос только задающий variable, но все ответы здесь относятся property. Интересно, можем ли мы прислушиваться к local variableизменениям?
Тарик Нугрохотомо
1
есть ли ответ на это? Я имею в виду, чтобы выбрать один
Braian Mellor

Ответы:

100

Да, это теперь вполне возможно!

Я знаю, что это старый поток, но теперь этот эффект возможен с использованием методов доступа (геттеры и сеттеры): 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/

Вы также можете использовать массив слушателей вместо одного слота слушателя, но я хотел бы привести вам самый простой пример.

Akira
источник
6
Это тонна кода на объект, есть ли способ сделать это более пригодным для повторного использования?
Ваэль Виктус
Где твой код? Вы начали новый вопрос с этого?
Акира
Как насчет способа обнаружить, когда новое свойство было добавлено к объекту или было удалено?
Майкл
Это старый ответ, но я хотел бы добавить, что это хорошо работает для значений массива, а также до тех пор, пока вы устанавливаете значение массива, а не нажимаете на него.
TabsNotSpaces
1
Вам просто нужно иметь массив слушателей вместо одного, и тогда вместо простого вызова this.aListener(val)вам придется циклически перебирать все функции слушателя и вызывать каждую проходящую функцию val. Как правило, метод вызывается addListenerвместо registerListener.
Акира
75

Большинство ответов на этот вопрос либо устарели, либо неэффективны, либо требуют включения больших раздутых библиотек:

  • Object.watch и Object.observe устарели и не должны использоваться.
  • onPropertyChange - это обработчик событий элемента DOM, который работает только в некоторых версиях IE.
  • Object.defineProperty позволяет вам сделать свойство объекта неизменным, что позволит вам обнаруживать предпринятые изменения, но также будет блокировать любые изменения.
  • Определение сеттеров и геттеров работает, но требует большого количества кода установки и не очень хорошо работает, когда вам нужно удалить или создать новые свойства.

Сегодня вы можете использовать объект Proxy для мониторинга (и перехвата) изменений, внесенных в объект. Он специально создан для того, что пытается сделать ОП. Вот основной пример:

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- это можно сделать с помощью a Proxy, это один из основных вариантов использования прокси.
Эллиот Б.
2
Нет, потому что вы изменяете цель напрямую. Если вы хотите наблюдать за изменением target, то вы должны сделать это через прокси. Однако proxy.hello_world = "test"это не означает, что вы модифицируете прокси, прокси остается неизменным, targetмодифицируется (если ваш установленный обработчик настроен для этого). Похоже, ваша точка зрения в том, что вы не можете наблюдать напрямую target.hello_world = "test". Это правда. Простые присвоения переменных не генерируют никаких событий. Вот почему мы должны использовать инструменты, подобные описанным в ответах на этот вопрос.
Эллиот Б.
2
Спасибо, Эллиот Б. It sounds like your point is that you cannot directly observe target.hello_world = "test". That is true., это точно моя точка зрения. В моем случае у меня есть объект, созданный где-то еще и обновленный каким-то другим кодом ... прокси-сервер в этом случае бесполезен, так как изменения будут внесены в цель.
Криштиану
1
@Cristiano Я думаю, что Эллиот пытается сказать, что вы можете использовать прокси вместо реального объекта, то есть вы можете передавать прокси, как если бы это был ваш объект, и заставить другие части приложения взаимодействовать с вашим прокси. Изменения в прокси будут отражены на реальном объекте.
Золтан Маток
33

Нет.

Но, если это действительно так важно, у вас есть 2 варианта (первый проверен, второй нет):

Во-первых, используйте сеттеры и геттеры, вот так:

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
«наблюдение» на самом деле не обнаруживает изменения. Это не основано на событиях, и, конечно, очень скоро замедлит работу всего приложения. Эти подходы ИМХО никогда не должны быть частью реального проекта.
Мухаммед бин Юсрат
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требует 2 аргумента, но часть вашего примера показывает, что функция вызывается только с параметром value.
Хлавулека МАС
22

Извините, что поднял старую ветку, но вот небольшое руководство для тех, кто (как и я!) Не видит, как работает пример Эли Грея:

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

Надеюсь, что это может помочь кому-то

JavaScript это будущее
источник
9
Часы не поддерживаются в Chrome или Safari на данный момент, только Firefox
Пол МакКлин
5
В сети разработчиков Mozilla это не рекомендуется. Object.prototype.watch () предназначался только для тестирования и не должен использоваться в рабочем коде. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Деннис Бартлетт
4
@PaulMcClean этот ответ был в ответ на ответ Эли Грея, который содержал Polyfill. gist.github.com/eligrey/384583
Hobbyist
2
часы были объявлены устаревшими Mozilla. Этот ответ может вводить в заблуждение.
Арно
7

Как ответ Люка Шефера ( примечание : это относится к его первоначальному сообщению; но весь смысл здесь остается действительным после редактирования ), я бы также предложил пару методов Get / Set для доступа к вашему значению.

Однако я бы предложил некоторые модификации (и именно поэтому я публикую ...).

Проблема с этим кодом заключается в том, что поле 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);
Бруно Рейс
источник
2
+1 для инкапсуляции. Это была моя первая мысль, но я хотел в конечном итоге добавить метод create_gets_sets, и, поскольку он неразборчив, скрывать значения - это не здорово :), мы можем сделать еще один шаг и написать некоторые вещи, чтобы скрыть значения, но Я думаю, что код, который я выложил, достаточно запутан для большинства людей ... может быть, если его призовут ...
Люк Шафер,
6

Если вы используете jQuery {UI} (который должен использовать каждый :-)), вы можете использовать .change () со скрытым элементом <input />.

Чак Хан
источник
7
Я не совсем понимаю. Как вы можете прикрепить переменную к скрытому <input/>элементу?
Питер Ли
4
Я думаю, что Чак предлагает установить значение ввода с помощью jquery, а затем и прослушивателя событий .change (). Если вы обновите значение ввода с помощью .val (), то сработает обратный вызов события .change ().
Jarederaj
2
<input type="hidden" value="" id="thisOne" />и с JQuery, $("#thisOne").change(function() { do stuff here });а $("#thisOne").val(myVariableWhichIsNew);затем .change()будет стрелять.
Хаверим
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');
Том Уокер
2
Для тех, у кого такая же проблема, как и у меня, если событие изменения не вызывает, попробуйте $ ("# thisOne"). Val (myVariableWhichIsNew) .trigger ('change'). Надеюсь, это поможет
Alator
6

AngularJS(Я знаю, что это не так JQuery, но это может помочь. [Чистый JS хорош только в теории]):

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

где «данные» - это имя вашей переменной в области видимости.

Есть ссылка на док.

сес
источник
К сожалению, это заставляет вас связывать переменную с областью действия
ruX
он запускается только при $scope.$apply()запуске
iamawebgeek
5

Для тех, кто занимается тюнингом через пару лет:

Доступно решение для большинства браузеров (и IE6 +), которое использует событие onpropertychange и более новую спецификацию defineProperty. Небольшая проблема в том, что вам нужно сделать вашу переменную объектом dom.

Полная информация:

http://johndyer.name/native-browser-get-set-properties-in-javascript/

MandoMando
источник
3

Функциональность, которую вы ищете, может быть достигнута с помощью метода defineProperty (), который доступен только для современных браузеров:

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

Я написал расширение jQuery, которое имеет некоторые аналогичные функциональные возможности, если вам нужна дополнительная кросс-браузерная поддержка:

https://github.com/jarederaj/jQueue

Небольшое расширение jQuery, которое обрабатывает обратные вызовы в очереди на существование переменной, объекта или ключа. Вы можете назначить любое количество обратных вызовов любому количеству точек данных, на которые могут повлиять процессы, выполняющиеся в фоновом режиме. jQueue прослушивает и ожидает появления указанных вами данных, а затем запускает правильный обратный вызов со своими аргументами.

jarederaj
источник
2

Не напрямую: вам нужна пара getter / setter с интерфейсом «addListener / removeListener» или плагин NPAPI (но это совсем другая история).

jldupont
источник
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 ... просто мысль.

markvgti
источник
Для переменной, которая не является свойством объекта, можно получить доступ - как в случае с переменными, объявленными varв модулях ES6 - это единственное решение.
атп
1

Пожалуйста, ребята, помните, что первоначальный вопрос был для ПЕРЕМЕННЫХ, а не для ОБЪЕКТОВ;)

в дополнение ко всем ответам выше я создал крошечную библиотеку forTheWatch.js , которая использует тот же способ для отлова и обратного вызова для изменений в обычных глобальных переменных в javascript.

Совместим с переменными JQUERY, нет необходимости использовать OBJECTS, и вы можете при необходимости напрямую передавать массив из нескольких переменных.

Если это может быть полезно ...: 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.valизменений в 2.

Теперь давайте определимся с некоторыми слушателями. У нас есть четыре слушателей доступны: 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.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 .

yusanshi
источник
-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родительский элемент при каждом нажатии дочерней кнопки. Рабочий стекблиц

TabsNotSpaces
источник
-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]);}
                    });
            }
Аватар
источник