国产av日韩一区二区三区精品,成人性爱视频在线观看,国产,欧美,日韩,一区,www.成色av久久成人,2222eeee成人天堂

Table of Contents
1. Why is componentization so difficult to do?
2. Changes in standards
3. The most fashionable front-end component framework/library at the moment
4. Reusability of front-end components
5. 為什么MVVM是一種很好的選擇
6. 組件的長期積累
7. 我們需要關(guān)注什么
7.1 模塊化
7.2 Web Components
7.3 變更檢測
7.4 Immutable Data
7.6 Promise與異步
7.7 Isomorphic JavaScript
8. Summary
Home Web Front-end HTML Tutorial The road to front-end component framework in 2015_html/css_WEB-ITnose

The road to front-end component framework in 2015_html/css_WEB-ITnose

Jun 24, 2016 am 11:45 AM

https://github.com/xufei/blog/issues/19

1. Why is componentization so difficult to do?

The componentization of web applications is A very complex topic.

In large-scale software, componentization is a consensus, which on the one hand improves development efficiency and on the other hand reduces maintenance costs. However, in the field of Web front-end, there is no very common component model. Because there is a lack of an implementation method that everyone can agree on, many frameworks/libraries have implemented their own componentization methods.

The front-end circle is most enthusiastic about making wheels. No other field can have such a chaotic and prosperous scene. On the one hand, this shows that creativity in the front-end field is very strong, but on the other hand, it shows that the infrastructure is imperfect.

I once had such an analogy to illustrate the several stages of a certain programming technology and its ecological development:

  • In the beginning, people were busy completing various APIs, which meant that they had There is still a shortage of things, and they need to continue to improve the language and infrastructure
  • Then various models started, indicating that the things they made were gradually becoming larger and more complex, and they needed better organization
  • Then there are various types of hierarchical MVC, MVP, MVVM, visual development, automated testing, team collaboration systems, etc., which shows that production efficiency is valued, which is the so-called engineering
  • Then, compare these three Stage, look at the number of people paying attention to these three things, where do you think the Web has developed?

    In terms of details, modularization and componentization standards are about to be implemented on a large scale (regardless of whether they are good or bad), and various APIs are generally available. We finally see hope of taking off. Various frameworks will be launched within a few years. There will be a very powerful shuffling. If the drag of old browsers is not taken into account, this shuffling process will be greatly accelerated before the production capacity of the Web front-end can be released.

    But we must note that many of these standards that are about to be popularized will bring changes to previous work. Comparing it with the development history of the industrial system, the front-end field is currently at a stage before the invention of the steam engine. Early machinery (such as the machine in "Mulan Ci", which mainly has relatively primitive power and materials) has become popular.

    So, from this perspective, many frameworks/libraries will die (specialized in modular AMD and CMD related libraries, some libraries focusing on standardized DOM selectors), and some will have to be Innovation, and some will be less affected (data visualization and other related directions), and can have the opportunity to continue to evolve in their own direction.

    2. Changes in standards

    For this kind of thing, the key to gaining a broad mass base is how well it caters to future standards. Standards that may have a significant impact on front-end programming include:

  • module
  • Web Components
  • class
  • observe
  • promise
  • The problem of module is easy to understand. JavaScript has a module mechanism in the language for the first time, while Web Components agrees on the way to build component libraries based on the pan-HTML system. Class enhances the programming experience, and observe provides An excellent way to separate data and presentation, promise is currently the most popular asynchronous programming method on the front end.

    There are only two things that cannot be bypassed, one is module and the other is Web Components. The former is the basis of modularization, and the latter is the basis of componentization.

    The standardization of modules mainly affects some AMD/CMD loading and related management systems. From this perspective, as @afc163 of the seajs team said, both AMD and CMD are outdated.

    Modularization is relatively easy to migrate. It is basically just pure logic packaging. Compared with AMD or CMD, the packaging form has changed, but componentization is a more difficult problem.

    Web Components provides a recommended way of componentization, specifically:

  • Encapsulate the internal structure of the component through shadow DOM
  • Provide components externally through Custom Element The tags
  • define the HTML template of the component through Template Element
  • control the dependency loading of components through HTML imports
  • These types of things will affect various existing front-end frameworks /library had a huge impact:

  • Due to the emergence of shadow DOM, the internal implementation of components is better hidden and each component is more independent. However, this makes CSS very fragmented, and style frameworks such as LESS and SASS face major challenges.
  • Due to the isolation of components, the complexity of the DOM inside each component is reduced, so selectors can be limited to the components in most cases, and the complexity of conventional selectors is reduced, which will lead to people's distrust of jQuery dependence decreases.
  • Because of the enhanced isolation of components, we are committed to establishing various frameworks/libraries (except Polymer) for front-end component development. In the combination of our own component implementation methods and standard Web Components, between components Unusual challenges have been encountered in issues such as data model synchronization.
  • The use of HTML imports and new component encapsulation methods will cause the previously commonly used JavaScript-based component definition methods to be in an embarrassing situation. Their dependence and loading are facing new challenges, and due to With the weakening of global scope, request merging becomes much more difficult.
  • 3. The most fashionable front-end component framework/library at the moment

    At this point in time in early 2015, there were three frameworks/libraries leading the fashion in the front-end field, namely Angular, Polymer, and React ( Ranking according to the first letter), in this Zhihu article, what are the popular web development technologies at the end of 2014? Here, I have roughly answered some points, and the answers of several other friends are also worth reading. Regarding the detailed analysis of these three, Hou Zhenyu’s article is very good: Where will the front-end framework go in 2015?

    We can see that Polymer has inherent advantages in this regard. Because its core concept is based on Web Components, that is to say, it basically does not consider how to solve current problems and directly focuses on the future as its development direction.

    React’s programming model actually does not need to consider Web standards in particular. Its migration cost is not high. It even shields the UI layer implementation due to its implementation mechanism, so everyone can see its use on native. The use of canvas is very different from the DOM-based programming method, so for it, the compatibility issue of Web Components must be solved when encapsulating tags, which must be encapsulated before anyway.

    The Angular 1.x version, like most frameworks/libraries of the same era, basically did not consider the compatibility of future standards. However, the 2.0 version after redesign has many trade-offs and changes. It becomes a radical change and suddenly becomes something of the future.

    These three things each have their own merits. In the foreseeable few years, they will be three points apart. There may be new frameworks emerging. It is hard to say whether they will be more popular than these.

    In addition, Rob Eisenberg, a member of the original Angular 2.0, created his own new generation framework, aurelia, which will become a strong competitor to Angular 2.0.

    4. Reusability of front-end components

    After looking at some of the existing things, we can roughly discuss some concepts of front-end componentization. Suppose we have some underlying component mechanism, regardless of whether it is native to the browser or a convention implemented by some framework/library, and now we plan to use it to build a large-scale Web application. What should we do?

    The so-called componentization, the core meaning is to extract things that are truly valuable for reuse. So what kind of things have reuse value?

  • Control
  • Basic logic function
  • Public style
  • Stable business logic
  • For the reusability of the control, basically There is no controversy, because this is a real universal function and relatively independent.

    Basic logic functions mainly refer to things that have nothing to do with the interface, such as auxiliary libraries such as underscore, or some pure logic functions such as verification.

    The reusability of public styles is also relatively easy to recognize, so things like bootstrap, foundation, and semantic will also be popular. However, they are not pure style libraries, but also have some small logic encapsulation. .

    The last piece is business logic. There is a lot of controversy over the reuse of this piece. On the one hand, many people do not agree that business logic also needs to be componentized. On the other hand, how to de-componentize this thing also requires thinking.

    In addition to the ones listed above, there are also a large number of business interfaces. Obviously, the reusability of these things is very low, and there is basically no reusability. However, there are still many solutions that use them as "components". ized”, making them “non-reusable components”. Why does this happen?

    The essential purpose of componentization is not necessarily for reusability, but to improve maintainability. This is just like an object-oriented language. Java is purer than C because it does not allow exceptions. Even the main function must be written in a certain class. Therefore, Java is a pure object-oriented language, but C is not.

    In our case, componentization can also be divided into: full componentization and partial componentization. How to understand the difference between these two things? Someone has asked what is the difference between a js framework and a library. Generally speaking, something with a strong agreement is called a framework, while something with a loose agreement is called a library. Many frameworks have a fully componentized concept. For example, ExtJS, which appeared many years ago, is a fully componentized framework, while jQuery and its plug-in system are partially componentized. So when writing something with ExtJS, no matter what you write, the writing method is almost the same. When using jQuery, most of the parts are original HTML. Wherever you need something different, just call the plug-in in that place to make specializations.

    For a web application of a certain scale, "componentizing" everything will bring greater convenience in management. Let me give you an example. When writing code, short codes are obviously more readable than long codes. Therefore, many languages ????will recommend that "a method should generally not exceed a certain number of lines, and a class should not exceed a certain number of lines." In the Web front-end system, JavaScript is relatively well done. Nowadays, entry-level people rarely write a bunch of js together. CSS, under the guidance of frameworks such as SASS and LESS, has recently been gradually developing towards modularity. Otherwise, it would be very painful to write bootstrap-like CSS directly.

    At this time, let’s look at the HTML part. If we don’t consider the use of technologies such as templates, some interface layout codes will be very much to write. For example, some forms need to be layered one after another, which is a lot Simple form elements require about three layers, not to mention things with complex layouts. Especially after the entire system is single-page, the header, footer, various nav or aside of the interface are likely to have a certain degree of complexity. If the code of these things is not segmented, then the HTML of the main interface will definitely be ugly.

    We don’t need to use any method to segment it. For example, use some kind of template, use something like include in Angular, or tags in Polymer, React, or directly use native Web Components. In short, we can separate them piece by piece. Taken apart and then contained. From this perspective, these removed things are like components, but from the perspective of reusability, it is likely that each piece of most things is only used in one place, and there is no reusability at all. This was removed purely to make the entire project easier to manage and maintain.

    At this time, we will focus on how different frameworks/libraries handle componentization of the UI layer, and find that there are two types, templates and functions.

    Template is a very common thing. It expresses the original structure of the interface in the form of HTML strings, and then generates the real interface by substituting data. Some generate target HTML, and some also generate various Automatic binding of events. The former is a static template and the latter is a dynamic template.

    There are also some frameworks/libraries that prefer to use functional logic to generate interfaces, the early ExtJS, and now React (it may still use templates internally, and it provides further encapsulation of the component creation interface??jsx) etc. The advantage of this implementation technology is that the programming experience is consistent on different platforms, and the same components can even be encapsulated for each platform. The caller can easily write a code that is available on the Web and different Native platforms. However, this method also has a troublesome aspect, that is, the interface adjustment is relatively cumbersome.

    In the article cited earlier in this article by Hou Zhenyu, he raised these questions:

    How to make components more reusable? More specifically:

  • What should I do if I need to readjust the order of the elements in the component when using a component?
  • What should I do if I want to remove a certain element in the component? How to make the component more extensible? To be more specific:
  • What should I do if the business side keeps asking to add functions to the components?
  • For this reason, a "template copying" solution was also proposed. I have different opinions on this point.

    Let’s take a look at how to cut a business interface into components.

    There is such a simple scenario: an employee list interface includes two parts, the employee form and the form for filling in employee information. What components exist in this scenario?

    Regarding this problem, there are two main tendencies. One is to only encapsulate "controls" and more general things into components, and the other is to componentize the entire application.

    For the former method, there is only one component such as data table.
    For the latter method, there may be: data table, employee form, and even a larger component such as employee list interface.

    These two methods are what we called before "partial componentization" and "full componentization".

    We mentioned earlier that full componentization has advantages in management. It can make things at different levels into similar structures. For example, the business scenario just now will probably end up like this when written. :

    <Employee-Panel>    <Employee-List></Employee-List>    <Employee-Form></Employee-Form></Employee-Panel>

    For the UI layer, the best componentization method is tagging. For example, in the above code, three tags express the entire interface. But I personally firmly oppose the abuse of labels. It does not mean that encapsulating all kinds of things as much as possible is necessarily good.

    The main problems with full tagging are as follows:

    First, the cost of semantics is too high. As long as a tag is used, it must be given appropriate semantics, that is, a name. But in actual use, it is probably just to simplify a bunch of html. What should the simplified thing be called? Just naming it takes up countless brain cells. For example, if you are talking about a form managed by employees, does this form have a header, a footer, can it be folded, etc. It is difficult to come up with a name that others will know at a glance, or it will be too long. This is relatively simple, because we are fully componentized, so it is likely to have a more complex interface that combines multiple things. After much thought, you couldn’t give it a name, so you wrote:

    <Panel-With-Department-Panel-On-The-Left-And-Employee-Panel-On-The-Right></Panel-With-Department-Panel-On-The-Left-And-Employee-Panel-On-The-Right>

    This is crazy... maybe I'm exaggerating, but many times the project scale is large enough that you can't afford such a complicated name. In the end, it's probably impossible to distinguish it from a component with similar functions, because of these The damn components all exist in the same namespace. If it is just included as an interface fragment, there will be no such psychological burden.

    For example, this one in Angular:

    <div ng-include="'aaa/bbb/ccc.html'"></div>

    Don’t give it a name, include it directly, and use the file path to distinguish it. The role of this fragment can be described by its directory structure, which is identified by physical names rather than logical names. The directory hierarchy acts as a good namespace.

    Some of the current mainstream MVVM frameworks, such as knockout, angular, avalon, vue, etc., have an "interface template", but this template is not just a template, but can be regarded as a configuration document. A certain interface template describes its relationship with the data model. After it is parsed, it is associated with the data according to the various settings in it, and in turn updates its corresponding view.

    A UI without business logic (or a UI with separated business logic) is basically not suitable to be treated as a component, because even if the logic remains unchanged, there are too many possibilities for interface revision. For example, even if a new CSS implementation is changed, from float layout to flex layout, it is possible to reduce the DOM structure by a few layers of divs. Therefore, in the scheme of using templates, the interface layer can only be regarded as a configuration file. It cannot be regarded as a component. If you do this, it will be much easier.

    When the troops are marching, they pay attention to "opening roads when encountering mountains and building bridges when encountering water." The key point of this sentence is that roads and bridges are only opened when reaching certain terrains. Most of the time, the business scenarios solved by using MVVM models are flat. , you can walk sideways, there is no need to forcefully build a road. Therefore, looking at the entire solution, the UI layer implementation should be a coexistence of templates and controls. Most of the parts are templates, and a few places are roads and bridges that require separate time.

    Second, the configuration is too complicated. There are many things that are not suitable for encapsulation. Not only is the cost of encapsulation high, but the cost of use is also high. Sometimes you will find that most of the calling code is writing various configurations.

    Just like the employee form just now, since you don’t distinguish it from the naming of labels, you will definitely add configuration to the component. For example, if you originally wanted to do this:

    <EmployeeForm heading="雇員表單"></EmployeeForm>

    Then inside the component, determine whether the header is set. If not, it will not be displayed. If it is, it will be displayed. After two days, the product asked if it could bold or change the color of certain words in the heading, and then the coder began to allow this heading attribute to be passed into the HTML. Not long after, you will be surprised to find that someone is using your component, and without telling you, they pass the html of the fold button in the header, and use the selector to add an event to the fold button, and they can collapse it after clicking it. Form...

    Then you think, this won’t work. I have to add another configuration to it so that it can easily control the display of the fold button. But it’s too unintuitive to write it like this now, so I use objects. Configuration of the structure:

    <EmployeeForm>    <Option collapsible="true">        <Heading>            <h4><strong>雇員</strong>表單</h4>        </Heading>    </Option></EmployeeForm>

    Then one day, I found that many panels can be folded, so I specially created a foldable panel component, and created an inheritance mechanism from which other ordinary business panels The inheritance has been out of control since then.

    What do I mean by giving this example? I want to say that in larger-scale projects, trying to describe all ordinary business interfaces using full labeling and configuration will definitely achieve half the result with twice the effort. , and the larger the scale, the more pitfalls it will have. This is also the biggest problem with systems like ExtJS that over-encapsulate the UI layer.

    Now that we have discussed this issue, let’s take a look at another issue: if UI components have business logic, how should it be handled.

    For example, the drop-down box for gender selection is a very general function and is ideally suited to be provided as a component. But how to encapsulate it, we have some difficulties. In addition to the interface, this component also has data. Should this data be built into the component? Theoretically, from the perspective of the encapsulation of components, everything should be inside, so I created a component like this:

    <GenderSelect></GenderSelect>

    這個組件非常美好,只需直接放在任意的界面中,就能顯示帶有性別數(shù)據(jù)的下拉框了。性別的數(shù)據(jù)很自然地是放在組件的實現(xiàn)內(nèi)部,一個寫死的數(shù)組中。這個太簡單了,我們改一下,改成商品銷售的國家下拉框。

    表面上看,這個沒什么區(qū)別,但我們有個要求,本公司商品銷售的國家的信息是統(tǒng)一配置的,也就是說,這個數(shù)據(jù)來源于服務(wù)端。這時候,你是不是想把一個http請求封裝到這組件里?

    這樣做也不是不可以,但存在至少兩個問題:

  • 如果這類組件在同一個界面中出現(xiàn)多次,就可能存在請求的浪費,因為有一個組件實例就會產(chǎn)生一個請求。
  • 如果國家信息的配置界面與這個組件同時存在,當(dāng)我們在配置界面中新增一個國家了,下拉框組件中的數(shù)據(jù)并不會實時刷新。
  • 第一個問題只是資源的浪費,第二個就是數(shù)據(jù)的不一致了。曾經(jīng)在很多系統(tǒng)中,大家都是手動刷新當(dāng)前頁面來解決這問題的,但到了這個時代,人們都是追求體驗的,在一個全組件化的解決方案中,不應(yīng)再出現(xiàn)此類問題。

    如何解決這樣的問題呢?那就是引入一層Store的概念,每個組件不直接去到服務(wù)端請求數(shù)據(jù),而是到對應(yīng)的前端數(shù)據(jù)緩存中去獲取數(shù)據(jù),讓這個緩存自己去跟服務(wù)端保持同步。

    所以,在實際做方案的過程中,不管是基于Angular,React,Polymer,最后肯定都做出一層Store了,不然會有很多問題。

    5. 為什么MVVM是一種很好的選擇

    我們回顧一下剛才那個下拉框的組件,發(fā)現(xiàn)存在幾個問題:

  • 界面不好調(diào)整。剛才的那個例子相對簡單,如果我們是一個省市縣三級聯(lián)動的組件,就比較麻煩了。比如說,我們想要把水平布局改成垂直的,又或者,想要把中間的label的字改改,都會非常麻煩。按照傳統(tǒng)的做組件的方式,就要加若干配置項,然后組件里面去分別判斷,修改DOM結(jié)構(gòu)。
  • 如果數(shù)據(jù)的來源不是靜態(tài)json,而是某個動態(tài)的服務(wù)接口,那用起來就很麻煩。
  • 我們更多地需要業(yè)務(wù)邏輯的復(fù)用和純“控件”的復(fù)用,至于那些綁定業(yè)務(wù)的界面組件,復(fù)用性其實很弱。
  • 所以,從這些角度,會盡量期望在HTML界面層與JavaScript業(yè)務(wù)邏輯之間,存在一種分離。

    這時候,再看看絕大多數(shù)界面組件存在什么問題:

    有時候我們考慮一下DOM操作的類型,會發(fā)現(xiàn)其實是很容易枚舉的:

  • 創(chuàng)建并插入節(jié)點
  • 移除節(jié)點
  • 節(jié)點的交換
  • 屬性的設(shè)置
  • 多數(shù)界面組件封裝的絕大部分內(nèi)容不過是這些東西的重復(fù)。這些東西,其實是可以通過某些配置描述出來的,比如說,某個數(shù)組以什么形式渲染成一個select或者無序列表之類,當(dāng)數(shù)組變動,這些東西也跟著變動,這些都應(yīng)當(dāng)被自動處理,如果某個方案在現(xiàn)在這個時代還手動操作這些,那真的是一種落伍。

    所以我們可以看到,以Angular,Knockout,Vue,Avalon為代表的框架們在這方面做了很多事,盡管理念有所差異,但大方向都非常一致,也就是把大多數(shù)命令式的DOM操作過程簡化為一些配置。

    有了這種方式之后,我們可以追求不同層級的復(fù)用:

  • 業(yè)務(wù)模型因為是純邏輯,所以非常容易復(fù)用
  • 視圖模型基本上也是純邏輯,界面層多數(shù)是純字符串模板,同一個視圖模型搭配不同的界面模板,可以實現(xiàn)視圖模型的復(fù)用
  • 同一個界面模板與不同的視圖模型組合,也能直接組合出完全不同的東西
  • 所以這么一來,我們的復(fù)用粒度就非常靈活了。正因為這樣,我一直認(rèn)為Angular這樣的框架戰(zhàn)略方向是很正確的,雖然有很多戰(zhàn)術(shù)失誤。我們在很多場景下,都是需要這樣的高效生產(chǎn)手段的。

    6. 組件的長期積累

    我們做組件化這件事,一定是一種長期打算,為了使得當(dāng)前的很多東西可以作為一種積累,在將來還能繼續(xù)使用,或者僅僅作較小的修改就能使用,所以必須考慮對未來標(biāo)準(zhǔn)的兼容。主要需要考慮的方面有這幾點:

  • 盡可能中立于語言和框架,使用瀏覽器的原生特性
  • 邏輯層的模塊化(ECMAScript module)
  • 界面層的元素化(Web Components)
  • 之前有很多人對Angular 2.0的激進(jìn)變更很不認(rèn)同,但它的變更很大程度上是對標(biāo)準(zhǔn)的全面迎合。這不僅僅是它的問題,其實是所有前端框架的問題。不面對這些問題,不管現(xiàn)在多么好,將來都是死路一條。這個問題的根源是,這幾個已有的規(guī)范約束了模塊化和元素化的推薦方式,并且,如果要對當(dāng)前和未來兩邊做適配的話,基本就沒法干了,導(dǎo)致以前的都不得不做一定的遷移。

    模塊化的遷移成本還比較小,無論是之前AMD還是CMD的,都可以根據(jù)一些規(guī)則轉(zhuǎn)換過來,但組件化的遷移成本太大了,幾乎每種框架都會提出自己的理念,然后有不同的組件化理念。

    還是從三個典型的東西來說:Polymer,React,Angular。

    Polymer中的組件化,其實就是標(biāo)簽化。這里的標(biāo)簽,并不只是界面元素,甚至邏輯組件也可以這樣,比如這個代碼:

    <my-panel>    <core-ajax id="ajax" url="http://url" params="{{formdata}}" method="post"></core-ajax></my-panel>

    注意到這里的core-ajax標(biāo)簽,很明顯這已經(jīng)是純邏輯的了,在大多數(shù)前端框架或者庫中,調(diào)用ajax肯定不是這樣的,但在瀏覽器端這么干也不是它獨創(chuàng),比如flash里面的WebService,比如早期IE中基于htc實現(xiàn)的webservice.htc等等,都是這么干的。在Polymer中,這類東西稱為非可見元素(non-visual-element)。

    React的組件化,跟Polymer略有不同,它的界面部分是標(biāo)簽化,但如果有單純的邏輯,還是純JavaScript模塊。

    既然大家的實現(xiàn)方式都那么不一致,那我們怎么搞出盡量可復(fù)用的組件呢?問題到最后還是要繞到Web Components上。

    在Web Components與前端組件化框架的關(guān)系上,我覺得是這么個樣子:

    各種前端組件化框架應(yīng)當(dāng)盡可能以Web Components為基石,它致力于組織這些Components與數(shù)據(jù)模型之間的關(guān)系,而不去關(guān)注某個具體Component的內(nèi)部實現(xiàn),比如說,一個列表組件,它究竟內(nèi)部使用什么實現(xiàn),組件化框架其實是不必關(guān)心的,它只應(yīng)當(dāng)關(guān)注這個組件的數(shù)據(jù)存取接口。

    然后,這些組件化框架再去根據(jù)自己的理念,進(jìn)一步對這些標(biāo)準(zhǔn)Web Components進(jìn)行封裝。換句話說,業(yè)務(wù)開發(fā)人員使用某個組件的時候,他是應(yīng)當(dāng)感知不到這個組件內(nèi)部究竟使用了Web Components,還是直接使用傳統(tǒng)方式。(這一點有些理想化,可能并不是那么容易做到,因為我們還要管理像import之類的事情)。

    7. 我們需要關(guān)注什么

    目前來看,前端框架/庫仍然處于混戰(zhàn)期,可比中國歷史上的春秋戰(zhàn)國,百家齊放,作為跟隨者來說,這是很痛苦的,因為無所適從,很可能你作為一個企業(yè)的前端架構(gòu)師或者技術(shù)經(jīng)理,需要做一些選型工作,但選哪個能保證幾年后不被淘汰呢?基本沒有。

    雖然我們不知道將來什么框架會流行,但我們可以從一些細(xì)節(jié)方面去關(guān)注,某個具體的方面,將來會有什么,也可以了解一下在某個具體領(lǐng)域存在什么樣的方案。一個完整的框架方案,無非是以下多個方面的綜合。

    7.1 模塊化

    這塊還是不講了,支付寶seajs還有百度ecomfe這兩個團(tuán)隊的人應(yīng)該都能比我講得好得多。

    7.2 Web Components

    本文前面討論過一些,也不深入了。

    7.3 變更檢測

    我們知道,現(xiàn)代框架的一個特點是自動化,也就是把原有的一些手動操作提取。在前端編程中,最常見的代碼是在干什么呢?讀寫數(shù)據(jù)和操作DOM。不少現(xiàn)代的框架/庫都對這方面作了處理,比如說通過某種配置的方式,由框架自動添加一些關(guān)聯(lián),當(dāng)數(shù)據(jù)變更的時候,把DOM進(jìn)行相應(yīng)修改,又比如,當(dāng)DOM發(fā)生變動的時候,也更新對應(yīng)的數(shù)據(jù)。

    這個關(guān)聯(lián)過程可能會用到幾種技術(shù)。首先我們看怎么知道數(shù)據(jù)在變化,這里面有三種途徑:

    一、存取器的封裝。這個的意思也就是對數(shù)據(jù)進(jìn)行一層包裝,比如:

    var data = {    name: "aaa",    getName: function() {        return this.name;    },    setName: function(value) {        this.name = value;    }}

    這樣,不允許用戶直接調(diào)用data.name,而是調(diào)用對應(yīng)的兩個函數(shù)。Backbone就是通過這樣的機制實現(xiàn)數(shù)據(jù)變動觀測的,這種方式適用于幾乎所有瀏覽器,缺點就是比較麻煩,要對每個數(shù)據(jù)進(jìn)行包裝。

    這個機制在稍微新一點的瀏覽器中,也有另外一種實現(xiàn)方式,那就是defineProperty相關(guān)的一些方法,使用更優(yōu)雅的存取器,這樣外界可以不用調(diào)用函數(shù),而是直接用data.name這樣進(jìn)行屬性的讀寫。

    The domestic framework avalon uses this mechanism. There is no defineProperty in the lower version of IE, but in the lower version of IE there is not only JavaScript, but also VBScript, which has accessors, so he cleverly used VBS to make such a Compatible packaging.

    Another trouble with the accessor-based mechanism is that every time an attribute is dynamically added, a corresponding accessor must be added, otherwise the changes to this attribute cannot be obtained.

    2. Dirty detection.

    Frameworks represented by Angular 1.x use dirty detection to learn about data changes. The general principle of this mechanism is:

    Save the old and new values ??of the data, whenever there is some DOM or network , timer and other events are generated. Use the data after this event to compare with the previously saved data. If they are the same, the interface refresh will not be triggered, otherwise it will be refreshed.

    The idea of ??this method is to control all sources that may cause data changes (that is, various events). After they may operate on the data, determine whether there are changes in the old and new data, ignoring all intermediate changes, and That is to say, if you modify a certain data arbitrarily many times in the same event, but finally change it back, the framework will think that you have done nothing, and will not notify the interface to refresh.

    It is undeniable that the efficiency of dirty detection is relatively low, mainly because the impact of data changes cannot be accurately known. Therefore, when the amount of data is larger, the waste is more serious, and some manual optimization is required. For example, a large array generates a list on the interface. When an item is selected, the color changes. Under this mechanism, every time the data status of this item is changed, all items need to be compared with the original ones. Then, all items need to be compared again to find that there are no related changes, and then the interface can be refreshed accordingly.

    3. Observation mechanism.

    In ES7, the observe method of Object is introduced, which can be used to monitor changes in objects or arrays.

    This is the most reasonable observation plan so far. This mechanism is very precise and efficient. For example, the company commander tells the soldiers to observe what is going on in the bunker opposite. This meaning is very complicated, what does it include?

  • Have people been added?
  • Have there been people left?
  • Who has changed the guard with whom?
  • The flag above has been changed from the sun flag to the blue sky and white sun.
  • The so-called observation mechanism refers to changes in the properties of the observed object, addition, removal, position changes of array elements, etc. Let's first think about the binding of interface and data. This should be an external observation. You are the data and I am the interface. You nod and I smile. You stretch out your hand and I hit. This kind of binding should be a loose relationship. It should not destroy some original things because of the binding, so it is obviously more reasonable.

    In addition to data changes that can be observed, DOM can also be observed. However, most current two-way synchronization frameworks synchronize DOM changes to data through events. For example, if a text box is bound to the properties of an object, it is very likely that the framework internally monitors the keyboard input, paste and other related events of this text box, and then takes the value and writes it into the object.

    Doing this can solve most problems, but if you directly myInput.value="111", this change will not be available. This is not a big problem, because in a two-way binding framework, something that is both monitored and assigned manually is quite strange in itself. However, some frameworks will try to override the value assignment from the prototype of HTMLInputELement. Try to make this Things are also included in the jurisdiction of the framework.

    Another question is that we only consider specific attributes of specific elements and can obtain changes through events. How to obtain DOM changes in a broader sense? For example, changes to general attributes, or even the addition and deletion of child nodes?

    DOM4 introduces MutationObserver to implement the observation of such changes. Whether such a complex observation and synchronization mechanism is needed between the DOM and data has not yet been determined, but under the general trend of gradual automation of the entire front-end development, this is also something worth trying.

    Complex correlation monitoring can easily lead to unexpected results:

  • Murong Fu wanted to return to the country, so he studied and practiced martial arts every day, and made various plans
  • Wang Yuyan observed this phenomenon, He thought his cousin didn’t love him anymore
  • Duan Yu saw that the fairy sister was unhappy and didn’t think about food or food every day
  • Princess Zhennan felt sorry for her son and went around to investigate the whole story, and unexpectedly discovered that Duan Zhengchun is still in contact with his old love
  • ...
  • In short, I don’t know where the impact will be in the end. Who let Qiu Chuji pass by Niujia Village?

    Therefore, the related monitoring of changes is a very complex system, especially when a closed loop occurs. Building such a whole set of things requires extremely precise design, otherwise people who are familiar with the whole set of mechanisms will fall over with just a slight push using a specific scenario. Although Master Lingzhi was excellent in martial arts, he encountered Ouyang Feng, Zhou Botong, and Huang Yaoshi one after another, and all of them were immediately grabbed at the back of their necks, which is roughly what it meant.

    Polymer implements an observe-js, which is used to observe changes in arrays, objects and paths. If you are interested, you can pay attention.

    在有些框架,比如aurelia中,是混合使用了存取器和觀察模式,把存取器作為觀察模式的降級方案,在瀏覽器不支持observe的情況下使用。值得一提的是,在臟檢測方式中,變更是合并后批量提交的,這一點常常被另外兩種方案的使用者忽視。其實,即使用另外兩種方式,也還是需要一個合并與批量提交過程。

    怎么理解這個事情呢?數(shù)據(jù)的綁定,最終都是要體現(xiàn)到界面上的,對于界面來說,其實只關(guān)注你每一次操作所帶來的數(shù)據(jù)變更的始終,并不需要關(guān)心中間過程。比如說,你寫了這么一個循環(huán),放在某個按鈕的點擊中:

    for (var i=0; i<10000; i++) {    obj.a += 1;}

    界面有一個東西綁定到這個a,對框架來說,絕對不應(yīng)當(dāng)把中間過程直接應(yīng)用到界面上,以剛才這個例子來說,合理的情況只應(yīng)當(dāng)存在一次對界面DOM的賦值,這個值就是對obj.a進(jìn)行了10000次賦值之后的值。盡管用存取器或者觀察模式,發(fā)現(xiàn)了對obj上a屬性的這10000次賦值過程,這些賦值還是都必須被舍棄,否則就是很可怕的浪費。

    React使用虛擬DOM來減少中間的DOM操作浪費,本質(zhì)跟這個是一樣的,界面只應(yīng)當(dāng)響應(yīng)邏輯變更的結(jié)束狀態(tài),不應(yīng)當(dāng)響應(yīng)中間狀態(tài)。這樣,如果有一個ul,其中的li綁定到一個1000元素的數(shù)組,當(dāng)首次把這個數(shù)組綁定到這個ul上的時候,框架內(nèi)部也是可以優(yōu)化成一次DOM寫入的,類似之前常用的那種DocumentFragment,或者是innerHTML一次寫入整個字符串。在這個方面,所有優(yōu)化良好的框架,內(nèi)部實現(xiàn)機制都應(yīng)當(dāng)類似,在這種方案下,是否使用虛擬DOM,對性能的影響都是很小的。

    7.4 Immutable Data

    Immutable Data是函數(shù)式編程中的一個概念,在前端組件化框架中能起到一些很獨特的作用。

    它的大致理念是,任何一種賦值,都應(yīng)當(dāng)被轉(zhuǎn)化成復(fù)制,不存在指向同一個地方的引用。比如說:

    var a = 1;var b = a;b = 2;console.log(a==b);

    這個我們都知道,b跟a的內(nèi)存地址是不一致的,簡單類型的賦值會進(jìn)行復(fù)制,所以a跟b不相等。但是:

    var a = {    counter : 1};var b = a;b.counter++;console.log(a.counter==b.counter);

    這時候因為a和b指向相同的內(nèi)存地址,所以只要修改了b的counter,a里面的counter也會跟著變。

    Immutable Data的理念是,我能不能在這種賦值情況下,直接把原來的a完全復(fù)制一份給b,然后以后大家各自變各自的,互相不影響。光憑這么一句話,看不出它的用處,看例子:

    對于全組件化的體系,不可避免會出現(xiàn)很多嵌套的組件。嵌套組件是一個很棘手的問題,在很多時候,是不太好處理的。嵌套組件所存在的問題主要在于生命周期的管理和數(shù)據(jù)的共享,很多已有方案的上下級組件之間都是存在數(shù)據(jù)共享的,但如果內(nèi)外層存在共享數(shù)據(jù),那么就會破壞組件的獨立性,比如下面的一個列表控件:

    <my-list list-data="{arr}">    <my-listitem></my-listitem>    <my-listitem></my-listitem>    <my-listitem></my-listitem></my-list>

    我們在賦值的時候,一般是在外層整體賦值一個類似數(shù)組的數(shù)據(jù),而不是自己挨個在每個列表項上賦值,不然就很麻煩。但是如果內(nèi)外層持有相同的引用,對組件的封裝性很不利。

    比如在剛才這個例子里,假設(shè)數(shù)據(jù)源如下:

    var arr = [    {name: "Item1"},     {name: "Item2"},     {name: "Item3"}];

    通過類似這樣的方式賦值給界面組件,并且由它在內(nèi)部給每個子組件分別進(jìn)行數(shù)據(jù)項的賦值:

    list.data = arr;

    賦值之后會有怎樣的結(jié)果呢?

    console.log(list.data == arr);console.log(listitem0.data == arr[0]);console.log(listitem1.data == arr[1]);console.log(listitem2.data == arr[2]);

    這種方案里面,后面那幾個log輸出的結(jié)果都會是true,意思就是內(nèi)層組件與外層共享數(shù)據(jù),一旦內(nèi)層組件對數(shù)據(jù)進(jìn)行改變,外層中的也就改變了,這明顯是違背組件的封裝性的。

    所以,有一些方案會引入Immutable Data的概念。在這些方案里,內(nèi)外層組件的數(shù)據(jù)是不共享的,它們的引用不同,每個組件實際上是持有了自己的數(shù)據(jù),然后引入了自動的賦值機制。

    這時候再看看剛才那個例子,就會發(fā)現(xiàn)兩層的職責(zé)很清晰:

  • 外層持有一個類似數(shù)組的東西arr,用于形成整個列表,但并不關(guān)注每條記錄的細(xì)節(jié)
  • 內(nèi)層持有某條記錄,用于渲染列表項的界面
  • 在整個列表的形成過程中,list組件根據(jù)arr的數(shù)據(jù)長度,實例化若干個listitem,并且把arr中的各條數(shù)據(jù)賦值給對應(yīng)的listitem,而這個賦值,就是immutable data起作用的地方,其實是把這條數(shù)據(jù)復(fù)制了一份給里面,而不是把外層這條記錄的引用賦值進(jìn)去。內(nèi)層組件發(fā)現(xiàn)自己的數(shù)據(jù)改變之后,就去進(jìn)行對應(yīng)的渲染
  • 如果arr的條數(shù)變更了,外層監(jiān)控這個數(shù)據(jù),并且根據(jù)變更類型,添加或者刪除某個列表項
  • 如果從外界改變了arr中某一條記錄的內(nèi)容,外層組件并不直接處理,而是給對應(yīng)的內(nèi)層進(jìn)行了一次賦值
  • 如果列表項中的某個操作,改變了自身的值,它首先是把自己持有的數(shù)據(jù)進(jìn)行改變,然后,再通過immutable data把數(shù)據(jù)往外同步一份,這樣,外層組件中的數(shù)據(jù)也就更新了。
  • 所以我們再看這個過程,真是非常清晰明了,而且內(nèi)外層各司其職,互不干涉。這是非常有利于我們打造一個全組件化的大型Web應(yīng)用的。各級組件之間存在比較松散的聯(lián)系,而每個組件的內(nèi)部則是封閉的,這正是我們所需要的結(jié)果。

    說到這里,需要再提一個容易混淆的東西,比如下面這個例子:

    <outer-component>    <inner-component></inner-component></outer-component>

    如果我們?yōu)榱私oinner-component做一些樣式定位之類的事情,很可能在內(nèi)外層組件之間再加一些額外的布局元素,比如變成這樣:

    <outer-component>    <div>        <inner-component></inner-component>    </div></outer-component>

    這里中間多了一級div,也可能是若干級元素。如果有用過Angular 1.x的,可能會知道,假如這里面硬造一級作用域,搞個ng-if之類,就可能存在多級作用域的賦值問題。在上面這個例子里,如果在最外層賦值,數(shù)據(jù)就會是outer -> div -> inner這樣,那么,從框架設(shè)計的角度,這兩次賦值都應(yīng)當(dāng)是immutable的嗎?

    不是,第一次賦值是非immutable,第二次才需要是,immutable賦值應(yīng)當(dāng)僅存在于組件邊界上,在組件內(nèi)部不是特別有必要使用。剛才的例子里,依附于div的那層變量應(yīng)當(dāng)還是跟outer組件在同一層面,都屬于outer組件的人民內(nèi)部矛盾。

    這里是facebook實現(xiàn)的immutable-js庫

    7.6 Promise與異步

    前端一般都習(xí)慣于用事件的方式處理異步,但很多時候純邏輯的“串行化”場景下,這種方式會讓邏輯很難閱讀。在新的ES規(guī)范里,也有yield為代表的各種原生異步處理方案,但是這些方案仍然有很大的理解障礙,流行度有限,很大程度上會一直停留在基礎(chǔ)較好的開發(fā)人員手中。尤其是在瀏覽器端,它的受眾應(yīng)該會比node里面還要狹窄。

    前端里面,處理連續(xù)異步消息的最能被廣泛接受的方案是promise,我這里并不討論它的原理,也不討論它在業(yè)務(wù)中的使用,而是要提一下它在組件化框架內(nèi)部所能起到的作用。

    現(xiàn)在已經(jīng)沒有哪個前端組件化框架可以不考慮異步加載問題了,因為,在前端這個領(lǐng)域,加載就是一個繞不過去的坎,必須有了加載,才能有執(zhí)行過程。每個組件化框架都不能阻止自己的使用者規(guī)模膨脹,因此也應(yīng)當(dāng)在框架層面提出解決方案。

    我們可能會動態(tài)配置路由,也可能在動態(tài)加載的路由中又引入新的組件,如何控制這些東西的生命周期,值得仔細(xì)斟酌,如果在框架層面全異步化,對于編程體驗的一致性是有好處的。將各類接口都promise化,能夠在可維護(hù)性和可擴(kuò)展性上提供較多便利。

    我們之前可能熟知XMLHTTP這樣的通信接口,這個東西雖然被廣為使用,但是在優(yōu)雅性等方面,存在一些問題,所以最近出來了替代方案,那就是fetch。

    細(xì)節(jié)可以參見月影翻譯的這篇【翻譯】這個API很“迷人”??(新的Fetch API)

    在不支持的瀏覽器上,也有g(shù)ithub實現(xiàn)的一個polyfill,雖然不全,但可以湊合用window.fetch polyfill

    大家可以看到,fetch的接口就是基于promise的,這應(yīng)當(dāng)是前端開發(fā)人員最容易接受的方案了。

    7.7 Isomorphic JavaScript

    這個東西的意思是前后端同構(gòu)的JavaScript,也就是說,比如一塊界面,可以選擇在前端渲染,也可以選擇在后端渲染,值得關(guān)注,可以解決像seo之類的問題,但現(xiàn)在還不能處理很復(fù)雜的狀況,持續(xù)關(guān)注吧。

    8. Summary

    Thank you very much for seeing this. The above is a summary of my thoughts in the past year. From the perspective of technology selection, it will be very painful for people who make large-scale web applications, because this is an era of sluggish development, and all existing frameworks/libraries have defects to varying degrees. When you look to the future, you find that they all need to be abandoned or transformed. The most painful thing for people is knowing that many things are bad, but they have to choose one of them to use. @yanqing discussed this issue with @inchzhi @Tiye, and they believe that it is difficult to select technology at this stage, so it is better to wait for a while. I completely agree with their point of view.

    It is difficult to choose, but from a learning perspective, it is really a good era. There are so many things to learn. I try hard to see things that may be worth seeing on the road every day, but still I can’t finish it, so I can only try to keep up with the times.

    The following paragraph is for your encouragement:

    It was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it was the season of Light, it was the season of Darkness, it was the spring of hope, it was the winter of despair, we had everything before us, we had nothing before us , we were all going direct to Heaven, we were all going direct the other way--in short, the period was so far like the present period, that some of its noisiest authorities insisted on its being received, for good or for evil, in the superlative degree of comparison only.

    Statement of this Website
    The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

    Hot AI Tools

    Undress AI Tool

    Undress AI Tool

    Undress images for free

    Undresser.AI Undress

    Undresser.AI Undress

    AI-powered app for creating realistic nude photos

    AI Clothes Remover

    AI Clothes Remover

    Online AI tool for removing clothes from photos.

    Clothoff.io

    Clothoff.io

    AI clothes remover

    Video Face Swap

    Video Face Swap

    Swap faces in any video effortlessly with our completely free AI face swap tool!

    Hot Tools

    Notepad++7.3.1

    Notepad++7.3.1

    Easy-to-use and free code editor

    SublimeText3 Chinese version

    SublimeText3 Chinese version

    Chinese version, very easy to use

    Zend Studio 13.0.1

    Zend Studio 13.0.1

    Powerful PHP integrated development environment

    Dreamweaver CS6

    Dreamweaver CS6

    Visual web development tools

    SublimeText3 Mac version

    SublimeText3 Mac version

    God-level code editing software (SublimeText3)

    How do I stay up-to-date with the latest HTML standards and best practices? How do I stay up-to-date with the latest HTML standards and best practices? Jun 20, 2025 am 08:33 AM

    The key to keep up with HTML standards and best practices is to do it intentionally rather than follow it blindly. First, follow the summary or update logs of official sources such as WHATWG and W3C, understand new tags (such as) and attributes, and use them as references to solve difficult problems; second, subscribe to trusted web development newsletters and blogs, spend 10-15 minutes a week to browse updates, focus on actual use cases rather than just collecting articles; second, use developer tools and linters such as HTMLHint to optimize the code structure through instant feedback; finally, interact with the developer community, share experiences and learn other people's practical skills, so as to continuously improve HTML skills.

    How do I use the  element to represent the main content of a document? How do I use the element to represent the main content of a document? Jun 19, 2025 pm 11:09 PM

    The reason for using tags is to improve the semantic structure and accessibility of web pages, make it easier for screen readers and search engines to understand page content, and allow users to quickly jump to core content. Here are the key points: 1. Each page should contain only one element; 2. It should not include content that is repeated across pages (such as sidebars or footers); 3. It can be used in conjunction with ARIA properties to enhance accessibility. Usually located after and before, it is used to wrap unique page content, such as articles, forms or product details, and should be avoided in, or in; to improve accessibility, aria-labeledby or aria-label can be used to clearly identify parts.

    How do I minimize the size of HTML files? How do I minimize the size of HTML files? Jun 24, 2025 am 12:53 AM

    To reduce the size of HTML files, you need to clean up redundant code, compress content, and optimize structure. 1. Delete unused tags, comments and extra blanks to reduce volume; 2. Move inline CSS and JavaScript to external files and merge multiple scripts or style blocks; 3. Simplify label syntax without affecting parsing, such as omitting optional closed tags or using short attributes; 4. After cleaning, enable server-side compression technologies such as Gzip or Brotli to further reduce the transmission volume. These steps can significantly improve page loading performance without sacrificing functionality.

    How do I create a basic HTML document? How do I create a basic HTML document? Jun 19, 2025 pm 11:01 PM

    To create a basic HTML document, you first need to understand its basic structure and write code in a standard format. 1. Use the declaration document type at the beginning; 2. Use the tag to wrap the entire content; 3. Include and two main parts in it, which are used to store metadata such as titles, style sheet links, etc., and include user-visible content such as titles, paragraphs, pictures and links; 4. Save the file in .html format and open the viewing effect in the browser; 5. Then you can gradually add more elements to enrich the page content. Follow these steps to quickly build a basic web page.

    How do I create checkboxes in HTML using the  element? How do I create checkboxes in HTML using the element? Jun 19, 2025 pm 11:41 PM

    To create an HTML checkbox, use the type attribute to set the element of the checkbox. 1. The basic structure includes id, name and label tags to ensure that clicking text can switch options; 2. Multiple related check boxes should use the same name but different values, and wrap them with fieldset to improve accessibility; 3. Hide native controls when customizing styles and use CSS to design alternative elements while maintaining the complete functions; 4. Ensure availability, pair labels, support keyboard navigation, and avoid relying on only visual prompts. The above steps can help developers correctly implement checkbox components that have both functional and aesthetics.

    How do I use the  element to represent the footer of a document or section? How do I use the element to represent the footer of a document or section? Jun 25, 2025 am 12:57 AM

    It is a semantic tag used in HTML5 to define the bottom of the page or content block, usually including copyright information, contact information or navigation links; it can be placed at the bottom of the page or nested in, etc. tags as the end of the block; when using it, you should pay attention to avoid repeated abuse and irrelevant content.

    How has HTML evolved over time, and what are the key milestones in its history? How has HTML evolved over time, and what are the key milestones in its history? Jun 24, 2025 am 12:54 AM

    HTMLhasevolvedsignificantlysinceitscreationtomeetthegrowingdemandsofwebdevelopersandusers.Initiallyasimplemarkuplanguageforsharingdocuments,ithasundergonemajorupdates,includingHTML2.0,whichintroducedforms;HTML3.x,whichaddedvisualenhancementsandlayout

    How do I use the tabindex attribute to control the tab order of elements? How do I use the tabindex attribute to control the tab order of elements? Jun 24, 2025 am 12:56 AM

    ThetabindexattributecontrolshowelementsreceivefocusviatheTabkey,withthreemainvalues:tabindex="0"addsanelementtothenaturaltaborder,tabindex="-1"allowsprogrammaticfocusonly,andtabindex="n"(positivenumber)setsacustomtabbing

    See all articles