Background:

The UI evolution

After MVC, after more than ten years of development, in the 1990s, there was a COMPANY’S CTO named Mike, who proposed MVP based on MVC.

Then in 2005, an architect at Microsoft came up with the MVVM pattern. Around 2014, FLUX came along, a mode that Facebook proposed for its JSX and React.

A year later, in 2015, REDUX appeared in the React community.

For the front end, we create value for users is a special need to pay attention to the problem, so many years have passed, what value has the front end created for users?

Back in the ’90s, when it was amazing, the buttons were three-dimensional. Now this thing is a little bit less aesthetically pleasing.

Around 2006, Vista’s interface began to undergo a major change, with designers taking the lead on the interface, but performance was poor.

Then, mobile phones appeared, such as the interface of iPhone. At this time, not only the interaction mode changed greatly, but also the screen changed. Even the familiar mouse disappeared and became a touch screen. Although there are some operational similarities between the two, the variation is very large.

view

We use computers today to surf the Internet, and basically, everyone’s computer is connected 24 hours a day, your phone is connected 24 hours a day, so the responsibilities of computers are changing.

This change has a great impact on UI. In the MVC paper in 1970, the model was very large and the view was very small. However, in 2018, most of our models are placed on the server side. You have a local view that just shows a little bit of the model, this is a very small part of the thing. And this part right here, maybe it’s views at different terminals, and the views are getting bigger and bigger.

Question:

Views are becoming more important, richer, and more technically complex. A page, there may be a navigation head, round broadcast graph, scrolling animation, a variety of gesture interaction, information flow and other interactions with the back end.

We often divided by natural duty write interactions in the generation of JS file and layout are written in HTML, style to write inside the CSS, when the target page content rarely, looks no problem, but when the target page becomes complicated enough, we will find that the inside of the JS logic code is becoming more and more if a gesture interaction, Having to trigger page loads, scrolling animations, and navigation changes at the same time is a very complicated situation for developers to deal with. At this point, if another person takes over the project, or a new interaction is added to trigger more linkage. It can be very painful.

This is because most of the time, at the beginning of the project demand is not much, so I will make the whole piece of application, a page and then as the growth of the business or alteration, the complexity of the project rich will show exponential growth, projects such as complicated enough, a tiny change occurs or a function of increasing may cause the changes of the overall logic, Cause a situation affecting the whole body.

Goal:

So how to solve this situation:

In fact, the industry has been exploring for a long time, if a large and complex scene can be broken down into several small parts, these small parts do not interfere with each other, can be independently developed, independently maintained, and they can be arbitrarily combined. Take the mainframe computer for example, a complete machine includes CPU, motherboard, memory, hard disk and so on, and these parts are actually produced by different companies, they are produced separately according to a set of standards, and finally assembled together. When there is a problem with a part, there is no need to repair the whole machine, just take the bad part down, repair and then put it together. This idea of simplifying complexity is componentized in front-end development, and the back-end is micro services.

With the emergence of React, Vue, Angular and other excellent front-end frameworks based on components (directives, etc.), front-end componentization has gradually become an urgent need for front-end development. Of course, this urgent need has gradually become a mainstream, which not only improves front-end development efficiency, but also reduces maintenance costs. Instead of having to deal with a bunch of complex, hard-to-read code, developers focus on snippets of code that exist as components.

As a front-end developer, how to face the endless front-end frameworks? We need to make good use of abstractions, find out their common ground and basic characteristics, understand their roots, and here is my understanding of componentization.

So what is componentization? How to make components?

componentization

I searched some materials and found that there is no clear definition of componentization, but when it is often mentioned, it is always accompanied by such a sentence, that is: high cohesion inside, low coupling outside.

The internal elements are closely integrated and interdependent with each other.

Minimal contact with other components and simple interfaces. Reusable, can be combined.

This seems like a specification or standard to follow when making components. It’s like we’re going to make the component look like this.

Components are also objects

Object we are familiar with, object is an abstraction of things, its basic features are: properties, methods and inherit.

The component is actually a kind of object specially used to describe the UI structure, of course, it also has the characteristics of the object, properties, methods and inherit, but also because the component is to describe the UI, so the component itself also has its own some characteristics: Attribute, external call registration callback function Event interface, whether to pass config during initialization, component’s own State State and Lisfecycle. To sum it up:

Properties: properties, methods, inherit, attribute: properties, config&& State, Event, Lisfecycle, children,

Let’s take a look at these characteristics:

Attribute vs Property

Property is a kind of Property.

Attribute and Property are often translated as attributes. Here are three examples to analyze the behavior of attributes and properties.

<div class="cls1 cls2"> < / div > < script > var div = document. The getElementByTagName (" div "); div.className // cls1 cls2 </script>Copy the code

The first one is the same: the name is different, attribute is class, property is className.

<a href="//m.taobao.com" ></div> 
<script>
var a = document.getElementByTagName('a'); A.getattribute (' href ') // "//m.taobao.com", Copy the code

The second difference: the values are different.

<input value = "cute"/ > < script > var input = document. The getElementByTagName (" input "); // If the property is not set, the result is attribute input.value // cute input.getAttribute(' value '); // cute input. Value = 'hello'; // Hello input.getAttribute(' value '); // Hello input.getattribute (' value '); // cute </script>Copy the code

The third is different: If the property is not set, the result is an attribute, if the value property is set, the attribute stays the same, the property changes, and the actual effect on the element is that the property takes precedence, looks like attibute once, One-way synchronous property.

The purpose of these three examples is to show that attributes and properties are not exactly different, but two different things. From an HTML perspective, different is the norm, and one is special.

But in React they’re completely constant. React implements attrbuie and property without distinguishing between them.

A data should exist on that feature of the component.

Four scenarios and four characteristics of components are defined here:

  1. Set through Markup
  2. Through JavaScript
  3. Modify it in JavaScript
  4. User input modification

Property: cannot be set through Markup. JS can be set and modified, and user input can be modified or not. Take HTML for example: The value of input can be modified, but nodeName cannot.

Attrubite: Markup and JS can be set. JS can be modified. User input can be modified or not.

State: Can only be changed by the user’s input, which also includes the time. Tag languages cannot change state, nor can JS languages (where JS is the value calling the component’s JS), so state is a very safe thing for components. If you put everything on state, the component can’t be customized externally at all, and the more exposed it is, the more complex the code logic needs to be written.

Config: generally, js is allowed to be set only once in config. There are many components that set property and config to the same, one-time synchronization relationship.

So if a piece of data comes in, where exactly should we store it? So position, for example, if I give it all four negative values at the same time. Is that ok? Of course you can, so it’s convenient when you type in a book, but the person who maintains the code has to write more code to fit the scenario. It’s more of a trade-off in design. There is no right or wrong, only good or bad.

In addition to storage, an important part of a component is Lifecycle

By life cycle, we mean component constructor and destroy.

Constructor -> destroy; destroy; constructor -> destroy; Occasionally we will see the bedore/will destroyed method to perform some task before the component is destroyed.

Now let’s think: what happens between initialization and destruction?

  1. Mount it and display it on the UI.
  2. JS code modification.
  3. User input is modified.

So based on those three things, the component is created and it needs to be mounted on a tree in order for it to be able to say, well, there must be a mount, there must be a mount and then there will be an unmount, and unmount is taking the component off the tree. The JS code is modified to update/render the component, as is the user input.

If you’ve used the React framework, you’ve probably used WillMount/DidMount. One happens before mount and one happens after mount. React or Vue or a new framework comes along. So once you understand the component life cycle this things, even if a new framework, you also won’t think it was an accident, of course, if a component coined a new life cycle, also need not too surprised, does two things, or made it wrong, we can give it a bug, or are we not rigorous analysis, so it is also a good thing, We can improve our knowledge system.

In the face of these endless new frameworks, we need to learn their essential content and logic behind them. For example, frameworks that are very popular in the community (or seemingly stupid designs) have many trade-offs behind them. For example, React uses a render to render the world, even if a small text is changed, It also needs to render all the way through. What about the overhead caused by render? React designed a virtual DOM mechanism. The principle is that while all of these places are updated in the JS code, only that one is actually updated at the native level because it diff in the middle. Once you understand this, you’ll see that the React Virtual DOM is tied to the component lifecycle. So when react is used, few people will listen for willUpdate or didupdate. Because it’s easy to update components just by writing render (because render gets both state and property/attribute), it simplifies the component lifecycle and makes it easy to write, but at the cost of writing a huge virtual DOM system.

Event

Event is usually a mechanism used by components to notify JS code. In terms of performance, it is usually through onClick or onEvent. JS code registers the callback function first and executes it when the component is triggered internally.

Children

According to the usage scenario of the component, the children to be taken over are also different, which can be divided into Content children and Template children Content.

<component-form>
    <input /> //children
</component-form>
Copy the code

Content, the component will handle the external element or the component as the children of the component.

<component-carousel data={['src1'.'src2']} >
    <div>  <img src={' '} /> </div>
</component-carousel>
Copy the code

Template, the component defines the Template internally and takes an external argument to create children.

Inside the component, different types of children should be treated differently, which requires the designer to consider what the mode of children is according to the application scenarios of the component, because this will affect the implementation of the component.

Take a look at the React implementation of the component

import React from 'react'

export default class Demo extends React.Component{
    constructor(props){
        super(props);
        this.state = {
            name: 'demo'}}componentDidMount(){
    }
    componentWillReceiveProps(){
    }
    componentWillUnmount(){
    }
    render(){
        const = { text } = this.props;
        return(
            <div>{text}</div>
            )
    }
}

/* html */
<Demo text="componet"/> <p> This is a p</p>Copy the code

First, we need to create a Demo component class that inherits react.componentto create the component. Second, you need to write a render function that returns the UI element of the component’s core, and you can see its trade-off on the lifecycle. Finally, the component is invoked using Matkup Code.

React implements the component life cycle well. Config, State and prop integrate the basic features of attribute, property, children and so on, and introduce JSX to invoke components in the way of Markup Code. Users can easily customize their own fragmented component requirements. Of course, you can also set up a set of component implementation. This is just a reference.

Let’s look at the Web Component:

<! DOCTYPE html> <html> <body> <! > <template id="compont-t">
        <style>
            p {
                background-color: brown;
                color: cornsilk
            }
            div {
                width: 200px;
                background-color: bisque;
                border: 3px solid chocolate;
                border-radius: 10px;
            }
        </style>
        <div>
            <p>component</p>
        </div>
        <script>
            function foo() {
                console.log('inner log')
            }
        </script>
    </template>
    <script>
        class Demo extends HTMLElement {
            constructor() {super() // Get component template const Content = document.querySelector()'#compont-t'Const shadowDOM = this.attachShadow({mode: attachShadow).content // create shadow node const shadowDOM = this.attachshadow ({mode: attachShadow)'open'}) // Add the template to shadowDOM. AppendChild (content.clonenode ()true))
            }
        }
        customElements.define('compoentd-emo'</script> <compoentd-emo>< div> <p> This is a test! </p> </div> <compoentd-emo></compoentd-emo> </body> </html>Copy the code

First, we use the template property to create the template, and second, we need to create a Demo class. There are three things to do in the constructor of this class:

  1. Find template content;
  2. Create shadow DOM;
  3. Add the template to the shadow DOM. Finally, the component is called in the same way as Markup.

There are two main functions of the shadow DOM:

  1. Elements in the shadow DOM are invisible to the entire web page;
  2. The CSS of the shadow DOM does not affect the CSSOM of the entire web page; the CSS inside the shadow DOM only affects the elements inside it.

WebCompoent, this system brings us the biggest benefit is the introduction of the shadow DOM mechanism, in a real sense, realize the component template and CSS style and global DOM isolation encapsulation.

This is because DOM and CSSOM are global, and one thing that can happen is that DOM or CSS styles within a component can affect the outside of the component. To avoid this, we have an implementation like the Shadow DOM, which is a good fit with the idea of componentization.

A componentized page

After componentization, your page might look like this.

<! DOCTYPE html> <html lang="en">
<head>
    <title>Document</title>
</head>
<body>
    <Component1 />
    <Component2 />
    ....
    <ComponentN />
</body>
</html>
Copy the code

Front-end componentization projects

Your project might look like this after componentization.

There are multiple pages within a project, multiple components within a page, and potentially multiple libraries within a component.

conclusion

First understand the development history of the front end, along with the development of the front-end, view have become increasingly large, which is associated with the content of the page is becoming more and more complexity is higher and higher, developers face, want to write more code for the page, often face, difficult to maintain, code reuse, tedious response to the demand.

In order to solve the problems of low development efficiency and high maintenance cost, the idea of front-end componentization is introduced. We want a large and complex scene to be broken down into small parts that don’t interfere with each other, can be developed and maintained separately, and can be combined at will.

The core idea of componentization: internal high cohesion, external low coupling. The internal elements are closely integrated and interdependent with each other. External and other components of the least contact and simple interface, reusable, can be combined.

Following the idea of componentalization, we abstract the features of components: properties, methods, inherit, Attribute, config&& State, Event, Lisfecycle, children and their respective meanings or responsibilities.

In the end, I learned the thoughts and merits of React and WebComponent when they realized their componentization, and the general appearance of a componentized page and a componentized project.