Comment: What is the most important problem to solve in modern JavaScript framework? This article is a good explanation of the problem.
I've seen a lot of people blindly use modern frameworks like React,angular or vue.js. These frameworks provide a lot of interesting things, and often people overlook the main reasons why these frameworks exist, and these are not:
- They are based on components;
- They have a strong community;
- They have many third-party libraries;
- They have many useful third-party components;
- They have browser plugins that can help with debugging;
- They apply to single-page applications.
These are not the most essential reasons, the most essential reason is to keep the UI and state synchronization is not easy.
What is the difficulty of UI and state synchronization?
If you are building a WEB application, users can start an invitation by filling in someone else's email address. And the invitation list has two states:
- Empty state, we prompt the user to fill in the mailbox in this state.
- Non-empty state, this state we need to list the users waiting to be invited, and provide the delete button.
Try using pure JavaScript for this functionality
Source code and effects can be referred to: Codepen.
Index.html Code
JS Code
' Class AddressList {
Constructor (Root) {
State variables
This.state = []
// UI variablesthis.root = rootthis.form = root.querySelector(‘form‘)this.input = this.form.querySelector(‘input‘)this.help = this.form.querySelector(‘.help‘)this.ul = root.querySelector(‘ul‘)this.items = {} // id -> li element// event handlersthis.form.addEventListener(‘submit‘, e => { e.preventDefault() const address = this.input.value this.input.value = ‘‘ this.addAddress(address)})this.ul.addEventListener(‘click‘, e => { const id = e.target.getAttribute(‘data-delete-id‘) if (!id) return // user clicked in something else this.removeAddress(id)})
}
AddAddress (address) {
State logic
Const ID = String (date.now ())
This.state = This.state.concat ({address, id})
// UI logicthis.updateHelp()const li = document.createElement(‘li‘)const span = document.createElement(‘span‘)const del = document.createElement(‘a‘)span.innerText = addressdel.innerText = ‘delete‘del.setAttribute(‘data-delete-id‘, id)this.ul.appendChild(li)li.appendChild(del)li.appendChild(span)this.items[id] = li
}
Removeaddress (ID) {
State logic
This.state = this.state.filter (item = item.id!== ID)
// UI logicthis.updateHelp()const li = this.items[id]this.ul.removeChild(li)
}
Utility method
Updatehelp () {
if (This.state.length > 0) {
This.help.classList.add (' hidden ')
} else {
This.help.classList.remove (' hidden ')
}
}
}
Const ROOT = document.getElementById (' AddressList ')
New AddressList (Root) '
This code is a good illustration of the amount of work required to implement a somewhat small, complex UI with pure JavaScript.
In the example, the static structure is created in HTML, and dynamic content is created using JavaScript. There are several problems with this approach:
The JavaScript code that builds the UI is not very readable, and we use two different parts to define the UI. We can use innerHTML to make the code more readable, but this is inefficient and prone to cross-site scripting vulnerabilities. We can also use the template engine, but if you regenerate the child nodes of the large DOM, you will encounter two more problems: inefficient, you will often need to reconnect the event handler.
But this is all a small problem, the main problem is: We need to update the UI when the state changes. Every time the state changes we all need to use a lot of code to update the UI. In the above example, we are updating the state with two lines of code, but updating the UI consumes 13 lines of code (although the UI is not complicated).
It is not only complex to write, but also fragile. Imagine that we need to implement the ability to synchronize the list to the server. We need to compare the local data with the data sent by the server. And a point-to-point pair is required to synchronize each change to the DOM node. If there are errors at each step in the process, the UI synchronization fails directly.
Therefore, maintaining UI and data synchronization requires writing a lot of tedious, fragile, and fragile code.
Declarative UI Solutions
It's not a community, it's not a tool, it's not an ecosystem, it's not a third-party library ...
So far, the biggest improvements these frameworks have provided are implementation state and UI synchronization.
We just need to define the UI once and not write the UI for each action. The same state always gets the same UI output (State and UI synchronization, which automatically updates the UI after a state change).
Principle
There are two basic strategies:
- Re-render the entire component: React. When a component's state sends a change, it renders a DOM in memory and compares it to the existing DOM. But to reduce costs, it actually renders a virtual DOM to compare to the previous virtual DOM, then calculates the changes and modifies the real DOM.
- Use observers to listen for changes: Angular and Vue.js observe your state changes, and only the associated DOM elements are updated.
Compare with Web Component?
Many times people compare react,angular and vue.js with WEB components. Many people do not understand the greatest benefit these frameworks offer: keeping the UI and state in sync. While the Web component does not provide content, it is a set of specifications so that developers can freely create reusable elements. So simply using Web Component + pure JavaScript still requires manual state synchronization, and a modern JavaScript framework is required to achieve an efficient and maintainable UI.
Own implementation
To achieve a similar function, you can deepen the understanding of the principle. We tried to rewrite the demo just by using the virtual DOM (rather than using a third-party framework) to implement a React-like framework.
Here is the core part of our Framework, which represents the base class for all components:
Here is the app for mailbox invitations based on the Component rewrite (with the Babel transform to support JSX) here is the source:
The UI is now declarative, and we don't use any frameworks directly. We can implement the logic of changing the state in any way, and do not require additional code to write UI synchronization.
Original: The deepest reason why modern JavaScript frameworks exist
The main reason for the existence of modern JavaScript frameworks