美高梅网投网站-美高梅手机网投-美高梅官方网站
做最好的网站

您的位置:美高梅网投网址 > Web前端 > 【美高梅官方网站】我说按模块划分好,图片等

【美高梅官方网站】我说按模块划分好,图片等

发布时间:2019-09-27 05:21编辑:Web前端浏览(50)

    致咱们终将组件化的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本人带的主意刚刚好13个。对于初学者的话是比较难以消食。但骨子里getInitialStatecomponentDidMountrender多个状态方法都能成就超过56%零部件,不必惧怕。

    回去组件化的大旨。

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

    美高梅官方网站 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正好符合要求点,一方面填补组件化才具点,另一方扶助大家完善组件化的一体化创设情状。

    第一要申美素佳儿(Friso)点是,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的模块加载器之后,大家组件的加载难点,内聚难点也都成功地消除掉

    “能源高内聚”—— (百分之百) 全体财富能够一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

    一、什么是webpack:webpack是一款模块加载兼打包工具,它能够将js、jsx、coffee、样式sass、less,图片等作为模块来使用和拍卖。
    二、优势:1、以commonJS的花样来书写脚本,对英特尔、CMD的帮助也很周详,方便旧项指标搬迁。2、能被模块化的不仅是JS了。3、能替代部分grunt/gulp的干活,比方打包,压缩混淆,图片转base64等。3、增加性强,插件机制完善,协助React热拔插(react-hot-loader)
    三、安装和配置:
    1、安装:直接利用npm来展开安装
    $ npm install webpack -g
    将凭仗写入package.json包
    $ npm init
    $ npm install webpack --save-dev
    2、配置:
    各样连串必需安插一个webpack.config.js,作用就像是gulpfile.js/Gruntfile.js,三个布局项,告诉webpack要做怎么样。
    示例:
    var webpack = require('webpack');
    var commonsPlugin = new webpack.optimize.CommonsChunkPlugin('common.js');
    module.exports = {
    //插件项
    plugins: [commonsPlugin],
    //页面入口文件配置
    entry: {
    index : './src/js/page/index.js'
    },
    //入口文件输出配置
    output: {
    path: 'dist/js/page',
    filename: '[name].js'
    },
    module: {
    //加载器配置
    loaders: [
    { test: /.css$/, loader: 'style-loader!css-loader' },
    { test: /.js$/, loader: 'jsx-loader?harmony' },
    { test: /.scss$/, loader: 'style!css!sass?sourceMap'},
    { test: /.(png|jpg)$/, loader: 'url-loader?limit=8192'}
    ]
    },
    //另外建设方案安插
    resolve: {
    root: 'E:/github/flux-example/src', //相对路径
    extensions: ['', '.js', '.json', '.scss'],
    alias: {
    AppStore : 'js/stores/AppStores.js',
    ActionType : 'js/actions/ActionType.js',
    AppAction : 'js/actions/AppAction.js'
    }
    }
    };
    (1)plugins是插件项,这里运用了二个CommonsChunkPlugin的插件,它用于提取三个输入文件的集体脚本有的,然后生成叁个common.js来方便多页面之间的复用。
    (2)entry是页面包车型地铁进口文件配置,output是对应的出口项配置
    {
    entry: {
    page1: "./page1",
    //帮忙数组情势,将加载数组中的全体模块,但以最终八个模块作为出口
    page2: ["./entry1", "./entry2"]
    },
    output: {
    path: "dist/js/page",
    filename: "[name].bundle.js"
    }
    }
    该代码会转换三个page1.bundle.js和page2.bundle.js,并寄存在./dist/js/page文件夹下。
    (3)module.loaders,告知webpack各个文件都亟待什么样加载器来拍卖
    module: {
    //加载器配置
    loaders: [
    //.css 文件使用 style-loader 和 css-loader 来拍卖
    { test: /.css$/, loader: 'style-loader!css-loader' },
    //.js 文件使用 jsx-loader 来编写翻译管理
    { test: /.js$/, loader: 'jsx-loader?harmony' },
    //.scss 文件使用 style-loader、css-loader 和 sass-loader 来编写翻译处理
    { test: /.scss$/, loader: 'style!css!sass?sourceMap'},
    //图片文件使用 url-loader 来拍卖,小于8kb的直白转为base64
    { test: /.(png|jpg)$/, loader: 'url-loader?limit=8192'}
    ]
    }
    -loader能够不写,七个loader之间用“!”连接起来。全部的加载器都亟需经过npm来加载。
    比方说最终贰个url-loader,它会将样式中援引到的图形转为模块来管理。使用前开展安装:
    $ npm install url-loader -save-dev
    布置新闻的参数:“?limit=8192”表示将具有小于8kb的图纸都转为base64格局(超越8kb的才使用url-loader来映射到文件,否则转为data url情势)
    (4)resolve配置,
    resolve: {
    //查找module的话从此处起初查找
    root: 'E:/github/flux-example/src', //绝对路径
    //自动扩大文件后缀名,意味着大家require模块能够轻便不写后缀名
    extensions: ['', '.js', '.json', '.scss'],
    //模块外号定义,方便后续直接引用小名,无须多写长长的地址
    alias: {
    AppStore : 'js/stores/AppStores.js',//后续直接 require('AppStore') 就能够
    ActionType : 'js/actions/ActionType.js',
    AppAction : 'js/actions/AppAction.js'
    }
    }
    四、运营webpack,直接实行:
    $ webpack --display-error-details
    背后的参数 “-display-error-details”推荐加上,方便出错开上下班时间能明白到更详实的新闻。其余首要参数:
    $ webpack --config XXX.js //使用另一份配置文件(举例webpack.config2.js)来打包
    $ webpack --watch //监听变动并机关打包
    $ webpack -p //压缩混淆脚本,那些非常可怜关键!
    $ webpack -d //生成map映射文件,告知哪些模块被最后包装到哪个地方了
    -p是很首要的参数,曾经二个未压缩的 700kb 的文件,压缩后一向降到 180kb(首借使样式这块一句就私吞一行脚本,导致未压缩脚本变得非常大)。
    五、模块引入:
    1、在HTML页面引入:引进webpack最后生成的本子就能够:
    <!DOCTYPE html>
    <html>
    <head lang="en">
    <meta charset="UTF-8">
    <title>demo</title>
    </head>
    <body>
    <script src="dist/js/page/common.js"></script>
    <script src="dist/js/page/index.js"></script>
    </body>
    </html>
    能够看到大家连样式都实际不是引进,毕竟脚本推行时会动态生成style并标签打到head里。
    2、JS引进:各脚本模块能够选择common.js来书写,并得以平昔引进未经编写翻译的模块,比方:jsx,coffee,sass,只要在webpack.config.js中配备好了对应的加载器就行。
    编写翻译页面包车型客车入口文件:
    require('../../css/reset.scss'); //加载起头化样式
    require('../../css/allComponent.scss'); //加载组件样式
    var React = require('react');
    var AppWrap = require('../component/AppWrap'); //加载组件
    var createRedux = require('redux').createRedux;
    var Provider = require('redux/react').Provider;
    var stores = require('AppStore');
    var redux = createRedux(stores);
    var App = React.createClass({
    render: function() {
    return (
    <Provider redux={redux}>
    {function() { return <AppWrap />; }}
    </Provider>
    );
    }
    });
    React.render(
    <App />, document.body
    );

    其他:
    1、shimming :
    在 英特尔/CMD 中,我们必要对不切合规范的模块(比方一些平昔回到全局变量的插件)进行shim 管理,那时候大家须求选拔 exports-loader 来赞助:
    { test: require.resolve(“./src/js/tool/swipe.js”), loader: “exports?swipe”}
    自此在剧本中须求援引该模块的时候,这么简单地来采纳就足以了:
    require(‘./tool/swipe.js’);
    swipe();
    2、自定义公共模块提取:
    在篇章开首我们运用了 CommonsChunkPlugin 插件来提取多少个页面之间的公共模块,并将该模块打包为 common.js 。
    但奇迹大家盼望能进一步特性化一些,咱们能够那样安插:
    var CommonsChunkPlugin = require("webpack/lib/optimize/CommonsChunkPlugin");
    module.exports = {
    entry: {
    p1: "./page1",
    p2: "./page2",
    p3: "./page3",
    ap1: "./admin/page1",
    ap2: "./admin/page2"
    },
    output: {
    filename: "[name].js"
    },
    plugins: [
    new CommonsChunkPlugin("admin-commons.js", ["ap1", "ap2"]),
    new CommonsChunkPlugin("commons.js", ["p1", "p2", "admin-commons.js"])
    ]
    };
    // <script>s required:
    // page1.html: commons.js, p1.js
    // page2.html: commons.js, p2.js
    // page3.html: p3.js
    // admin-page1.html: commons.js, admin-commons.js, ap1.js
    // admin-page2.html: commons.js, admin-commons.js, ap2.js
    3、独立包装样式:
    一时大概希望项目的体制能不用被打包到脚本中,而是独立出来作为.css,然后在页面中以标签引进。那时候大家要求extract-text-webpack-plugin 来赞助:
    var webpack = require('webpack');
    var commonsPlugin = new webpack.optimize.CommonsChunkPlugin('common.js');
    var ExtractTextPlugin = require("extract-text-webpack-plugin");
    module.exports = {
    plugins: [commonsPlugin, new ExtractTextPlugin("[name].css")],
    entry: {
    //...省略别的配置
    提起底 webpack 实施后会乖乖地把体制文件提收取来:
    4、使用CDN远程文件:
    有的时候候大家愿意有些模块走CDN并以<script>的款型挂载到页面上来加载,但又希望能在 webpack 的模块中接纳上。
    那会儿大家得以在布置文件里使用 externals 属性来扶助:
    {
    externals: {
    // require("jquery") 是援用自外界模块的
    // 对应全局变量 jQuery
    "jquery": "jQuery"
    }
    }
    急需小心的是,得保障 CDN 文件必得在 webpack 打包文件引入从前先引进。
    我们倒也得以选用 script.js 在本子中来加载大家的模块:
    var $script = require("scriptjs");
    $script("//ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js", function() {
    $('body').html('It works!')
    });
    5、与grunt/gulp相结合:
    gulp.task("webpack", function(callback) {
    // run webpack
    webpack({
    // configuration
    }, function(err, stats) {
    if(err) throw new gutil.PluginError("webpack", err);
    gutil.log("[webpack]", stats.toString({
    // output options
    }));
    callback();
    });
    });
    本来大家只供给把布置写到 webpack({ … }) 中去就能够,无须再写 webpack.config.js 了。

    本文由美高梅网投网址发布于Web前端,转载请注明出处:【美高梅官方网站】我说按模块划分好,图片等

    关键词: