隨著前端功能越來越復雜,前端代碼日益膨脹,為了減少維護成本,提高代碼的可復用性,前端模塊化勢在必行。
所有js文件都在一個html中引入,造成以下不良影響:
webpack中是這樣定義的:
在模塊化編程中,開發者將程序分解成離散功能塊(discrete chunks of functionality),并稱之為模塊。 每個模塊具有比完整程序更小的接觸面,使得校驗、調試、測試輕而易舉。 精心編寫的模塊提供了可靠的抽象和封裝界限,使得應用程序中每個模塊都具有條理清楚的設計和明確的目的。
模塊應該是職責單一、相互獨立、低耦合的、高度內聚且可替換的離散功能塊。
模塊化是一種處理復雜系統分解成為更好的可管理模塊的方式,它可以把系統代碼劃分為一系列職責單一,高度解耦且可替換的模塊,系統中某一部分的變化將如何影響其它部分就會變得顯而易見,系統的可維護性更加簡單易得。
模塊化是一種分治的思想,通過分解復雜系統為獨立的模塊實現細粒度的精細控制,對于復雜系統的維護和管理十分有益。模塊化也是組件化的基石,是構成現在色彩斑斕的前端世界的前提條件。
前端開發和其他開發工作的主要區別,首先是前端是基于多語言、多層次的編碼和組織工作,其次前端產品的交付是基于瀏覽器,這些資源是通過增量加載的方式運行到瀏覽器端,如何在開發環境組織好這些碎片化的代碼和資源,并且保證他們在瀏覽器端快速、優雅的加載和更新,就需要一個模塊化系統。
function fn1(){
// ...
}
function fn2(){
// ...
}
通過 script 標簽引入文件,調用相關的函數。這樣需要手動去管理依賴順序,容易造成命名沖突,污染全局,隨著項目的復雜度增加維護成本也越來越高。
var output = {
_count: 0,
fn1: function(){
// ...
}
}
這樣可以解決上面的全局污染的問題,有那么點命名空間的意思,但是隨著項目復雜度增加需要越來越多的這樣的對象需要維護,不說別的,取名字都是個問題。最關鍵的還是內部的屬性還是可以被直接訪問和修改。
var module = (function(){
var _count = 0;
var fn1 = function (){
// ...
}
var fn2 = function fn2(){
// ...
}
return {
fn1: fn1,
fn2: fn2
}
})()
module.fn1();
module._count; // undefined
這樣就擁有獨立的詞法作用域,內存中只會存在一份 copy。這不僅避免了外界訪問此 IIFE 中的變量,而且又不會污染全局作用域,通過 return 暴露出公共接口供外界調用。這其實就是現代模塊化實現的基礎。
還有基于閉包實現的松耦合拓展、緊耦合拓展、繼承、子模塊、跨文件共享私有對象、基于 new 構造的各種方式,這種方式在現在看來都不再優雅。
// 松耦合拓展
// 這種方式使得可以在不同的文件中以相同結構共同實現一個功能塊,且不用考慮在引入這些文件時候的順序問題。
// 缺點是沒辦法重寫你的一些屬性或者函數,也不能在初始化的時候就是用module的屬性。
var module = (function(my){
// ...
return my
})(module || {})
// 緊耦合拓展(沒有傳默認參數)
// 加載順序不再自由,但是可以重載
var module = (function(my){
var old = my.someOldFunc
my.someOldFunc = function(){
// 重載方法,依然可通過old調用舊的方法...
}
return my
})(module)
歷史上,JavaScript 一直沒有模塊(module)體系,無法將一個大程序拆分成互相依賴的小文件,再用簡單的方法拼裝起來。其他語言都有這項功能,比如 Ruby 的require、Python 的import,甚至就連 CSS 都有@import,但是 JavaScript 任何這方面的支持都沒有,這對開發大型的、復雜的項目形成了巨大障礙。
在 ES6 之前,社區制定了一些模塊加載方案,最主要的有 CommonJS 和 AMD 兩種。前者用于服務器,后者用于瀏覽器。ES6 在語言標準的層面上,實現了模塊功能,而且實現得相當簡單,完全可以取代 CommonJS 和 AMD 規范,成為瀏覽器和服務器通用的模塊解決方案。
ES6 模塊的設計思想是盡量的靜態化,使得編譯時就能確定模塊的依賴關系,以及輸入和輸出的變量。CommonJS 和 AMD 模塊,都只能在運行時確定這些東西。比如,CommonJS 模塊就是對象,輸入時必須查找對象屬性。
目前實現模塊化的規范主要有:
CommonJS 是以在瀏覽器環境之外構建 JavaScript 生態系統為目標而產生的項目,比如在服務器和桌面環境中。
采用同步加載模塊的方式,也就是說只有加載完成,才能執行后面的操作。CommonJS 代表:Node 應用中的模塊,通俗的說就是你用 npm 安裝的模塊。
它使用 require 引用和加載模塊,exports 定義和導出模塊,module 標識模塊。使用 require 時需要去讀取并執行該文件,然后返回 exports 導出的內容。
//定義模塊 math.js
var random=Math.random()*10;
function printRandom(){
console.log(random)
}
function printIntRandom(){
console.log(Math.floor(random))
}
//模塊輸出
module.exports={
printRandom:printRandom,
printIntRandom:printIntRandom
}
//加載模塊 math.js
var math=require('math')
//調用模塊提供的方法
math.printIntRandom()
math.printRandom()
|-js
|-dist //打包生成文件的目錄
|-src //源碼所在的目錄
|-module1.js
|-module2.js
|-module3.js
|-app.js //應用主源文件
|-index.html //運行于瀏覽器上
|-package.json
{
"name": "browserify-test",
"version": "1.0.0"
}
注意:index.html文件要運行在瀏覽器上,需要借助browserify將app.js文件打包編譯,如果直接在index.html引入app.js就會報錯!
根目錄下運行browserify js/src/app.js -o js/dist/bundle.js
在index.html文件中引入<script type="text/javascript" src="js/dist/bundle.js"></script>
異步模塊定義,所謂異步是指模塊和模塊的依賴可以被異步加載,他們的加載不會影響它后面語句的運行。有效避免了采用同步加載方式中導致的頁面假死現象。AMD代表:RequireJS。
AMD一開始是CommonJS規范中的一個草案,全稱是Asynchronous Module Definition,即異步模塊加載機制。后來由該草案的作者以RequireJS實現了AMD規范,所以一般說AMD也是指RequireJS。
RequireJS是一個工具庫,主要用于客戶端的模塊管理。它的模塊管理遵守AMD規范,RequireJS的基本思想是,通過define方法,將代碼定義為模塊;通過require方法,實現代碼的模塊加載。
它主要有兩個接口:define 和 require。define 是模塊開發者關注的方法,而 require 則是模塊使用者關注的方法。
define(id?, dependencies?, factory);
//id :可選參數,它指的是模塊的名字。
//dependencies:可選參數,定義中模塊所依賴模塊的數組。
//factory:模塊初始化要執行的函數或對象
需要注意的是,dependencies有多少個元素,factory就有多少個傳參,位置一一對應。 使用栗子:
define("alpha", ["require", "exports", "beta"], function (require, exports, beta) {
exports.verb = function() {
return beta.verb();
//Or:
//return require("beta").verb();
}
});
require([module], callback);
//module:一個數組,里面的成員就是要加載的模塊.
//callback:模塊加載成功之后的回調函數。
需要注意的是 ,module 有多少個元素,callback 就有多少個傳參,位置一一對應。
require(["a","b","c"],function(a,b,c){ //code here });
AMD 運行時核心思想是「Early Executing」,也就是提前執行依賴 AMD 的這個特性有好有壞:
然后將require.js導入項目: js/libs/require.js
|-js
|-libs
|-require.js
|-modules
|-alerter.js
|-dataService.js
|-main.js
|-index.html
// dataService.js文件
// 定義沒有依賴的模塊
define(function() {
let msg = 'www.baidu.com'
function getMsg() {
return msg.toUpperCase()
}
return { getMsg } // 暴露模塊
});
//alerter.js文件
// 定義有依賴的模塊
define(['dataService'], function(dataService) {
let name = 'Tom'
function showMsg() {
alert(dataService.getMsg() + ', ' + name)
}
// 暴露模塊
return { showMsg }
});
// main.js文件
(function() {
require.config({
baseUrl: 'js/', //基本路徑 出發點在根目錄下
paths: {
//映射: 模塊標識名: 路徑
alerter: './modules/alerter', //此處不能寫成alerter.js,會報錯
dataService: './modules/dataService'
}
});
require(['alerter'], function(alerter) {
alerter.showMsg()
});
})();
// index.html文件
<!DOCTYPE html>
<html>
<head>
<title>Modular Demo</title>
</head>
<body>
<!-- 引入require.js并指定js主文件的入口 -->
<script data-main="js/main" src="js/libs/require.js"></script>
</body>
</html>
在index.html引入 <script data-main="js/main" src="js/libs/require.js"></script>
此外在項目中如何引入第三方庫?只需在上面代碼的基礎稍作修改:
// alerter.js文件
define(['dataService', 'jquery'], function(dataService, $) {
let name = 'Tom'
function showMsg() {
alert(dataService.getMsg() + ', ' + name)
}
$('body').css('background', 'green')
// 暴露模塊
return { showMsg }
});
// main.js文件
(function() {
require.config({
baseUrl: 'js/', //基本路徑 出發點在根目錄下
paths: {
//自定義模塊
alerter: './modules/alerter', //此處不能寫成alerter.js,會報錯
dataService: './modules/dataService',
// 第三方庫模塊
jquery: './libs/jquery-1.10.1' //注意:寫成jQuery會報錯
}
})
require(['alerter'], function(alerter) {
alerter.showMsg()
})
})()
上例是在alerter.js文件中引入jQuery第三方庫,main.js文件也要有相應的路徑配置。 小結:通過兩者的比較,可以得出AMD模塊定義的方法非常清晰,不會污染全局環境,能夠清楚地顯示依賴關系。AMD模式可以用于瀏覽器環境,并且允許非同步加載模塊,也可以根據需要動態加載模塊。
CMD是SeaJS在推廣過程中生產的對模塊定義的規范,在Web瀏覽器端的模塊加載器中,SeaJS與RequireJS并稱,SeaJS作者為阿里的玉伯。
CMD規范專門用于瀏覽器端,模塊的加載是異步的,模塊使用時才會加載執行。CMD規范整合了CommonJS和AMD規范的特點。在 Sea.js 中,所有 JavaScript 模塊都遵循 CMD模塊定義規范。
//定義沒有依賴的模塊
define(function(require, exports, module){
exports.xxx = value
module.exports = value
})
//定義有依賴的模塊
define(function(require, exports, module){
//引入依賴模塊(同步)
var module2 = require('./module2')
//引入依賴模塊(異步)
require.async('./module3', function (m3) {
})
//暴露模塊
exports.xxx = value
})
define(function (require) {
var m1 = require('./module1')
var m4 = require('./module4')
m1.show()
m4.show()
})
然后將sea.js導入項目: js/libs/sea.js
|-js
|-libs
|-sea.js
|-modules
|-module1.js
|-module2.js
|-module3.js
|-module4.js
|-main.js
|-index.html
// module1.js文件
define(function (require, exports, module) {
//內部變量數據
var data = 'atguigu.com'
//內部函數
function show() {
console.log('module1 show() ' + data)
}
//向外暴露
exports.show = show
});
// module2.js文件
define(function (require, exports, module) {
module.exports = {
msg: 'I Will Back'
}
});
// module3.js文件
define(function(require, exports, module) {
const API_KEY = 'abc123'
exports.API_KEY = API_KEY
});
// module4.js文件
define(function (require, exports, module) {
//引入依賴模塊(同步)
var module2 = require('./module2')
function show() {
console.log('module4 show() ' + module2.msg)
}
exports.show = show
//引入依賴模塊(異步)
require.async('./module3', function (m3) {
console.log('異步引入依賴模塊3 ' + m3.API_KEY)
})
});
// main.js文件
define(function (require) {
var m1 = require('./module1')
var m4 = require('./module4')
m1.show()
m4.show()
})
<script type="text/javascript" src="js/libs/sea.js"></script>
<script type="text/javascript">
seajs.use('./js/modules/main')
</script>
ES6模塊的設計思想,是盡量的靜態化,使得編譯時就能確定模塊的依賴關系,以及輸入和輸出的變量。所以說ES6是編譯時加載,不同于CommonJS的運行時加載(實際加載的是一整個對象),ES6模塊不是對象,而是通過export命令顯式指定輸出的代碼,輸入時也采用靜態命令的形式。
ES6 的模塊自動采用嚴格模式,不管你有沒有在模塊頭部加上"use strict";。
嚴格模式主要有以下限制。
上面這些限制,模塊都必須遵守。由于嚴格模式是 ES5 引入的,不屬于 ES6,所以請參閱相關 ES5 書籍,本書不再詳細介紹了。
其中,尤其需要注意this的限制。ES6 模塊之中,頂層的this指向undefined,即不應該在頂層代碼使用this。
模塊功能主要由兩個命令構成:export和import。export命令用于規定模塊的對外接口,import命令用于輸入其他模塊提供的功能。
一個模塊就是一個獨立的文件。該文件內部的所有變量,外部無法獲取。如果你希望外部能夠讀取模塊內部的某個變量,就必須使用export關鍵字輸出該變量。下面是一個 JS 文件,里面使用export命令輸出變量。
function cUl(){
let ulEle = document.createElement("ul");
for(let i = 0; i < 5; i++){
let liEle = document.createElement("li");
liEle.innerHTML = "無序列表" + i;
ulEle.appendChild(liEle);
}
return ulEle;
}
let ul = cUl();
export {ul};
使用export命令定義了模塊的對外接口以后,其他 JS 文件就可以通過import命令加載這個模塊。
import {table} from "../test/test_table.js";
import {div} from "../test/test_div.js" ;
import {ul} from "../test/test_ul.js" ;
export {table, div, ul};
它們有兩個重大差異:
1. CommonJS 模塊輸出的是一個值的拷貝,ES6 模塊輸出的是值的引用。
2. CommonJS 模塊是運行時加載,ES6 模塊是編譯時輸出接口。
第二個差異是因為 CommonJS 加載的是一個對象(即module.exports屬性),該對象只有在腳本運行完才會生成。而 ES6 模塊不是對象,它的對外接口只是一種靜態定義,在代碼靜態解析階段就會生成。
下面重點解釋第一個差異,我們還是舉上面那個CommonJS模塊的加載機制例子:
// lib.js
export let counter = 3;
export function incCounter() {
counter++;
}
// main.js
import { counter, incCounter } from './lib';
console.log(counter); // 3
incCounter();
console.log(counter); // 4
ES6 模塊的運行機制與 CommonJS 不一樣。ES6 模塊是動態引用,并且不會緩存值,模塊里面的變量綁定其所在的模塊。
學習有趣的知識,結識有趣的朋友,塑造有趣的靈魂!
大家好,我是〖編程三昧〗的作者 隱逸王,我的公眾號是『編程三昧』,歡迎關注,希望大家多多指教!
望收藏了我寫的文章的你同時可以關注一下“小海前端”,因為這些文章都是連載的,并且是經過我系統的歸納過的。
【技術等級】初級
【承接文章】《CSS實現圖片精靈,原來要這樣使用背景屬性,前端設計師必備知識》
本文小海老師為大家講解利用CSS處理HTML中的列表,也就是CSS有關列表的屬性。本文屬于前端開發的初級教程,適合于剛剛開始接觸CSS技術的學習者。
列表屬性是指可以對HTML中的<ol></ol>標記對和<ul></ul>標記對進行樣式設置的屬性。這一組CSS屬性包括以下三個:
list-style-type
list-style-image
list-style-position
一、設置列表的項目符號或編號:
CSS技術使用 list-style-type 設置列表的項目符號或編號
在HTML中,主要操作的列表有兩種:
無序列表:用<ul></ul>標記對實現。無序列表項中左側的標識我們把它稱為“項目符號”。
有序列表:用<ol></ol>標記對實現。有序列表項中左側的標識我們把它稱為“編號”。
有序列表與無序列表
CSS技術利用 list-style-type 屬性來設置HTML列表左側標識的樣式。并且在CSS看來,<ul></ul>和<ol></ol>兩個標記對不再進行有序和無序的區分,使用list-style-type屬性設置為哪個取值,就是對應的哪種列表。
該屬性包括以下幾種取值:
none,列表項無標記。
disc,默認值,標記為實心圓。
circle,標記為空心圓。
square,標記為實心方塊。
decimal,標記為數字。
decimal-leading-zero,標記為0開頭的數字(01、02、03 等)。
lower-roman,標記為小寫羅馬數字(i、ii、iii等)。
upper-roman,標記為大寫羅馬數字(I、II、III等)。
lower-alpha,標記為小寫英文字母(a、b、c等)。
upper-alpha,標記為大寫英文字母(A、B、C等)。
二、使用自定義圖片來代替項目符號和編號:
CSS技術利用 list-style-image 屬性來設置列表左側的標識為指定的圖片
CSS技術利用 list-style-image 屬性來設置列表左側的標識為指定的圖片。
格式:list-style-image:url(Image_URL);
例如:ul{list-style-image:url(../images/01.jpg);}
三、設置列表中列表項的縮進:
CSS技術利用 list-style-position 屬性來設置列表項的縮進
CSS技術利用 list-style-position 屬性來設置列表項的縮進。
該屬性包括以下兩種取值:
loutside,默認值,列表項不縮進。
linside,列表項縮進。
這個屬性使用在列表項<li></li>標記對上的,不能用在<ol></ol>或<ul></ul>之上。
下一篇文章中,小海老師會繼續為大家向下講解CSS屬性,下一次我們講解CSS中最為重要的一組屬性:定位屬性。這是CSS中非常常用的一組屬性,希望大家千萬不要錯過!
如果大家希望得到更加全面的關于HTML和CSS技術講解的內容,可以私信我,我會免費將小海老師自己編寫的HTML和CSS的PDF教材發給你,幫助你在前端開發的道路上闊步前行。
在頭條上發表的這些文章都是從前端開發的基礎開始一步一步講起的。我非常希望能有更多的前端開發初學者通過我寫的文章,逐步學到一定的知識,甚至慢慢有了入門的感覺。這些文章都是我這幾年教學過程中的經驗,每寫一篇時我都盡量把握好措辭,用簡單易懂的語言描述,同時精心設計版面,讓版面更加豐富,激發閱讀興趣。所以,每一篇文章可能篇幅不長,但是都要耗費小海老師很久的時間。
希望收藏了我寫的文章的你同時可以關注一下“小海前端”,因為這些文章都是連載的,并且是經過我系統的歸納過的。
關注“小海前端”,我會繼續為大家奉上更加深入的前端開發文章,也希望更多的初學者跟著學下去,我們共同將前端開發的路努力堅持的走下去。
、跳出新頁面:
<basetarget=”_blank”>target="_self"不跳轉
<form action="xxx.htm" target="_blank">form表單提交的跳轉設置
2、點擊按鈕跳出別的頁面添加
<a href="#" onclick="openZoosUrl();return false;">
onclick="return false"
3、display:block;塊級元素,也就是說它可以設置一些寬高,獨占一行,比如,div元素,p元素等display:inline-block,行級元素,也就說它可以使得同樣設置成行級元素的元素一起在一行,然后可以設置寬高,這個適應于制作一個導航菜單,將每個菜單項設置成行級元素。它的寬和高默認是內容的寬和高,典型的元素是表單類的元素。dispaly:inline.行級元素,不可設置寬和高,默認寬高是內容的寬和高,典型的比如,span,
4、html鼠標小手:
cursor:pointer;
5、html背景圖屬性:
background-size:100%;,但是你的圖片寬度,高度要設置成100% ,要注意的是.php的文件里面這個background-image:url();不好用,失效,你要使用網站的絕對路徑background:url('/20151106/404/image/404.png') no-repeat 4px 5px;}background:url("11111.jpg");background-repeat:no-repeat;background-size:100%;width:100%;height:100%;
這個是給頁面加背景的body{padding: 0px;margin: 0px;background-color:#494949;width:100%;height:100%;}.
還有在設置背景圖片的時候可以使用背景background-image:url("");這個屬性來設置背景,但是圖片要用gif的格式
6、按輸出方式來顯示文本格式:<pre></pre>橫線:<hr /><q></q>雙引號標簽下劃線<ins></ins>
7、html---position/relative/absolute/fixed/三種布局定位方式的總結relative是按照自身來說,absolute是按照瀏覽器來說,但是要注意的是,如果他有父級元素的話,那么他就是依照父級元素來進行改變位置的。
8、無序列表去掉前面黑點li{list-style:none;}
9、隱藏元素 - display:none或visibility:hidden
display-這個元素,設置之后原本的元素不會占用當前的空間,不會影響布局,但是后者,隱藏之后還會占用空間
10、HTML隱藏多余
Div{overflow:hidden}
10、隱藏自適應:overflow:auto;
11、關于框架的問題
這個是接受你要顯示頁面
indx.php是框架顯示的頁面,最上面,也就是沒按鍵顯示
<iframe src="index.php" style="width:100%;height:100%;border:none " name="main"></iframe>
這個是你點擊之后想在哪顯示后面加:target=""
<a href='../admin/shopclass/add.php' target="main">添加分類</a>
12、關于背景的高的問題,也就是說你定義了一個div但是沒有搞,是為了讓你的圖片在上面。那么就有這個屬性了
overflow:hidden;
也就是你本身是屬于父級元素的,但是你float就脫離了文本,變成浮動的,所有就不會在用父子元素的空間,所以就父級加上這個overflow:hidden;
13、錨點的設置
在你想跳轉的頁面的地方加上:<a name="miao">
然后在你想加鏈接的地方加上<a href="#miao">去找錨點</a>
14.點擊換驗證碼圖片
<img src="../public/common/yzm.php" alt="" style="cursor:pointer" onclick="this.src='../public/common/yzm.php?rand='+Math.random()">
15、圓角
border-radius:5px;
16、textarea的左側文字在最左邊
style="vertical-align:top"
17、html塊狀元素和內聯元素的總結,塊狀元素可以設置margin,但是使用margin的時候要符合:1.塊狀元素,2.有寬高,其中內聯元素不能設置margin和寬高的屬性,只能設置padding
*請認真填寫需求信息,我們會在24小時內與您取得聯系。