最近在學(xué)習webpack,正好拿了之前做的一個(gè)小組件,圖片輪播來(lái)做了下練手,讓我們一起來(lái)初步感受下webpack的神奇魅力。
webpack是一個(gè)前端的打包管理工具,大家可以前往:http://webpack.github.io/ 作詳細了解。相對于之前的前端模塊打包工具,
個(gè)人認為webpack至少擁有以下值得我們拿來(lái)一用的優(yōu)點(diǎn):
當前很多優(yōu)點(diǎn)是我沒(méi)有提及的或者還沒(méi)有了解到的,但是目前這幾個(gè)優(yōu)點(diǎn)來(lái)說(shuō),已經(jīng)算是可以完全滿(mǎn)足我們在項目中的實(shí)際打包需求了。
這次算是把webpack模塊打包與之前的一篇文章: http://www.cnblogs.com/souvenir/p/4977407.html 中提及的圖片輪播二者結合起來(lái),一起與大家進(jìn)行分享。
同樣的,這次我也將這次寫(xiě)的DEMO代碼分享到Github上,大家可以自行前往查看源碼: https://github.com/xiaoyunchen/easySlide/
最后的頁(yè)面效果大家可以訪(fǎng)問(wèn) http://xiaoyunchen.github.io/easySlide/ 進(jìn)行查看。
功能很簡(jiǎn)單:
可以看到,我們在這個(gè)頁(yè)面上做了兩個(gè)圖片輪播效果,而且兩個(gè)圖片輪播的時(shí)間間隔與動(dòng)畫(huà)時(shí)長(cháng)都是獨立的,互不干擾。

在開(kāi)始學(xué)習webpack打包之前,我們先要做一些準備工作。第一步當然安裝nodejs了,然后再使用npm命令安裝webpack以及我們所需要的幾個(gè)加載器:
npm install webpack -gnpm install jquery@1npm install css-loadernpm install style-loader
看完最終的效果后,我們接下來(lái)繼續來(lái)看這個(gè)簡(jiǎn)單的項目是如何使用webpack進(jìn)行打包的。
首先大家在Github可以先打開(kāi)項目的源碼,可以看到項目的目錄結構是這樣的:

最外層有幾個(gè)文件:
index.html --- 項目入口頁(yè)面
package.json --- nodejs環(huán)境下用于描述模塊包結構的文件
webpack.config.js --- webpack配置文件,稍后我們將重點(diǎn)分析這個(gè)配置文件
然后就是三個(gè)目錄:
src --- 項目開(kāi)發(fā)的源碼
node_modules --- 項目打包中用到的node模塊
dist --- 打包后最終的輸出目錄
再來(lái)看看src目錄的結構,先按照常規的css/js/img進(jìn)行劃分,然后每個(gè)目錄下在按照功能模塊進(jìn)行子目錄劃分:
module --- 通用組件
page --- 頁(yè)面應用
vendor ---引用第三方組件
這是我個(gè)人的一個(gè)目錄劃分,實(shí)際的項目中大家可以根據項目或者公司的需要進(jìn)行調整。
接著(zhù)來(lái)看入口文件:index.js
1 (function(){ 2 //引入公共CSS與頁(yè)面CSS 3 require('../../css/vendor/reset.css'); 4 require('../../css/page/index.css'); 5 6 //引入并創(chuàng )建多個(gè)獨立slideModule模塊 7 var slideModule=require("../module/slide.js"); 8 new slideModule({dom:$('[node-type="iccAdvisorPicture"]')}); 9 new slideModule({10 dom:$('[node-type="iccAdvisorPicture2"]'),11 delay:4000,12 duration:80013 });14 })();
代碼量14行,整體來(lái)說(shuō)還算是比較清爽的,這都得益于模塊打包。
在這里,我們定義并執行了一個(gè)閉包函數。主要功能就是兩個(gè):
1.加載改頁(yè)面上的公共CSS (別忘了css也是一種資源,我們可以通過(guò)webpack來(lái)進(jìn)行打包加載)
2.引入了我們自定義了slideModule組件,然后使用該組件創(chuàng )建了兩個(gè)圖片輪播的實(shí)例
就是這么簡(jiǎn)潔,這也是我們所希望的,將功能按模塊進(jìn)行開(kāi)發(fā),使用的時(shí)候按照需要進(jìn)行加載。
我們先不管slideModule是如何具體實(shí)現這個(gè)功能的,我們接著(zhù)來(lái)看webpack的配置文件:
1 var path=require('path'); 2 var webpack = require('webpack'); 3 module.exports = { 4 entry: { 5 index:"./src/js/page/index.js", 6 }, 7 output: { 8 path: path.join(__dirname,'dist'), 9 filename: "bundle.js"10 },11 module: {12 loaders: [ //css加載器13 { test: /\.css$/, loader: "style!css" }14 ]15 },16 plugins:[17 new webpack.ProvidePlugin({ //加載jq18 $: 'jquery'19 }),20 new webpack.optimize.UglifyJsPlugin({ //壓縮代碼21 compress: {22 warnings: false23 },24 except: ['$super', '$', 'exports', 'require'] //排除關(guān)鍵字25 })26 ]27 };
關(guān)于這個(gè)配置文件中詳細參數與屬性,大家可以前往webpack官網(wǎng)進(jìn)行查看。這里我們主要講解下這個(gè)配置文件所要達到的目的。
entry:入口。注意這里的路徑是相對于webpack.config.js的路徑,也就是根目錄
path:主要是定義了打包后的文件存放目錄和文件名,這里我們是將打包后的文件存放在/dist/bundle.js文件中。
module-loaders:加載器。這里我們只使用了一個(gè)CSS加載器
plugins:插件。第一個(gè)是jquery,我們將jquery加載進(jìn)行項目中并將$作為全局變量返回,所以在任何位置都可以使用jquery而且無(wú)需更多配置。
第二個(gè)是對輸出的的js代碼進(jìn)行壓縮,這一步是可選的,一般也可以將有部署服務(wù)器將部署到正式環(huán)境之前在進(jìn)行壓縮處理。
OK,接下來(lái)我們就可以使用webpack進(jìn)行打包了,在命令行切換當前項目所在目錄,然后打包使用:
webpack -w
然后僅能看到類(lèi)似于下圖的輸出結果,沒(méi)有任何報錯的話(huà)說(shuō)明打包已經(jīng)成功:

-w 是打包選項,watch的意思,webpack將監控項目的文件如果有修改變動(dòng)的時(shí)候,將會(huì )自動(dòng)運行打包命令
其他的選項還有:-p 壓縮代碼。但是一般我們都將代碼壓縮卸載配置文件中。
-d 輸出sourcemap
打包成功后我們在index.html頁(yè)面中就只需要引入/dist/bundle.js即可,連css都無(wú)需再引入。
然后就可以運行頁(yè)面查看具體的效果。
OK,webpack打包過(guò)程大概就是這樣,相信大家可能會(huì )有一些疑問(wèn),這不就是把所有資源文件都放在一個(gè)文件里面嗎,如果項目太大的話(huà),那這個(gè)文件還不得很大了。
這里就涉及到之前說(shuō)的webpack可以實(shí)現按需加載模塊,我們將在下一篇為大家進(jìn)行介紹有關(guān)內容。
接下來(lái)我們來(lái)看圖片輪播這個(gè)組件是如何實(shí)現的,以及在實(shí)現的過(guò)程如何使用webpack語(yǔ)法進(jìn)行資源加載。

這是我們的代碼截圖,所有的代碼同樣都是在一個(gè)閉包函數中的,這樣做可以避免對全局變量window的污染。
第2行我們使用require引入了一個(gè)css文件,這個(gè)CSS是專(zhuān)屬于圖片輪播模塊的,在模塊里進(jìn)行引入,屏蔽具體實(shí)現,外面的js在使用的使用不用再關(guān)心是不是還要在
引入額外的css,只需要一句話(huà)引入然后完成相應的功能。
第4行定義了一個(gè)默認配置對象,用于定義模塊的一些基礎配置,如果在使用的時(shí)候不傳入對應的參數我們將默認使用該默認配置。
第12行定義了一個(gè)方法,這個(gè)方法其實(shí)也就是我們圖片滑動(dòng)模塊的構建函數,在這個(gè)構造函數里我們首先將外層傳入的配置參數與默認參數進(jìn)行合并。
然后在根據dom選擇器重新計算圖片數量。
在19行我們使用prototype對slideModule這個(gè)方法進(jìn)行了擴展,增加了幾個(gè)處理方法
1 slideModule.prototype={ 2 init:function(){ 3 this.bindMouseEvent(); 4 this.autoPlay(); 5 }, 6 slidePic:function(){ //切換圖片 7 var that=this; 8 this.config.dom.animate({'marginLeft':-(this.config.current==this.config.total?0:this.config.current)*this.config.width+'px'},this.config.duration,function(){ 9 that.config.current++;10 if(that.config.current>that.config.total){11 that.config.current=1;12 }13 });14 },15 autoPlay:function(){ //自動(dòng)切換16 var that=this;17 this.config.timer=setInterval(function(){18 that.slidePic();19 }, this.config.delay);20 },21 bindMouseEvent:function(){ //綁定鼠標移入/移除事件22 var that=this;23 this.config.dom.mouseenter(function(){24 if(that.config.timer){25 clearInterval(that.config.timer);26 }27 });28 this.config.dom.mouseleave(function(){29 that.autoPlay();30 });31 }32 };
init:模塊初始化方法,負責調用對應函數對模塊進(jìn)行功能初始化
slidePic:圖片切換的具體實(shí)現方法,這里使用了jquery的animate方法,創(chuàng )建了一個(gè)動(dòng)畫(huà),將圖片外層父級元素marginLeft減少一個(gè)圖片的寬度
整個(gè)動(dòng)畫(huà)的時(shí)長(cháng)來(lái)自于配置信息。
滑動(dòng)動(dòng)畫(huà)結束后將修改當前顯示的是第幾個(gè)圖片,如果超過(guò)最大數量的話(huà)就設置回1,讓動(dòng)畫(huà)下次從頭開(kāi)始。
autoPlay:創(chuàng )建一個(gè)定時(shí)器,每隔一段時(shí)間自動(dòng)執行slidePic來(lái)切換圖片,從而實(shí)現了自動(dòng)輪播的效果。
這里之所以使用閉包函數,是因為作用域的原因,詳細的介紹大家可以查看之前的文章。
bindMouseEvent:這里增加了兩個(gè)鼠標事件,當鼠標移入滑動(dòng)組件區域內時(shí),清除掉定時(shí)器暫時(shí)動(dòng)畫(huà),當鼠標離開(kāi)時(shí)重新開(kāi)啟定時(shí)器,繼續執行輪播動(dòng)畫(huà)
圖片輪播的實(shí)現原理大概是這樣的:

最外層的div寬度固定,與單個(gè)圖片寬度(加載邊距)相同,同時(shí)設置了超出的部分隱藏顯示;然后ul寬度設置為很大, 至少需要N唄的圖片寬度,可以讓所有圖片放在一行
然后定時(shí)器來(lái)改變ul的margin-left值,從而達到滑動(dòng)切換的效果。
聯(lián)系客服