新浦京娱乐场官网-301net-新浦京娱乐www.301net
做最好的网站

我说按模块划分好

致大家必定组件化的Web

2015/11/25 · HTML5 · 1 评论 · 组件化

初稿出处: AlloyTeam   

那篇小说将从四年前的三遍工夫争论起来。争论的集中就是下图的三个目录分层结构。作者说按模块划分好,他说您傻逼啊,当然是按财富划分。

图片 1 《=》图片 2

”按模块划分“目录结构,把近日模块下的具备逻辑和财富都放一块了,那对于几个人独自开荒和保安个人模块不是很好啊?当然了,那争辩的结果是本人婴儿地改回主流的”按能源划分“的目录结构。因为,未有变成JS模块化和财富模块化,仅仅物理地方上的模块划分是从没有过意义的,只会增多构建的本金而已。

虽说他说得好有道理作者理屈词穷,不过笔者心不甘,等待他多年来端组件化成熟了,再来世界首次大战!

而明日正是作者强调正义的光阴!只是那时候充足跟你撕逼的人不在。

模块化的欠缺

模块日常指能够独立拆分且通用的代码单元。由于JavaScript语言本人未有放置的模块机制(ES6有了!!),大家日常会选择CMD或ADM建设构造起模块机制。未来超越约得其半多少大型一点的类型,都会选拔requirejs可能seajs来贯彻JS的模块化。多人分工同盟开拓,其各自定义依赖和揭穿接口,维护效率模块间独立性,对于项指标支出功用和类型后期扩张和护卫,都是是有异常的大的赞助意义。

但,麻烦我们有个别略读一下上边包车型大巴代码

JavaScript

require([ 'Tmpl!../tmpl/list.html','lib/qqapi','module/position','module/refresh','module/page','module/net' ], function(listTmpl, QQapi, Position, Refresh, Page, NET){ var foo = '', bar = []; QQapi.report(); Position.getLocaiton(function(data){ //... }); var init = function(){ bind(); NET.get('/cgi-bin/xxx/xxx',function(data){ renderA(data.banner); renderB(data.list); }); }; var processData = function(){ }; var bind = function(){ }; var renderA = function(){ }; var renderB = function(data){ listTmpl.render('#listContent',processData(data)); }; var refresh = function(){ Page.refresh(); }; // app start init(); });

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
require([
    'Tmpl!../tmpl/list.html','lib/qqapi','module/position','module/refresh','module/page','module/net'
], function(listTmpl, QQapi, Position, Refresh, Page, NET){
    var foo = '',
        bar = [];
    QQapi.report();
    Position.getLocaiton(function(data){
        //...
    });
    var init = function(){
        bind();
        NET.get('/cgi-bin/xxx/xxx',function(data){
            renderA(data.banner);
            renderB(data.list);
        });
    };
    var processData = function(){
    };
    var bind = function(){
    };
    var renderA = function(){
    };
    var renderB = function(data){
        listTmpl.render('#listContent',processData(data));
    };
    var refresh = function(){
        Page.refresh();
    };
    // app start
    init();
});

地点是现实某些页面包车型地铁主js,已经封装了像Position,NET,Refresh等功效模块,但页面的主逻辑还是是”面向进度“的代码结构。所谓面向进程,是指依据页面包车型地铁渲染进度来编排代码结构。像:init -> getData -> processData -> bindevent -> report -> xxx 。 方法之间线性跳转,你大致也能感受那样代码缺欠。随着页面逻辑更是复杂,那条”过程线“也会更长,並且尤其绕。加之缺乏专门的学问约束,其余门类成员依照各自必要,在”进程线“加插各自逻辑,最终那几个页面包车型大巴逻辑变得难以保证。

图片 3

支出必要实事求是,生怕影响“进程线”后边不奇怪逻辑。而且每三回加插或修改都以bug泛滥,无不令产品有关人口无不触目惊心。

 页面结构模块化

据说上边的面向进程的标题,行当内也可以有许多缓慢解决方案,而我们公司也计算出一套成熟的应用方案:Abstractjs,页面结构模块化。大家能够把大家的页面想象为一个乐高机器人,供给不一样零件组装,如下图,若是页面划分为tabContainer,listContainer和imgsContainer四个模块。最终把这个模块add到最后的pageModel里面,最后利用rock方法让页面运维起来。

图片 4
(原经过线示例图)

图片 5
(页面结构化示例图)

上面是伪代码的贯彻

JavaScript

require([ 'Tmpl!../tmpl/list.html','Tmpl!../tmpl/imgs.html','lib/qqapi','module/refresh','module/page' ], function(listTmpl, imgsTmpl, QQapi, Refresh, Page ){ var tabContainer = new RenderModel({ renderContainer: '#tabWrap', data: {}, renderTmpl: "<li soda-repeat='item in data.tabs'>{{item}}</li>", event: function(){ // tab's event } }); var listContainer = new ScrollModel({ scrollEl: $.os.ios ? $('#Page') : window, renderContainer: '#listWrap', renderTmpl: listTmpl, cgiName: '/cgi-bin/index-list?num=1', processData: function(data) { //... }, event: function(){ // listElement's event }, error: function(data) { Page.show('数据再次来到格外[' data.retcode ']'); } }); var imgsContainer = new renderModel({ renderContainer: '#imgsWrap', renderTmpl: listTmpl, cgiName: '/cgi-bin/getPics', processData: function(data) { //... }, event: function(){ // imgsElement's event }, complete: function(data) { QQapi.report(); } }); var page = new PageModel(); page.add([tabContainer,listContainer,imgsContainer]); page.rock(); });

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
require([
    'Tmpl!../tmpl/list.html','Tmpl!../tmpl/imgs.html','lib/qqapi','module/refresh','module/page'
], function(listTmpl, imgsTmpl, QQapi, Refresh, Page ){
 
    var tabContainer = new RenderModel({
        renderContainer: '#tabWrap',
        data: {},
        renderTmpl: "<li soda-repeat='item in data.tabs'>{{item}}</li>",
        event: function(){
            // tab's event
        }
    });
 
    var listContainer = new ScrollModel({
        scrollEl: $.os.ios ? $('#Page') : window,
        renderContainer: '#listWrap',
        renderTmpl: listTmpl,
        cgiName: '/cgi-bin/index-list?num=1',
        processData: function(data) {
            //...
        },
        event: function(){
            // listElement's event
        },
        error: function(data) {
            Page.show('数据返回异常[' data.retcode ']');
        }
    });
 
    var imgsContainer = new renderModel({
        renderContainer: '#imgsWrap',
        renderTmpl: listTmpl,
        cgiName: '/cgi-bin/getPics',
        processData: function(data) {
            //...
        },
        event: function(){
            // imgsElement's event
        },
        complete: function(data) {
           QQapi.report();
        }
    });
 
    var page = new PageModel();
    page.add([tabContainer,listContainer,imgsContainer]);
    page.rock();
 
});

我们把这个常用的央求CGI,管理多少,事件绑定,上报,容错管理等一两种逻辑格局,以页面块为单位封装成二个Model模块。

如此那般的叁个虚幻层Model,大家能够清晰地看出该页面块,乞请的CGI是什么样,绑定了什么样风云,做了怎么着上报,出错怎么管理。新扩张的代码就活该放置在对应的模块上相应的景况方法(preload,process,event,complete…),杜绝了今后的无准绳乱增代码的写作。并且,依照分裂专业逻辑封装差别品种的Model,如列表滚动的ScrollModel,滑块功能的SliderModel等等,能够拓宽中度封装,集中优化。

近期依赖Model的页面结构开垦,已经包涵一点”组件化“的含意。各类Model都带有各自的数目,模板,逻辑。已经算是贰个完好无缺的效率单元。但间隔真正的WebComponent仍然有一段间隔,起码满足不断作者的”理想目录结构“。

 WebComponents 标准

作者们回顾一下运用多个datapicker的jquery的插件,所急需的步奏:

  1. 引进插件js

  2. 引入插件所需的css(借使有)

  3. copy 组件的所需的html片段

  4. 增加代码触发组件运转

近年来的“组件”基本上只好落得是某些功用单元上的成团。他的能源都以松散地分散在二种财富文件中,况兼组件功能域揭示在全局意义域下,贫乏内聚性很轻易就能够跟任何零件产生冲突,如最简便易行的css命名冲突。对于这种“组件”,还不及上边的页面结构模块化。

于是乎W3C按耐不住了,制订贰个WebComponents标准,为组件化的前景指导了明路。

上面以较为轻松的办法介绍那份正经,力求大家能够高效理解达成组件化的剧情。(对这部分询问的同学,能够跳过这一小节)

1. <template>模板本领

模板这东西哈工业余大学学学家最熟识但是了,前一年见的很多的沙盘品质战斗artTemplate,juicer,tmpl,underscoretemplate等等。而后天又有mustachejs无逻辑模板引擎等新入选手。不过咱们有没有想过,这么基础的力量,原生HTML5是不援救的(T_T)。

近些日子天WebComponent就要提供原生的模板本事

XHTML

<template id="datapcikerTmpl"> <div>小编是原生的模版</div> </template>

1
2
3
<template id="datapcikerTmpl">
<div>我是原生的模板</div>
</template>

template标签钦定义了myTmpl的模版,须要使用的时候将要innerHTML= document.querySelector('#myTmpl').content;能够见到这一个原生的模板够原始,模板占位符等功能都未曾,对于动态数据渲染模板技艺只可以自力更新。

2. ShadowDom 封装组件独立的内部结构

ShadowDom能够清楚为一份有独立效能域的html片段。那些html片段的CSS意况和主文书档案隔断的,各自笔者保护持内部的独立性。也正是ShadowDom的单独天性,使得组件化成为了大概。

JavaScript

var wrap = document.querySelector('#wrap'); var shadow = wrap.createShadowRoot(); shadow.innerHTML = '<p>you can not see me </p>'

1
2
3
var wrap = document.querySelector('#wrap');
var shadow = wrap.createShadowRoot();
shadow.innerHTML = '<p>you can not see me </p>'

在实际dom节点上行使createShadowRoot方法就能够生成其ShadowDom。就好像在整份Html的室内面,新建了一个shadow的房屋。房间外的人都不知道房间内有何样,保持shadowDom的独立性。

3. 自定义原生标签

最早接触Angularjs的directive指令成效,设定好组件的逻辑后,多少个<Datepicker />就会引进整个组件。如此狂炫彩炸碉堡天的效劳,实在令人弹冠相庆,跃地三尺。

JavaScript

var tmpl = document.querySelector('#datapickerTmpl'); var datapickerProto = Object.create(HTMLElement.prototype); // 设置把大家模板内容大家的shadowDom datapickerProto.createdCallback = function() { var root = this.createShadowRoot(); root.appendChild(document.importNode(tmpl.content, true)); }; var datapicker = docuemnt.registerElement('datapicker',{ prototype: datapickerProto });

1
2
3
4
5
6
7
8
9
10
11
12
var tmpl = document.querySelector('#datapickerTmpl');
var datapickerProto = Object.create(HTMLElement.prototype);
 
// 设置把我们模板内容我们的shadowDom
datapickerProto.createdCallback = function() {
    var root = this.createShadowRoot();
    root.appendChild(document.importNode(tmpl.content, true));
};
 
var datapicker = docuemnt.registerElement('datapicker',{
    prototype: datapickerProto
});

Object.create情势一连HTMLElement.prototype,获得三个新的prototype。当剖析器开掘我们在文档中标志它将检查是还是不是二个名叫createdCallback的主意。假如找到这几个法子它将立刻运行它,所以我们把克隆模板的源委来创立的ShadowDom。

谈到底,registerElement的形式传递我们的prototype来注册自定义标签。

地方的代码初始略显复杂了,把前边三个手艺“模板”“shadowDom”结合,形成组件的中间逻辑。最终通过registerElement的措施注册组件。之后方可快乐地<datapicker></datapicker>的使用。

4. imports化解组件间的依赖性

XHTML

<link rel="import" href="datapciker.html">

1
<link rel="import" href="datapciker.html">

其一类php最常用的html导入成效,HTML原生也能匡助了。

WebComponents标准内容差非常的少到这里,是的,小编这里未有啥样德姆o,也并未试行经验共享。由于webComponents新性情,基本三巳了高版本的Chrome扶持外,别的浏览器的支撑度甚少。尽管有polymer协助推动webcompoents的仓库储存在,可是polymer本身的渴求版本也是相当高(IE10 )。所以今日的栋梁并不是她。

作者们简要来回想一下WebCompoents的四片段机能:

1 .<template>定义组件的HTML模板技艺

  1. Shadow Dom封装组件的内部结构,并且维持其独立性

  2. Custom Element 对外提供组件的竹签,落成自定义标签

  3. import化解组件结合和凭借加载

 组件化实行方案

法定的标准看完了,大家理念一下。一份真正成熟可信赖的组件化方案,需求具备的力量。

“财富高内聚”—— 组件财富内部高内聚,组件资源由自己加载调控

“功用域独立”—— 内部结构密闭,不与全局或任何零件发生震慑

“自定义标签”—— 定义组件的施用方式

“可互相结合”—— 组件正在有力的地方,组件间组装整合

“接口规范化”—— 组件接口有联合标准,可能是生命周期的保管

个体认为,模板技艺是基础技能,跟是还是不是组件化未有强联系,所以并未提议多个大点。

既然是实践,现阶段WebComponent的支撑度还不成熟,不可能充任方案的花招。而除此以外一套以高品质虚构Dom为切入点的零部件框架React,在facebook的造势下,社区获得了大力发展。别的一名骨干Webpack,担负化解组件能源内聚,同时跟React极其符合形成补充。

所以【Webpack】 【React】将会是那套方案的大旨技艺。

不了解你今后是“又是react webpack”感觉失望图片 6,照旧“太好了是react webpack”不用再学二次新框架的开心图片 7。无论怎么样上面包车型客车内容不会让您失望的。

一,组件生命周期

图片 8

React天生便是强制性组件化的,所以能够从根性子上缓和面向进程代码所带来的辛勤。React组件自个儿有生命周期方法,能够知足“接口规范化”技巧点。并且跟“页面结构模块化”的所封装抽离的多少个方法能挨个对应。其他react的jsx自带模板功效,把html页面片间接写在render方法内,组件内聚性尤其严俊。

出于React编写的JSX是会先生成虚构Dom的,需求机会才真正插入到Dom树。使用React必供给通晓组件的生命周期,其生命周期多个状态:

Mount: 插入Dom

Update: 更新Dom

Unmount: 拔出Dom

mount那单词翻译扩展,嵌入等。作者倒是建议“插入”越来越好精晓。插入!拔出!插入!拔出!默念贰遍,懂了没?别少看黄段子的力量,

图片 9

零件状态正是: 插入-> 更新 ->拔出。

然后各样组件状态会有三种管理函数,一前一后,will函数和did函数。

componentWillMount()  准备插入前

componentDidlMount()  插入后

componentWillUpdate() 计划更新前

componentDidUpdate()  更新后

componentWillUnmount() 筹算拔出前

因为拔出后基本都是贤者形态(作者说的是组件),所以未有DidUnmount那些主意。

除此以外React别的贰个宗旨:数据模型props和state,对应着也可能有自个状态方法

getInitialState()     获取开端化state。

getDefaultProps() 获取暗中认可props。对于那贰个未有父组件传递的props,通过该措施设置默许的props

componentWillReceiveProps()  已插入的组件收到新的props时调用

再有贰个卓殊意况的管理函数,用于优化管理

shouldComponentUpdate():决断组件是或不是要求update调用

丰裕最要害的render方法,React本身带的诀要刚刚好12个。对于初学者的话是相比难以消化吸收。但骨子里getInitialStatecomponentDidMountrender三个状态方法都能产生当先八分之四零部件,不必惧怕。

归来组件化的宗旨。

三个页面结构模块化的零件,能独立包装整个组件的进程线

图片 10

大家换算成React生命周期方法:

图片 11

 

零件的动静方法流中,有两点须求极其表明:

1,贰遍渲染:

由于React的杜撰Dom性情,组件的render函数不需和谐触发,依照props和state的变动自个通过差别算法,得出最优的渲染。

伸手CGI日常都以异步,所以料定带来三次渲染。只是空数据渲染的时候,有不小希望会被React优化掉。当数码回来,通过setState,触发叁遍render

 

2,componentWiillMount与componentDidMount的差别

和大许多React的教程小说不一致样,ajax央浼小编提出在WillMount的办法内实施,并不是组件早先化成功之后的DidMount。那样能在“空数据渲染”阶段在此以前央求数据,尽早地缩小三遍渲染的小运。

willMount只会执行三次,特别切合做init的业务。

didMount也只会实践叁回,何况这时候真实的Dom已经产生,非常切合事件绑定和complete类的逻辑。

 

 二,JSX很难看,可是组件内聚的要紧!

WebComponents的标准之一,须要模板本事。本是认为是我们耳闻则诵的沙盘技能,但React中的JSX那样的奇人还是令人言三语四。React还不曾火起来的时候,我们就早就在和讯上尖锐地嘲谑了“JSX写的代码那TM的丑”。那件事实上只是德姆o阶段JSX,等到实战的大型项目中的JSX,包涵多情形相当多据多事件的时候,你会意识………….JSX写的代码还是极不好看。

图片 12
(固然用sublime-babel等插件高亮,逻辑和渲染耦合一同,阅读性依旧略差)

为什么我们会感到丑?因为我们曾经经对“视图-样式-逻辑”分离的做法默化潜移。

据说维护性和可读性,以至质量,咱们都不提议直接在Dom下面绑定事件只怕间接写style属性。大家会在JS写事件代理,在CSS上写上classname,html上的就是明显的Dom结构。大家很好地维护着MVC的设计情势,一切平安。直到JSX把她们都夹杂在共同,所守护的技术栈受到凌犯,难免有着抗拒。

 

唯独从组件化的目标来看,这种高内聚的做法未尝不可。

上边包车型客车代码,以前的“逻辑视图分离”格局,大家要求去找相应的js文件,相应的event函数体内,找到td-info的class所绑定的事件。

对待起JSX的可观内聚,不论什么事件逻辑正是在本身jsx文件内,绑定的即是自个儿的showInfo方法。组件化的性状能马上体现出来。

(注意:固然写法上大家好疑似HTML的内联事件管理器,可是在React底层并从未实际赋值类似onClick属性,内层依然使用类似事件代理的不二秘技,高效地保证着事件管理器)

再来看一段style的jsx。其实jsx未有对体制有硬性规定,大家一同可比照此前的定义class的逻辑。任何一段样式都应当用class来定义。在jsx你也截然能够这么做。可是出于组件的独立性,作者提议部分唯有“二遍性”的样式直接行使style赋值更加好。减少冗余的class。

XHTML

<div className="list" style={{background: "#ddd"}}> {list_html} </div>

1
2
3
<div className="list" style={{background: "#ddd"}}>
   {list_html}
</div>

大概JSX内部有担负琐碎的逻辑样式,可JSX的自定义标签技术,组件的黑盒性立马能体会出来,是否一弹指顷美好了无数。

JavaScript

render: function(){ return ( <div> <Menus bannerNums={this.state.list.length}></Menus> <TableList data={this.state.list}></TableList> </div> ); }

1
2
3
4
5
6
7
8
render: function(){
    return (
      <div>
         <Menus bannerNums={this.state.list.length}></Menus>
         <TableList data={this.state.list}></TableList>
      </div>
   );
}

虽说JSX本质上是为着设想Dom而计划的,但这种逻辑和视图中度合一对于组件化未尝不是一件好事。

 

读书完React那些组件化框架后,看看组件化手艺点的成功意况

“财富高内聚”—— (33%)  html与js内聚

“效能域独立”—— (二分一)  js的作用域独立

“自定义标签”—— (百分之百)jsx

“可交互结合”—— (百分之五十)  可组成,但贫乏使得的加载形式

“接口标准化”—— (百分之百)组件生命周期方法

 

Webpack 能源组件化

对于组件化的能源独立性,平常的模块加载工具和营造流程视乎变得吃力。组件化的营造筑工程程化,不再是事先我们广阔的,css合二,js合三,而是体验在组件间的重视于加载关系。webpack正好符合须求点,一方面填补组件化本事点,另一方协理大家完善组件化的总体营造处境。

先是要阐宾博(Karicare)点是,webpack是二个模块加载打包工具,用于管理你的模块能源注重打包难题。那跟大家纯熟的requirejs模块加载工具,和grunt/gulp营造工具的定义,多多少少有些出入又有一点点雷同。

图片 13

率先webpak对于CommonJS与英特尔同时帮助,知足大家模块/组件的加载方式。

JavaScript

require("module"); require("../file.js"); exports.doStuff = function() {}; module.exports = someValue;

1
2
3
4
require("module");
require("../file.js");
exports.doStuff = function() {};
module.exports = someValue;

JavaScript

define("mymodule", ["dep1", "dep2"], function(d1, d2) { return someExportedValue; });

1
2
3
define("mymodule", ["dep1", "dep2"], function(d1, d2) {
    return someExportedValue;
});

自然最刚劲的,最特出的,当然是模块打包效率。这正是这一成效,补充了组件化财富信赖,以至完整工程化的本事

基于webpack的安插性观念,全部财富都是“模块”,webpack内部贯彻了一套财富加运载飞机制,可以把想css,图片等财富等有依赖关系的“模块”加载。那跟大家选拔requirejs这种只有管理js大大分歧。而那套加运载飞机制,通过叁个个loader来完毕。

 

JavaScript

// webpack.config.js module.exports = { entry: { entry: './index.jsx', }, output: { path: __dirname, filename: '[name].min.js' }, module: { loaders: [ {test: /.css$/, loader: 'style!css' }, {test: /.(jsx|js)?$/, loader: 'jsx?harmony', exclude: /node_modules/}, {test: /.(png|jpg|jpeg)$/, loader: 'url-loader?limit=10240'} ] } };

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// webpack.config.js
module.exports = {
    entry: {
     entry: './index.jsx',
    },
    output: {
        path: __dirname,
        filename: '[name].min.js'
    },
    module: {
        loaders: [
            {test: /.css$/, loader: 'style!css' },
            {test: /.(jsx|js)?$/, loader: 'jsx?harmony', exclude: /node_modules/},
            {test: /.(png|jpg|jpeg)$/, loader: 'url-loader?limit=10240'}
        ]
    }
};

上面一份简单的webpack配置文件,在乎loaders的安排,数组内叁个object配置为一种模块财富的加运载飞机制。test的正则为合作文件准绳,loader的为相配到文件将由什么加载器管理,八个Computer之间用相隔,管理顺序从右到左。

 

style!css,css文件通过css-loader(管理css),再到style-loader(inline到html)的加工管理流。

jsx文件通过jsx-loader编写翻译,‘?’开启加载参数,harmony扶助ES6的语法。

图表财富通过url-loader加载器,配置参数limit,调整少于10KB的图片将会base64化。

 财富文件怎样被require?

JavaScript

// 加载组件本人css require('./slider.css'); // 加载组件依赖的模块 var Clip = require('./clipitem.js'); // 加载图片能源 var spinnerImg = require('./loading.png');

1
2
3
4
5
6
// 加载组件自身css
require('./slider.css');
// 加载组件依赖的模块
var Clip = require('./clipitem.js');
// 加载图片资源
var spinnerImg = require('./loading.png');

在webpack的js文件中我们除了require大家例行的js文件,css和png等静态文件也得以被require进来。大家透过webpack命令,编写翻译之后,看看输出结果什么:

JavaScript

webpackJsonp([0], { /* 0 */ /***/ function(module, exports, __webpack_require__) { // 加载组件自己css __webpack_require__(1); // 加载组件依赖的模块 var Clip = __webpack_require__(5); // 加载图片能源 var spinnerImg = __webpack_require__(6); /***/ }, /* 1 */ /***/ function(module, exports, __webpack_require__) { /***/ }, /* 2 */ /***/ function(module, exports, __webpack_require__) { exports = module.exports = __webpack_require__(3)(); exports.push([module.id, ".slider-wrap{rn position: relative;rn width: 100%;rn margin: 50px;rn background: #fff;rn}rnrn.slider-wrap li{rn text-align: center;rn line-height: 20px;rn}", ""]); /***/ }, /* 3 */ /***/ function(module, exports) { /***/ }, /* 4 */ /***/ function(module, exports, __webpack_require__) { /***/ }, /* 5 */ /***/ function(module, exports) { console.log('hello, here is clipitem.js') ; /***/ }, /* 6 */ /***/ function(module, exports) { module.exports = "data:image/png;base64,iVBORw0KGg......" /***/ } ]);

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
webpackJsonp([0], {
/* 0 */
/***/ function(module, exports, __webpack_require__) {
          // 加载组件自身css
          __webpack_require__(1);
          // 加载组件依赖的模块
          var Clip = __webpack_require__(5);
          // 加载图片资源
          var spinnerImg = __webpack_require__(6);
/***/ },
/* 1 */
/***/ function(module, exports, __webpack_require__) {
 
/***/ },
/* 2 */
/***/ function(module, exports, __webpack_require__) {
          exports = module.exports = __webpack_require__(3)();
          exports.push([module.id, ".slider-wrap{rn position: relative;rn width: 100%;rn margin: 50px;rn background: #fff;rn}rnrn.slider-wrap li{rn text-align: center;rn line-height: 20px;rn}", ""]);
 
/***/ },
/* 3 */
/***/ function(module, exports) {
 
/***/ },
 
/* 4 */
/***/ function(module, exports, __webpack_require__) {
/***/ },
 
/* 5 */
/***/ function(module, exports) {
          console.log('hello, here is clipitem.js') ;
/***/ },
/* 6 */
/***/ function(module, exports) {
          module.exports = "data:image/png;base64,iVBORw0KGg......"
/***/ }
]);

webpack编写翻译之后,输出文件视乎乱糟糟的,但骨子里每四个能源都被封装在四个函数体内,况兼以编号的样式标志(注释)。那一个模块,由webpack的__webpack_require__中间方法加载。入口文件为编号0的函数index.js,能够看见__webpack_require__加载其余编号的模块。

css文件在编号1,由于应用css-loader和style-loader,编号1-4都以拍卖css。此中编号2我们能够看大家的css的string体。最后会以内联的秘籍插入到html中。

图形文件在号码6,能够看出exports出base64化的图形。

 组件一体输出

JavaScript

// 加载组件自己css require('./slider.css'); // 加载组件信任的模块 var React = require('react'); var Clip = require('../ui/clipitem.jsx'); // 加载图片能源 var spinnerImg = require('./loading.png'); var Slider = React.createClass({ getInitialState: function() { // ... }, componentDidMount: function(){ // ... }, render: function() { return ( <div> <Clip data={this.props.imgs} /> <img className="loading" src={spinnerImg} /> </div> ); } }); module.exports = Slider;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 加载组件自身css
require('./slider.css');
// 加载组件依赖的模块
var React = require('react');
var Clip = require('../ui/clipitem.jsx');
// 加载图片资源
var spinnerImg = require('./loading.png');
var Slider = React.createClass({
    getInitialState: function() {
        // ...
    },
    componentDidMount: function(){
        // ...
    },
    render: function() {
        return (
            <div>
               <Clip data={this.props.imgs} />
               <img className="loading" src={spinnerImg} />
            </div>
        );
    }
});
module.exports = Slider;

若是说,react使到html和js合为一体。

那么丰硕webpack,两个结合一同的话。js,css,png(base64),html 全部web财富都能合成叁个JS文件。那多亏那套方案的基本所在:组件独立一体化。要是要引用三个零件,仅仅require('./slider.js') 就能够实现。

 

步向webpack的模块加载器之后,大家组件的加载难点,内聚难点也都职业有成地消除掉

“能源高内聚”—— (100%) 全体能源得以一js出口

“可相互结合”—— (百分百)  可结合可依附加载

 

 CSS模块化实行

很欢腾,你能阅读到此地。目前大家的零部件实现度非常的高,财富内聚,易于组合,功能域独立互不污染。。。。等等图片 14,视乎CSS模块的实现度有欠缺。

那么近期组件完结度来看,CSS作用域其实是全局性的,并不是组件内部独立。下一步,大家要做得正是什么让大家组件内部的CSS作用域独立。

那儿恐怕有人马上跳出,大喊一句“德玛西亚!”,哦不,应该是“用sass啊傻逼!”。可是品种组件化之后,组件的此中封装已经很好了,其内部dom结交涉css趋向不难,独立,以至是满目疮痍的。LESS和SASS的一体式样式框架的安排,他的嵌套,变量,include,函数等丰盛的法力对于全体大型项指标体裁管理特别有效。但对于一个功力单一组件内部样式,视乎就变的有一些水火不容。“无法为了框架而框架,合适才是最棒的”。视乎原生的css本事已经满足组件的体制必要,唯独就是上边的css功用域难题。

 

这里本身付诸考虑的方案: classname随意写,保持原生的秘籍。编译阶段,依据组件在类型路径的独一性,由【组件classname 组件独一路线】打成md5,生成全局独一性classname。正当自个儿要写八个loader达成笔者的主张的时候,发掘歪果仁已经早在先走一步了。。。。

此处具体方案参照他事他说加以考察作者事先博客的译文:

后边大家商议过JS的模块。今后通过Webpack被加载的CSS财富叫做“CSS模块”?笔者感觉照旧有标题标。现在style-loader插件的贯彻精神上只是成立link[rel=stylesheet]要素插入到document中。这种作为和通常引入JS模块极其例外。引进另八个JS模块是调用它所提供的接口,但引入三个CSS却并不“调用”CSS。所以引进CSS自个儿对于JS程序来讲并不设有“模块化”意义,纯粹只是表明了一种财富信任——即该零件所要完成的功力还索要或多或少asset。

从而,那位歪果仁还扩充了“CSS模块化”的概念,除了上面的大家要求有的成效域外,还大概有众多效应,这里不详述。具体参照他事他说加以考察原来的书文 

格外赞的有些,正是cssmodules已经被css-loader收纳。所以我们无需依赖额外的loader,基本的css-loader开启参数modules就可以

JavaScript

//webpack.config.js ... module: { loaders: [ {test: /.css$/, loader: 'style!css?modules&localIdentName=[local]__[name]_[hash:base64:5]' }, ] } ....

1
2
3
4
5
6
7
8
//webpack.config.js
...  
    module: {
        loaders: [
            {test: /.css$/, loader: 'style!css?modules&localIdentName=[local]__[name]_[hash:base64:5]' },
        ]  
    }
....

modules参数代表开启css-modules功效,loaclIdentName为设置大家编写翻译后的css名字,为了有助于debug,大家把classname(local)和组件名字(name)输出。当然能够在最终输出的本子为了节省提交,仅仅使用hash值就能够。另外在react中的用法差没有多少如下。

JavaScript

var styles = require('./banner.css'); var Banner = new React.createClass({ ... render: function(){ return ( <div> <div className={styles.classA}></div> </div> ) } });

1
2
3
4
5
6
7
8
9
10
11
var styles = require('./banner.css');
var Banner = new React.createClass({
    ...
    render: function(){
        return (
            <div>
                <div className={styles.classA}></div>
            </div>
        )
    }
});

末段这里关于出于对CSS一些合计,

至于css-modules的别的成效,作者并不准备选用。在里边分享【大家竭尽所能地让CSS变得复杂】中聊到:

大家项目中相当多的CSS都不会像boostrap那样须求变量来安装,身为一线开辟者的大家大意能够感受到:设计员们改版UI,绝对不是轻易的换个色或改个间距,而是万物更新的全新UI,那相对不是三个变量所能化解的”维护性“。

反倒项目实战进度中,真正要消除的是:在本子迭代进程中这二个淘汰掉的晚点CSS,大批量地积聚在档案的次序个中。大家像极了家中的欧巴酱不舍得吐弃没用的事物,因为那只是大家应用sass或less编写出具有莫斯中国科学技术大学学的可维护性的,确定有复用的一天。

这几个聚积的超时CSS(or sass)之间又有部分重视,一部分超时失效了,一部分又被新的体裁复用了,导致没人敢动那个历史样式。结果现网项目迭代还带着大量三年前没用的体制文件。

组件化之后,css的布局同样被改造了。恐怕postcss才是你今后手上最符合的工具,而不在是sass。

 

到此地,我们算是把组件化最终三个标题也消除了。

“成效域独立”—— (百分之百) 就如shadowDom成效域独立

 

到这里,大家得以开一瓶82年的百事可乐,好好庆祝一下。不是吗?

图片 15

 

 组件化之路还在一连

webpack和react还会有比很多新特别主要的表征和职能,介于本文仅仅围绕着组件化的为着力,未有种种解说。别的,配搭gulp/grunt补充webpack营造手艺,webpack的codeSplitting,react的零部件通讯难题,开垦与生产条件布置等等,都以成套大型项目方案的所不可不的,限于篇幅难题。能够等等小编更新下篇,或我们能够活动查阅。

然则,不得不再安利一下react-hotloader神器。热加载的开支方式相对是下一代前端开垦必备。严苛说,若无了热加载,作者会很泼辣地遗弃那套方案,纵然这套方案再怎么能够,小编都讨厌react必要5~6s的编写翻译时间。不过hotloader能够在笔者不刷新页面包车型客车图景下,动态修改代码,而且不单单是样式,连逻辑也是即时生效。

图片 16

如上在form表单内。使用热加载,表单没有须求再行填写,修改submit的逻辑登时见效。那样的支出功效真不是抓牢仅仅贰个水平。必需安利一下。

 

或者你意识,使用组件化方案以往,整个技艺栈都被更新了一番。学习费用也不菲,何况能够预见到,基于组件化的前端还只怕会过多相差的主题素材,譬如质量优化方案供给再度思索,以至最主旨的零件可复用性不鲜明高。前面不短一段时间,必要我们不断磨砺与优化,索求最优的前端组件化之道。

最少大家能够设想,不再挂念自个儿写的代码跟某些什么人何人冲突,不再为找某段逻辑在八个文件和办法间穿梭,不再copy一片片逻辑然后改改。我们每便编写都以可选拔,可组合,独立且内聚的零部件。而各样页面将会由一个个嵌套组合的机件,相互独立却相互效用。

 

对于如此的前端今后,有所期望,不是很好呢

从这之后,多谢你的阅读。

1 赞 6 收藏 1 评论

图片 17

本文由新浦京娱乐场官网-301net-新浦京娱乐www.301net发布于301net网站建设,转载请注明出处:我说按模块划分好

您可能还会对下面的文章感兴趣: