Apa yang membuat sistem reaktif bagus?

Posting ini adalah yang kedua dari serangkaian artikel tentang pelacakan otomatis - sistem reaktivitas baru di Ember.js. Saya juga membahas konsep reaktivitas secara umum, dan bagaimana ia memanifestasikan dirinya dalam JavaScript.


Dari penerjemah: Chris Garrett - bekerja untuk LinkedIn dan merupakan salah satu kontributor inti kerangka kerja Ember. Dia mengambil bagian aktif dalam menciptakan edisi baru kerangka kerja - Ember Octane . Salah satu landasan edisi ini adalah sistem reaktivitas baru berdasarkan pelacakan otomatis (autotracking). Terlepas dari kenyataan bahwa seri-nya ditulis untuk pengembang Ember, itu menyentuh konsep-konsep yang berguna untuk diketahui oleh semua programmer web.


  1. Apa itu reaktivitas?
  2. Apa yang membuat sistem reaktif bagus? ← Posting ini
  3. Cara kerja pelacakan otomatis
  4. Tempat Pelacakan Otomatis - TrackedMap
  5. Kasing untuk pelacakan otomatis - @localCopy
  6. Tempat Pelacakan Otomatis - RemoteData
  7. Kasus untuk pelacakan otomatis - efek ()

, . , :


: , .

, , . : ?


, , . . , , . , , .


, , . , , . ! , , - ( ).


HTML


HTML . , , . HTML ( CSS) , - JavaScript!


-, HTML ? ? HTML :


<form action="/my-handling-form-page" method="post">
  <label>
    Email:
    <input type="email" />
  </label>

  <label>
    Password:
    <input type="password" />
  </label>

  <button type="submit">Log in</button>
</form>

. . β€” , , - . , , .


​​ : , , , . HTML , , , β€” (JavaScript). , HTML ? , HTML ?


HTML, input select. , , , . , , .


<style>
  input[type='checkbox'] + ul {
    display: none;
  }

  input[type='checkbox']:checked + ul {
    display: inherit;
  }
</style>

<nav>
  <ul>
    <li>
      <label for="dropdown">Dropdown</label>
      <input id="dropdown" type="checkbox" />
      <ul>
        <li>Item 1</li>
        <li>Item 2</li>
      </ul>
    </li>
  </ul>
</nav>

β€” Β« , CSSΒ». . ./index.html - HTML / CSS .


HTML (, checked ). HTML- , . , , :


1. , , ,

, , HTML- . - , 10 , , .


. - . , JS .


push


push. , , . , JavaScript, .


. , , , , , - . , - <edit-word> :


customElements.define('edit-word',
  class extends HTMLElement {
    constructor() {
      super();

      const shadowRoot = this.attachShadow({mode: 'open'});
      this.form = document.createElement('form');
      this.input = document.createElement('input');
      this.span = document.createElement('span');

      shadowRoot.appendChild(this.form);
      shadowRoot.appendChild(this.span);

      this.isEditing = false;
      this.input.value = this.textContent;

      this.form.appendChild(this.input);

      this.addEventListener('click', () => {
        this.isEditing = true;
        this.updateDisplay();
      });

      this.form.addEventListener('submit', e => {
        this.isEditing = false;
        this.updateDisplay();
        e.preventDefault();
      });

      this.input.addEventListener('blur', () => {
        this.isEditing = false;
        this.updateDisplay();
      });

      this.updateDisplay()
    }

    updateDisplay() {
      if (this.isEditing) {
        this.span.style.display = 'none';
        this.form.style.display = 'inline-block';
        this.input.focus();
        this.input.setSelectionRange(0, this.input.value.length)
      } else {
        this.span.style.display = 'inline-block';
        this.form.style.display = 'none';
        this.span.textContent = this.input.value;
        this.input.style.width = this.span.clientWidth + 'px';
      }
    }
  }
);

- , . isEditing, updateDisplay span form . , . , updateDisplay .


, , isEditing . , . :


2.

isEditing , . , , β€” .


, , .


Ember


Ember Classic push. (observers) (evert listeners) , , , . , (binding), (dependency chaining), .


fullName:


import { computed, set } from '@ember/object';

class Person {
  firstName = 'Liz';
  lastName = 'Hewell';

  @computed('firstName', 'lastName')
  get fullName() {
    return `${this.firstName} ${this.lastName}`;
  }
}

let liz = new Person();

console.log(liz.fullName); 'Liz Hewell';

set(liz, 'firstName', 'Elizabeth');

console.log(liz.fullName); 'Elizabeth Hewell';

Classic Ember . , , , Ember . , set(), .



, (observers) , (computed) (templates) . , , , . ( ) .


Ember , , . . , - . , , . - () β€” , , .


, , , . , , . , , .


Observables, Streams Rx.js


push, , β€” Observable. JavaScript RxJS Angular .


, . , , , .


//  JS
let count = 0;
document.addEventListener(
  'click',
  () => console.log(`Clicked ${++count} times`)
);

//   (Streams)
import { fromEvent } from 'rxjs';
import { scan } from 'rxjs/operators';

fromEvent(document, 'click')
  .pipe(scan(count => count + 1, 0))
  .subscribe(count => console.log(`Clicked ${count} times`));

Ember, β€” , . , , .


, . , , , . , .



, (debounce), , . :


3.

, . , , . , , , , .


, , push, . (lazy) , , , Ember Classic, . , , push, , .


, , . pull.


pull


, , pull, β€” . , , . , , , - , . , , , .


, , pull. , , . , .


, pull , . , Β«Virtual DOMΒ».


React VirtualDOM


Virtual DOM, , React.js . , HTML . , , , HTML, React , , HTML.


HTML-. , . -.



, React, , - . , setState API ( useState ).


class Toggle extends React.Component {
  state = { isToggleOn: true };

  handleClick = () => {
    this.setState(state => ({
      isToggleOn: !state.isToggleOn
    }));
  }

  render() {
    return (
      <button onClick={this.handleClick}>
        {this.state.isToggleOn ? 'ON' : 'OFF'}
      </button>
    );
  }
}

, ( ) .



, (consistency), , setState useState . , ( ). - React , :


4.

React , , . , React :


class Example extends React.Component {
  state = {
    value: 123;
  };

  render() {
    let part1 = <div>{this.state.value}</div>

    this.setState({ value: 456 });

    let part2 = <div>{this.state.value}</div>

    return (
      <div>
        {part1}
        {part2}
      </div>
    );
  }
}

, , part1 , part2 . , , - , . , , . React , .


, React , . API, shouldComponentUpdate() useMemo(), React .


API , ​​ . , .


Vue:


Vue Virtual DOM, . Vue data :


const vm = new Vue({
  data: {
    a: 1
  }
});

Vue setState useState ( , API), . data , , . observables.


, :


const vm = new Vue({
  el: '#example',

  data: {
    message: 'Hello'
  },

  computed: {
    reversedMessage() {
      return this.message.split('').reverse().join('')
    }
  }
})

reversedMessage message , message .


Vue , React, . , (memoization) , - , . push, , .


Elm


, , JavaScript. , , (autotracking) , , - .


Elm β€” , . , ( HTML + JS). , - .


, Elm - , . , Elm .



- Elm , (memoization). , . / , .


//     JS
let lastArgs;
let lastResult;

function memoizedRender(...args) {
  if (deepEqual(lastArgs, args)) {
    // Args
    return lastResult;
  }

  lastResult = render(...args);
  lastArgs = args;

  return lastResult;
}

«» , , Elm .


. , HTML , React / Vue / Virtual DOM.


, , , . Elm, , - .


, Elm JavaScript . JavaScript, , . , . Redux β€” , , .


, , β€” , , . , .


!



, , :


  • HTML / CSS
  • push
  • JavaScript
    β€” Ember
    β€” Observables / Rx.js
  • pull
    β€” React.js
    β€” Vue.js
    β€” Elm

:


  1. , , ,
  2. Membaca keadaan dalam sistem mengarah ke keadaan turunan reaktif
  3. Sistem meminimalkan pekerjaan yang tidak perlu secara default
  4. Sistem mencegah status turunan yang saling bertentangan

Saya tidak mengklaim bahwa daftar ini lengkap, tetapi mencakup banyak hal yang membuat sistem reaktif dapat diandalkan dan dapat digunakan. Pada posting berikutnya, kita akan mempelajari pelacakan otomatis dan mencari tahu bagaimana penerapan prinsip-prinsip ini.


All Articles