ag旗舰厅官网_ag旗舰厅下载客户端

热门关键词: ag旗舰厅官网,ag旗舰厅下载客户端

前端技术

当前位置:ag旗舰厅官网 > 前端技术 > 致我们终将组件化的Web

致我们终将组件化的Web

来源:http://www.pedaLyourcycLe.com 作者:ag旗舰厅官网 时间:2019-11-26 12:48

致大家必定将组件化的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…卡塔 尔(英语:State of Qatar),杜绝了以前的不可能则乱增代码的行文。何况,依据差别职业逻辑封装区别档次的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自个儿带的办法刚刚好11个。对于初读书人的话是比较麻烦消化吸取。但实质上getInitialStatecomponentDidMountrender四个意况方法都能成功大部分组件,不必惧怕。

再次来到组件化的核心。

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

图片 10

我们换算成React生命周期方法:

图片 11

 

构件的情形方法流中,有两点须要新鲜表达:

1,三次渲染:

出于React的捏造Dom性格,组件的render函数不需本身触发,遵照props和state的退换自个通过差别算法,得出最优的渲染。

央浼CGI日常都以异步,所以自然带给二遍渲染。只是空数据渲染的时候,有非常的大恐怕会被React优化掉。当数码回来,通过setState,触发叁回render

 

2,componentWiillMount与componentDidMount的差别

和大超级多React的学科随笔不相似,ajax供给笔者提出在威尔Mount的章程内实施,并不是组件初步化成功现在的DidMount。那样能在“空数据渲染”阶段以前诉求数据,尽早地压缩二回渲染的岁月。

willMount只会举办一次,特别符合做init的业务。

didMount也只会施行叁回,何况那个时候真实的Dom已经产生,特别切合事件绑定和complete类的逻辑。

 

 二,JSX非常不好看,但是组件内聚的最主要!

WebComponents的专门的职业之意气风发,须求模板技能。本是感觉是我们熟识的模版技术,但React中的JSX这样的怪人依然令人胡言乱语。React还不曾火起来的时候,大家就早就在博客园上狠狠地戏弄了“JSX写的代码那TM的丑”。这实则只是德姆o阶段JSX,等到实战的大型项目中的JSX,包含多情状许多据多事件的时候,你会意识………….JSX写的代码依旧超难看。

图片 12
(纵然用sublime-babel等插件高亮,逻辑和渲染耦合一同,阅读性依然略差卡塔 尔(英语:State of Qatar)

缘何大家会感到丑?因为大家已经经对“视图-样式-逻辑”分离的做法潜移默化。

基于维护性和可读性,以至质量,我们都不提出直接在Dom上面绑定事件或然间接写style属性。大家会在JS写事件代理,在CSS上写上classname,html上的正是清楚的Dom结构。大家很好地保障着MVC的设计方式,一切因祸得福。直到JSX把她们都夹杂在协同,所守护的工夫栈受到侵袭,难免存有抗拒。

 

但是从组件化的指标来看,这种高内聚的做法未尝不可。

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

相对来说起JSX的冲天内聚,所有事件逻辑就是在小编jsx文件内,绑定的正是本身的showInfo方法。组件化的特点能登时体现出来。

(注意:固然写法上大家好疑似HTML的内联事件微处理机,可是在React底层并不曾实际赋值相像onClick属性,内层依旧采纳雷同事件代理的议程,高效地维护着事件微电脑卡塔 尔(英语:State of Qatar)

再来看生机勃勃段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%卡塔 尔(英语:State of Qatar)  html与js内聚

“成效域独立”—— (四分之二卡塔尔  js的效用域独立

“自定义标签”—— (百分之百卡塔尔jsx

“可相互结合”—— (八分之四卡塔 尔(阿拉伯语:قطر‎  可结合,但缺稀有效的加载格局

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

 

Webpack 能源组件化

对于组件化的能源独立性,平日的模块加载工具和创设流程视乎变得费力。组件化的营造筑工程程化,不再是事先大家相近的,css合二,js合三,而是体验在组件间的依赖性于加载关系。webpack无独有偶合乎必要点,一方面增补组件化手艺点,另一方扶助大家完善组件化的一体化塑造碰着。

先是要阐贝因美点是,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的为相称到文件将由什么加载器管理,五个计算机之间用相隔,管理顺序从右到左。

 

style!css,css文件通过css-loader(管理css卡塔 尔(英语:State of Qatar),再到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输出

“可相互结合”—— (百分百卡塔 尔(英语:State of Qatar)  可结合可依据加载

 

 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卡塔 尔(英语:State of Qatar)之间又有风流洒脱对正视,后生可畏部分超时失效了,生机勃勃部分又被新的体裁复用了,招致没人敢动那几个历史样式。结果现网项目迭代还带着多量五年前没用的体制文件。

组件化之后,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卡塔 尔(英语:State of Qatar)来打包
$ 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 :
在 AMD/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 了。

本文由ag旗舰厅官网发布于前端技术,转载请注明出处:致我们终将组件化的Web

关键词:

上一篇:掌握SVG坐标系和转变,坐标与转变

下一篇:没有了