What do you think of homemade frames
In the ancient days of the front end, there were many front-end frameworks, such as Knockout, Backone, extJS… Have been used by numerous users. However, because at that time or JSP, PHP, ASP and other back-end rendering architecture as the mainstream, in fact, the vast majority of applications are still in the form of jquery + control library development. Back then, front-end developers were more interested in the challenge of using JS + CSS to create cool animations on the constrained platform of the browser than framework development.
A few years ago, the widespread use of Ajax became the key to the change in the front-end ecology, and the framework wars of this generation have begun. Various responsive frameworks are emerging. The result, the convergence of the three frameworks, is well known.
The three frameworks are now deeply rooted in the hearts of each present and each front end. Today, a front end that doesn’t know how the three frameworks work is too embarrassed to greet people on a forum. And the echo is, if a man says he made a front frame, will usher in the soul of the three people ask, “can you do by the three frameworks, please” “do you have any ecological do this”? “, “who will use your framework will eventually received the evaluation made wheels” repeat “, while his framework “is just a toy, does not make sense.
Why design a front-end frame by hand
For most people, programming is nothing more than writing a program to make a machine run. Machines only need instructions to run, so why do programmers need frameworks to write code? The answer is “high efficiency with frame”. “Why is development written in frameworks efficient?” “Less code,” followed by “responsive,” “functional,” and so on. If you look at frames from this perspective, there is no need to make your own frames. Business development is not as efficient as the existing mature framework, and without all the cloudy probabilities, the framework loses its meaning.
Machines are good at following instructions, people are not good at this, most programmers must have experienced the pain of breakpoints. Humans are good at solving complex problems in abstract ways, but machines are not. The code is written by a human, but executed by a machine. How to write code becomes a contradiction. Today’s various operating systems, programming languages, design patterns, programming paradigms, and application frameworks are the answer to this question.
If programming describes machine instructions in an appropriate way, then the framework is an abstraction of those instructions. The same rendering view can be viewed as a rendering function composed of multiple component rendering functions, or as a view object composed of multiple component objects that communicate with each other. Different application scenarios, different development habits, different understanding thinking will affect our abstract way. Outside of the three frameworks, we can also try to validate our own abstract approach, where homemade frameworks make sense.
The unification and differentiation of the three frameworks are discussed from the perspective of design
Let’s start with a simple data structure.
export interface Watcher<T> {
emit: (r: Reactive<T>) = > void
}
export class Reactive<T> {
#val: T
#watchers: Watcher<T>[] = []
constructor(val: T) {
this.#val = val
}
getVal() {
return this.#val
}
setVal(newVal: T) {
this.#val = newVal
this.#watchers.forEach(v= > v.emit(this))}attach(watcher: Watcher<T>) {
this.#watchers = this.#watchers.filter(v= >v ! = watcher).concat([watcher]) } }Copy the code
This is a simple Reactive
data, which contains the current real data. When setVal changes, all watcher
is notified to update the data.
If you bind this value to a view, you can express it in code as follows
// <div>{{text}}</div>
class View implements Watcher<string>{
div = document.createElement('div')
constructor(text: Reactive<string>) {
text.detach(this)
this.emit(text)
}
emit(v: Reactive<string>) {
this.div.innerText = v.getVal()
}
}
Copy the code
There is nothing difficult about simply binding a string, but when the bound value is an object, it changes.
<div>
<div>{{val.id}}</div>
<div>{{val.name}}</div>
</div>
Copy the code
The most stupid way to think about val is to think of it as a Reactive object
// <div>
//
{{val.id}}
//
{{val.name}}
// </div>
class View implements Watcher<{id:string.name:string}>{
div = document.createElement('div')
constructor(text: Reactive<{id:string,name:string} >) {
text.detach(this)
this.emit(text)
}
emit(v: Reactive<{id:string,name:string} >) {
this.div.innerHTML = `
<div>${v.getVal().id}</div>
<div>${v.getVal().name}</div>
`}}Copy the code
Another way to do this is to make every property of an object Reactive
// <div>{{text}}</div>
class Div implements Watcher<string>{
div = document.createElement('div')
constructor(text: Reactive<string>) {
text.detach(this)
this.emit(text)
}
emit(v: Reactive<string>) {
this.div.innerText = v.getVal()
}
}
// <div>
//
{{val.id}}
//
{{val.name}}
// </div>
class View implements Watcher<{id:Reactive<string>,name:Reactive<string>}>{
div = document.createElement('div')
constructor(text: Reactive<{
id:Reactive<string>,
name:Reactive<string> >}) {
text.detach(this)
this.emit(text)
}
emit(v: Reactive<{id:Reactive<string>,name:Reactive<string> >}) {
this.div.innerHTML = ' '
const div1 = new Div(v.getVal().id)
const div2 = new Div(v.getVal().name)
this.div.appendChild(div1.div)
this.div.appendChild(div2.div)
}
}
Copy the code
The former renders simply, but the entire view is refreshed as data changes.
Although the latter can accurately update the local view when the data changes, it is difficult to avoid large memory consumption when listening to complex objects by converting all the attributes of the object to Reactive in this recursive way.
I don’t know if that sounds familiar. Isn’t that react and Vue?
Besides these two extreme methods, are there any other methods?
export class Computed<S , T>
extends Reactive<T>
implements Watcher<S>{
#fn: (s: S) = > T
constructor(fn: (s: S) => T, source: Reactive<S>) {
const val = fn(source.getVal());
super(val);
this.#fn = fn
}
emit(source:Reactive<S>) {
const val = this.#fn(source.getVal());
if(val! = =this.getVal()) this.setVal(val)
}
}
Copy the code
Computed,target>
It generates a Reactive
based on a Reactive
On Computed, the entire Reacive<{id:string,name:string}> is converted to a view-related Reacive
// <div>
//
{{val.id}}
//
{{val.name}}
// </div>
class View {
div = document.createElement('div')
constructor(text: Reactive<{id:string,name:string} >) {
this.render(text)
}
render(v: Reactive<{id:string,name:string} >) {
this.div.innerHTML = ' '
const c1 = new Computed((m:{id:string,name:string}) = >m.id,v)
const c2 = new Computed((m:{id:string,name:string}) = >m.id,v)
const div1 = new Div(c1)
const div2 = new Div(c2)
this.div.appendChild(div1.div)
this.div.appendChild(div2.div)
}
}
Copy the code
In this way, only Computed related to the view is recalculated each time the view is updated. If the view changes, the corresponding bound node is updated. If no change is required, the view is not updated.
Eh, isn’t that the logic behind Angular dirty checking?
Nowadays react is associated with “global state”, Vue is associated with “defineProperty/”, and Angular is associated with “dirt checking”. Admittedly, these are the “labels” of each of the three frameworks, but the perception of the framework stays only on these labels, which is not much use except as a conversation piece.
If Reactive is used to unify the thinking of Reactive updating among the three; The three implementations of responsive updates are differentiated by binding to complex objects and views. This way of thinking not only gives you a better understanding of the advantages and disadvantages of the framework implementation, but also gives you a better understanding of the concept of the “front-end framework” itself. As you gain a deeper understanding of the “front-end framework,” it’s natural to want to implement a framework to validate your ideas.
This post is the intro to the next series of “Homemade front-end frameworks” articles, and it’s a poke at the current “front-end framework” discussion.
As for the front-end framework, there is never a lack of tutorials on the use of a function or discussion on its implementation principle, such as “How to develop components with the New feature Hook of React”, “the principle of vUE using Proxy to realize data binding” and so on.
However, in the face of endless new frameworks and new wheels, front-end er’s mentality from novelty to anxiety, whether the industry is developing too fast, or everyone’s understanding of the framework only stays at the tool level?
I just wanted to talk to you.