JSFiddle - React, Tailwind, and code Playground

by Hellfrom

JavaScript

//скопы создаются с помощью scope конструктора
function Scope(){
    this.$$watchers = [];
    this.$$asyncQueue = []; //задачи, которые нужно будет выполнить когда-то
    this.$$postDigestQueue = []; //задачи, которые выполнятся после $digest, но не запустят $digest()
    this.$$phase = null; // фаза $digest цикла
};

//ф-ия принимает ф-ию наблюдения и ф-ию callback
Scope.prototype.$watch = function (watchFn, listenerFn, valueEq){
    var watcher = {
        watchFn : watchFn,
        listenerFn : listenerFn||function (){},
        valueEq : !!valueEq //если указан 3-й параметр будет глубокое сравнение
    };
    this.$$watchers.push(watcher);
};

//цикл обхода всех наблюдателей 1 раз
Scope.prototype.$$digestOnce = function (){
    var self = this;
    var dirty; //был ли изменёно что-то
    _.forEach(this.$$watchers,function (watch){
        try{
            //запускаем наблюдатель
            var newValue = watch.watchFn(self);
            var oldValue = watch.last;
            //если предыдущее возвращаемое наблюдателем значение не равно новому запустить callback
            //if(newValue !== oldValue){ //сравнивает строки
            if (!self.$$areEqual(newValue, oldValue, watch.valueEq)) {
                 watch.listenerFn(newValue, oldValue, self);    //self == scope
                //если хоть в каком-то наблюдателе изменилось значение return
                dirty = true; //возвращаем маркер - изменение
                watch.last = newValue;
            }
        }catch(e){
            (console.error||console.log)(e);
        }
    });
    return dirty;
};

Scope.prototype.$digest = function (){
    var dirty;
    var ttl = 10; //количество допустимых мутаций (Time To Live)
    this.$beginPhase("$digest");
    do{
        //реализуем все отложенные ф-ии
        while(this.$$asyncQueue.length){
            try{
                var asyncTask = this.$$asyncQueue.shift();
                this.$eval(asyncTask.expression);
            }catch(e){
              ...