V-ați întrebat vreodată cum funcționează un cadru?

Când am descoperit AngularJS după învățare jQuery acum mulți ani, AngularJS mi se părea magie întunecată.

Apoi Vue.js a ieșit și, după ce am analizat cum funcționează sub capotă, am fost încurajat să încerc să scriu propriile mele sistem de legare bidirecțională.

În acest articol, vă voi arăta cum să scrieți un cadru JavaScript modern cu atribute de element HTML personalizate, reactivitate și dublă legare.

Cum funcționează reactivitatea?

Ar fi bine să începem cu o înțelegere a modului în care funcționează reactivitatea. Vestea bună este că acest lucru este simplu. De fapt, atunci când declarați o componentă nouă în Vue.js, cadrul va fi proxify fiecare proprietate (getters și seters) folosind model de proiectare proxy.

Astfel, va fi capabil să detecteze modificările valorii proprietății atât din cod, cât și din intrările utilizatorului.

Cum arată modelul de proiectare proxy

Ideea din spatele modelului proxy este pur și simplu să supraîncărcați accesul la un obiect. O analogie în viața reală ar putea fi accesul la contul dvs. bancar.

De exemplu, nu puteți accesa direct soldul contului dvs. bancar și nu puteți modifica valoarea în funcție de nevoile dvs. Este necesar să întrebați pe cineva care are această permisiune, în acest caz, banca dvs.

var account = {
	balance: 5000
}

// A bank acts like a proxy between your bank account and you
var bank = new Proxy(account, {
    get: function (target, prop) {
    	return 9000000;
    }
});

console.log(account.balance); // 5,000 (your real balance)
console.log(bank.balance);    // 9,000,000 (the bank is lying)
console.log(bank.currency);   // 9,000,000 (the bank is doing anything)

În exemplul de mai sus, când utilizați bank obiect pentru a accesa account echilibru, funcția getter este supraîncărcată și revine întotdeauna 9,000,000 în loc de valoarea proprietății, chiar dacă proprietatea nu există.

// Overload setter default function
var bank = new Proxy(account, {
    set: function (target, prop, value) {
        // Always set property value to 0
        return Reflect.set(target, prop, 0); 
    }
});

account.balance = 5800;
console.log(account.balance); // 5,800

bank.balance = 5400;
console.log(account.balance); // 0 (the bank is doing anything)

Prin supraîncărcare set funcție, este posibil să-i manipulăm comportamentul. Puteți modifica valoarea pentru a seta, actualiza o altă proprietate sau chiar să nu faceți deloc.

Exemplu de reactivitate

Acum, că aveți încredere în modul în care funcționează modelul de proiectare proxy, să începem să scriem cadrul nostru JavaScript.

Pentru a fi simplă, vom imita sintaxa AngularJS pentru ao face. Declararea unui controler și legarea elementelor șablonului la proprietățile controlerului este destul de simplă.

<div ng-controller="InputController">
    <!-- "Hello World!" -->
    <input ng-bind="message"/>   
    <input ng-bind="message"/>
</div>

<script type="javascript">
  function InputController () {
      this.message="Hello World!";
  }
  angular.controller('InputController', InputController);
</script>

Mai întâi, definiți un controler cu proprietăți. Apoi utilizați acest controler într-un șablon. În cele din urmă, utilizați ng-bind atribut pentru a activa legarea dublă cu valoarea elementului.

Analizați șablonul și instanțiați controlerul

Pentru a avea proprietăți de legat, trebuie să obținem un loc (aka controler) pentru a declara acele proprietăți. Astfel, este necesar să definim un controler și să îl introducem în cadrul nostru.

În timpul declarației controlerului, cadrul va căuta elemente care au ng-controller atribute.

Dacă se potrivește cu unul dintre controlerele declarate, va crea o nouă instanță a acestui controler. Această instanță a controlorului este responsabilă numai pentru această piesă specială de șablon.

var controllers = {};
var addController = function (name, constructor) {
    // Store controller constructor
    controllers[name] = {
        factory: constructor,
        instances: []
    };
    
    // Look for elements using the controller
    var element = document.querySelector('[ng-controller=" + name + "]');
    if (!element){
       return; // No element uses this controller
    }
    
    // Create a new instance and save it
    var ctrl = new controllers[name].factory;
    controllers[name].instances.push(ctrl);
    
    // Look for bindings.....
};

addController('InputController', InputController);

Iată ce este realizat manual controllers declarația variabilă arată. controllers obiect conține toți controlorii declarați în cadru prin apelare addController.

Cum sa va imbunatatiti abilitatile JavaScript prin scrierea propriului cadru
Definiție controlere handmade

Pentru fiecare controler, a factory funcția este salvată pentru a crea un nou controler atunci când este necesar. Cadrul stochează, de asemenea, fiecare dintre noile instanțe ale aceluiași controler utilizat în șablon.

Caută legături

În acest moment, avem o instanță a controlerului și o bucată de șablon care utilizează această instanță.

Următorul pas este să căutați elemente cu legături care utilizează proprietăți de controler.

var bindings = {};

// Note: element is the dom element using the controller
Array.prototype.slice.call(element.querySelectorAll('[ng-bind]'))
    .map(function (element) {
        var boundValue = element.getAttribute('ng-bind');

        if(!bindings[boundValue]) {
            bindings[boundValue] = {
                boundValue: boundValue,
                elements: []
            }
        }

        bindings[boundValue].elements.push(element);
    });

Destul de simplu, stochează toate legăturile unui obiect (folosit ca harta hash). Această variabilă conține toate proprietățile de legat cu valoarea curentă și toate elementele DOM care leagă această proprietate.

1611438786 681 Cum sa va imbunatatiti abilitatile JavaScript prin scrierea propriului cadru
Declarație manuală de legături

Proprietățile controlerului de legare dublă

După ce lucrările preliminare au fost realizate de cadru, acum vine partea interesantă: dublă legare.

Aceasta implică legarea proprietății controlerului de elementele DOM pentru a actualiza DOM ori de câte ori codul actualizează valoarea proprietății.

De asemenea, nu uitați să legați elementele DOM de proprietatea controlerului. În acest fel, când utilizatorul modifică valoarea de intrare, va actualiza proprietatea controlerului. Apoi, va actualiza, de asemenea, toate celelalte elemente legate de această proprietate.

Detectați actualizări din cod cu un proxy

După cum sa explicat mai sus, Vue împachetează componentele dintr-un proxy pentru a reacționa la modificările proprietății. Să facem același lucru proxy setter numai pentru proprietăți legate de controler.

// Note: ctrl is the controller instance
var proxy = new Proxy(ctrl, {
    set: function (target, prop, value) {
        var bind = bindings[prop];
        if(bind) {
            // Update each DOM element bound to the property  
            bind.elements.forEach(function (element) {
                element.value = value;
                element.setAttribute('value', value);
            });
        }
        return Reflect.set(target, prop, value);
    }
});

Ori de câte ori este setată o proprietate legată, proxy-ul va verifica toate elementele legate de această proprietate. Apoi le va actualiza cu noua valoare.

În acest exemplu, acceptăm numai intrare elemente obligatorii, deoarece doar value atributul este setat.

Reacționează la evenimentele elementare

Ultimul lucru de făcut este să reacționezi la interacțiunile utilizatorilor. Elementele DOM declanșează evenimente atunci când detectează o modificare a valorii.

Ascultați acele evenimente și actualizați proprietatea legată cu noua valoare din eveniment. Toate celelalte elemente legate de aceeași proprietate se vor actualiza automat datorită proxy-ului.

Object.keys(bindings).forEach(function (boundValue) {
  var bind = bindings[boundValue];
  
  // Listen elements event and update proxy property   
  bind.elements.forEach(function (element) {
    element.addEventListener('input', function (event) {
      proxy[bind.boundValue] = event.target.value; // Also triggers the proxy setter
    });
  })  
});

Odată ce ați pus totul laolaltă, veți obține intrări manuale cu legătură dublă. Iată o demonstrație de lucru care include tot codul.

Mulțumesc că ai citit. Sper că v-a ajutat să demistați cum funcționează cadrele JavaScript.

Felicitări! Ați dezvoltat caracteristici populare, cum ar fi atributele elementelor HTML personalizate, reactivitatea și legarea dublă!

Dacă ați găsit util acest articol, vă rugăm să faceți clic pe ? apăsați de câteva ori pentru a-i face pe alții să găsească articolul și pentru a vă arăta sprijinul! ?

Nu uitați să mă urmăriți pentru a primi notificări despre articolele mele viitoare ?

https://www.freecodecamp.org/news/author/jbardon/

➥ Reacționează pentru începători

➥ JavaScript