整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          Javascript模塊化

          本文主要理理js模塊化相關知識。
          涉及到內聯腳本、外聯腳本、動態腳本、阻塞、
          deferasyncCommonJSAMDCMDUMDES Module。順帶探究下Vite

          內聯腳本

          假設你是一個前端新手,現在入門,那么我們創建一個html頁面,需要新建一個index.html文件:

          <!DOCTYPE html>
          <html>
          <head>
            <title>test</title>
          </head>
          <body>
            <p id="content">hello world</p>
          </body>
          </html>

          如果需要在頁面中執行javascript代碼,我們就需要在 HTML 頁面中插入 <script> 標簽。

          有2種插入方式:
          1、放在
          <head>
          2、放在<body>

          比如,點擊hello world之后,在hello world后面加3個感嘆號的功能,我們在head中加入script標簽,并給hello world綁定點擊事件:

          <!DOCTYPE html>
          <html>
          <head>
            <title>test</title>
            <script>
              function myFunction() {
                document.getElementById('content').innerHTML = 'hello world!!!'
              }
            </script>
          </head>
          
          <body>
            <p id="content" onclick="myFunction()">hello world</p>
          </body>
          </html>

          如果加在body中,一般放在body的最后面:

          <!DOCTYPE html>
          <html>
          <head>
            <title>test</title>
          </head>
          
          <body>
            <p id="content" onclick="myFunction()">hello world</p>
            <script>
              function myFunction() {
                document.getElementById('content').innerHTML = 'hello world!!!'
              }
            </script>
          </body>
          </html>

          簡單的邏輯我們可以用這2種方式寫,這種方式叫做內聯腳本。

          外聯腳本

          當邏輯復雜時,我們可以把上面的script標簽中的代碼抽取出來,比如在html的同級目錄創建一個js文件夾,里面新建一個a.js的文件。

          a.js中寫上面script標簽中的代碼:

          function myFunction() {
            document.getElementById('content').innerHTML = 'hello world!!!'
          }

          上面的script標簽則可以改成:

          <script src="./js/a.js"></script>

          阻塞

          上面的2種寫法,瀏覽器在加載html時,遇到script標簽,會停止解析html。
          內聯腳本會立刻執行;外聯腳本會先下載再立刻執行。
          等腳本執行完畢才會繼續解析html。
          (html解析到哪里,頁面就能顯示到哪里,用戶也能看到哪里)

          比如下面的代碼:

          <p>...content before script...</p>
          
          <script src="./js/a.js"></script>
          
          <p>...content after script...</p>

          解析到第一個p標簽,我們能看到...content before script...顯示在了頁面中,然后瀏覽器遇到script標簽,會停止解析html,而去下載a.js并執行,執行完a.js才會繼續解析html,然后頁面中才會出現...content after script...

          我們可以通過Chrome的Developer Tools分析一下index.html加載的時間線:

          這會導致2個問題:
          1、腳本無法訪問它下面的dom;
          2、如果頁面頂部有個笨重的腳本,在它執行完之前,用戶都看不到完整的頁面。

          對于問題2,我們可以把腳本放在頁面底部,這樣它可以訪問到上面的dom,且不會阻塞頁面的顯示:

          <body>
            ...all content is above the script...
          
            <script src="./js/a.js"></script>
          </body>

          但這不是最好的辦法,我們接著往下看。

          defer

          我們給script標簽加defer屬性,就像下面這樣:

          <p>...content before script...</p>
          
          <script defer src="./js/a.js"></script>
          
          <p>...content after script...</p>

          defer 特性告訴瀏覽器不要等待腳本。于是,瀏覽器將繼續解析html,腳本會并行下載,然后等 DOM 構建完成后,腳本才會執行。

          這樣script標簽不再阻塞html的解析。

          這時再看時間線:

          需要注意的是,具有 defer 特性的腳本保持其相對順序。

          比如:

          <script defer src="./js/a.js"></script>
          <script defer src="./js/b.js"></script>

          上面的2個腳本會并行下載,但是不論哪個先下載完成,都是先執行a.js,a.js執行完才會執行b.js。
          這時,如果b.js依賴a.js,這種寫法將很有用。

          另外需要注意的是,defer 特性僅適用于外聯腳本,即如果 script標簽沒有 src屬性,則會忽略 defer 特性。

          async

          我們可以給script標簽加async屬性,就像下面這樣:

          <script async src="./js/a.js"></script>

          這會告訴瀏覽器,該腳本完全獨立。
          獨立的意思是,DOM 和其他腳本不會等待它,它也不會等待其它東西。async 腳本就是一個會在加載完成時立即執行的完全獨立的腳本。

          這時再看時間線:

          可以看到,雖然下載a.js不阻塞html的解析,但是執行a.js會阻塞。

          還需要注意多個async時的執行順序,比如下面這段代碼:

          <p>...content before script...</p>
          
          <script async src="./js/a.js"></script>
          <script async src="./js/b.js"></script>
          
          <p>...content after script...</p>

          兩個p標簽的內容會立刻顯示出來,a.js和b.js則并行下載,且下載成功后立刻執行,所以多個async時的執行順序是誰先下載成功誰先執行。
          一些比較獨立的腳本,比如性能監控,就很適合用這種方式加載。

          另外,和defer一樣,async 特性也僅適用于外聯腳本。

          動態腳本

          我們可以動態地創建一個script標簽并append到文檔中。

          let script = document.createElement('script')
          script.src = '/js/a.js'
          document.body.append(script)

          append后腳本就會立刻開始加載,表現默認和加了async屬性一致。
          我們可以顯示的設置
          script.async = false來改變這個默認行為,那么這時表現就和加了defer屬性一致。

          上面的這些寫法,當script標簽變多時,容易導致全局作用域污染,還要維護書寫順序,要解決這個問題,需要一種將 JavaScript 程序拆分為可按需導入的單獨模塊的機制,即js模塊化,我們接著往下看。

          CommonJS

          很長一段時間 JavaScript 沒有模塊化的概念,直到 Node.js 的誕生,把 JavaScript 帶到服務端,這時,CommonJS誕生了。

          CommonJS定義了三個全局變量:

          require,exports,module

          require 讀入并執行一個 js 文件,然后返回其 exports 對象;
          exports 對外暴露模塊的接口,可以是任何類型,指向 module.exports;
          module 是當前模塊,exports 是 module 上的一個屬性。

          Node.js 使用了CommonJS規范。

          比如:

          // a.js
          let name = 'Lily'
          export.name = name
          
          // b.js
          let a = require('a.js')
          console.log(a.name) // Lily

          由于CommonJS不適合瀏覽器端,于是出現了AMD和CMD規范。

          AMD

          AMD(Asynchronous Module Definition) 是 RequireJS 在推廣過程中對模塊定義的規范化產出。

          基本思想是,通過 define 方法,將代碼定義為模塊。當這個模塊被 require 時,開始加載依賴的模塊,當所有依賴的模塊加載完成后,開始執行回調函數,返回該模塊導出的值。

          使用時,需要先引入require.js:

          <script src="require.js"></script>
          <script src="a.js"></script>

          然后可以這樣寫:

          // a.js
          define(function() {
              let name = 'Lily'
              return {
                  name
              }
          })
          // b.js
          define(['a.js'], function(a) {
              let name = 'Bob'
              console.log(a.name) // Lily
              return {
                  name
              }
          })

          CMD

          CMD(Common Module Definition) 是 Sea.js 在推廣過程中對模塊定義的規范化產出。

          使用時,需要先引入sea.js:

          <script src="sea.js"></script>
          <script src="a.js"></script>

          然后可以這樣寫:

          // a.js
          define(function(require, exports, module) {
              var name = 'Lily'
              exports.name = name
          })
          
          // b.js
          define(function(require, exports, module) {
              var name = 'Bob'
              var a = require('a.js')
              console.log(a.name) // 'Lily'
              exports.name = name
          })

          UMD

          UMD (Universal Module Definition) 目的是提供一個前后端跨平臺的解決方案(兼容全局變量、AMD、CMD和CommonJS)。

          實現很簡單,判斷不同的環境,然后以不同的方式導出模塊:

          (function (root, factory) {
              if (typeof define === 'function' && (define.amd || define.cmd)) {
                  // AMD、CMD
                  define([], factory);
              } else if (typeof module !== 'undefined' && typeof exports === 'object') {
                  // Node、CommonJS
                  module.exports = factory();
              } else {
                  // 瀏覽器全局變量
                  root.moduleName = factory();
            }
          }(this, function () {
              // 只需要返回一個值作為模塊的export
              // 這里我們返回了一個空對象
              // 你也可以返回一個函數
              return {};
          }));

          ES Module

          AMD 和 CMD 是社區的開發者們制定的模塊加載方案,并不是語言層面的標準。從 ES6 開始,在語言標準的層面上,實現了模塊化功能,而且實現得相當簡單,完全可以取代上文的規范,成為瀏覽器和服務器通用的模塊解決方案。

          ES6 的模塊自動采用嚴格模式。模塊功能主要由兩個命令構成:export和import。

          export命令用于規定模塊的對外接口;
          import命令用于輸入其他模塊提供的功能。

          比如上面的代碼,我們可以這樣寫:

          // a.js
          const name = 'Lily'
          
          export {
            name
          }
          
          // 等價于
          export const name = 'Lily'
          
          // b.js
          import { name } from 'a.js'
          console.log(name) // Lily
          
          // b.js
          import * as a from 'a.js'
          console.log(a.name) // Lily

          此外,還可以用export default默認導出的寫法:

          // a.js
          const name = 'Lily'
          
          export default {
            name
          }
          
          // b.js
          import a from 'a.js'
          console.log(a.name) // Lily

          如果只想運行a.js,可以只import:

          // b.js
          import 'a.js'

          我們可以給script標簽加type=module讓瀏覽器以 ES Module 的方式加載腳本:

          <script type="module" src="./js/b.js"></script>

          這時,script標簽會默認有defer屬性(也可以設置成async),支持內聯和外聯腳本。

          這時我們運行打開index.html,會發現瀏覽器報錯了:

          這是因為 type=module 的 script 標簽加強了安全策略,瀏覽器加載不同域的腳本資源時,如果服務器未返回有效的 Allow-Origin 相關 CORS 頭,會禁止加載改腳本。而這里啟動的index.html是一個本地文件(地址是file://路徑),將會遇到 CORS 錯誤,需要通過一個服務器來啟動 HTML 文件。

          Vite

          在瀏覽器支持 ES Module 之前,我們用工具實現JavaScript模塊化的開發,比如webpack、Rollup 和 Parcel 。但是當項目越來越大后,本地熱更新越來越慢,而 Vite 旨在利用ESM解決上述問題。

          Vite使用簡單,可以去官網(https://cn.vitejs.dev/)看看。

          總結

          老的規范了解即可,未來是ES Module的,用Vite可以極大的提升開發時的體驗,生產環境用Rollup打包。

          Image 對象

          Image 對象代表嵌入的圖像。

          <img> 標簽每出現一次,一個 Image 對象就會被創建。

          Image 對象屬性

          W3C: W3C 標準。

          屬性描述W3C
          align設置或返回與內聯內容的對齊方式。Yes
          alt設置或返回無法顯示圖像時的替代文本。Yes
          border設置或返回圖像周圍的邊框。Yes
          complete返回瀏覽器是否已完成對圖像的加載。No
          height設置或返回圖像的高度。Yes
          hspace設置或返回圖像左側和右側的空白。Yes
          longDesc設置或返回指向包含圖像描述的文檔的 URL。Yes
          lowsrc設置或返回指向圖像的低分辨率版本的 URL。No
          name設置或返回圖像的名稱。Yes
          src設置或返回圖像的 URL。Yes
          useMap設置或返回客戶端圖像映射的 usemap 屬性的值。Yes
          vspace設置或返回圖像的頂部和底部的空白。Yes
          width設置或返回圖像的寬度。Yes

          Image 對象事件

          事件描述W3C
          onabort當用戶放棄圖像的裝載時調用的事件句柄。Yes
          onerror在裝載圖像的過程中發生錯誤時調用的事件句柄。Yes
          onload當圖像裝載完畢時調用的事件句柄。Yes

          標準屬性和事件

          Image 對象同樣支持標準的 屬性 和 事件。

          如您還有不明白的可以在下面與我留言或是與我探討QQ群308855039,我們一起飛!

          顏色設置的簡便方法

          昨天我們在《使用HTML添加表格3(間距與顏色)——零基礎自學網頁制作》(目錄在結尾)中學習了設置單元格以及其中內容的空間間距和背景顏色。

          其中添加列向單元格背景顏色只需要修改對應的<tr>標簽中的style屬性,而修改行向標簽需要修改不同<tr></tr>標簽中的<td>標簽的style屬性,這樣操作起來就非常的麻煩,那有沒有簡便的修改行向單元格背景顏色的方法呢?

          當然有!

          開發團隊給出了<colgroup><col></col></colgroup>這樣的組合來解決這個問題,下面讓我們詳細學習。

          <colgroup></colgroup>標簽是一個給行向單元格打組的標簽,在頁面中不會顯示。

          <col></col>標簽是來具體設置行向單元格數量和顏色的標簽。

          示例代碼如下:

          <colgroup><col span = "1" style="background-color:#ff0000;"></col></colgroup>

          這段代碼添加到"第一個頁面.html"當中就可以,具體代碼如下:

          <!DOCTYPE HTML>
            <html>
            <head> 
            <title>第一個網頁</title>
            </head> 
            <body>
            <h1>第一個網頁</h1><hr>
            <h2>表格元素</h2><hr>
            <table border="1" width="100%">
            <thead>
            <tr>
            <td colspan="2">表格的頭部信息</td>
            </tr>
            </thead>
            <tfoot>
            <tr>
            <td colspan="2">表格的腳部信息</td>
            <tr>
            </tfoot>
            <tbody>
            <caption>表格標題</caption>
            <colgroup>
            <col span = "1" style="background-color:#ff0000;"></col>
            </colgroup>
            <tr>
            <th>姓名</th>
            <th>年齡</th>
            </tr>
            <tr>
            <td>一列一行</td>
            <td>一列二行</td>
            </tr>
            <tr>
            <td>二列一行</td>
            <td>二列二行</td>
            </tr>
            </tbody>
            </table>
            </body> 
            </html>

          頁面效果如圖:

          因為第一列和最后一列只有一行所以,也都變紅了。

          其中span的數量代表行數。

          如果把span等號后面的數改成2,因為表格只有兩行,所以整個表格都紅了。

          表格嵌套

          我們可以通過向表格中添加表格實現表格嵌套。表格嵌套可以把一個單元格分成行向或列向分割單元格。

          代碼示例如下:我們把"一列一行"分割成列向兩個單元格。

          <tr><td><table border = "1" width="100%"><tr><td>1</td><td>2</td></tr></table></td>

          使用

          <table border = "1" width="100%">
          
          <tr>
          
          <td>1</td>
          
          <td>2</td>
          
          </tr>
          
          </table>

          這段代碼替換文字"一列一行"即可。

          頁面效果如圖所示:

          留個思考題,大家可以思考一下行向分割單元格怎么寫。

          今天的內容結束了。

          全部示例代碼如下:

          <!DOCTYPE HTML>
            <html>
            <head> 
            <title>第一個網頁</title>
            </head> 
            <body>
            <h1>第一個網頁</h1><hr>
            <h2>表格元素</h2><hr>
            <table border="1" width="100%">
            <thead>
            <tr>
            <td colspan="2">表格的頭部信息</td>
            </tr>
            </thead>
            <tfoot>
            <tr>
            <td colspan="2">表格的腳部信息</td>
            <tr>
            </tfoot>
            <tbody>
            <caption>表格標題</caption>
            <colgroup>
            <col span = "1" style="background-color:#ff0000;"></col>
            </colgroup>
            <tr>
            <th>姓名</th>
            <th>年齡</th>
            </tr>
            <tr>
            <td>
            <table border = "1" width="100%">
            <tr>
            <td>1</td>
            <td>2</td>
            </tr>
            </table>
            </td>
            <td>一列二行</td>
            </tr>
            <tr>
            <td>二列一行</td>
            <td>二列二行</td>
            </tr>
            </tbody>
            </table>
            </body> 
            </html>

          喜歡的小伙伴請關注我,閱讀中遇到任何問題請給我留言,如有疏漏或錯誤歡迎大家斧正,不勝感激!

          學到這里,相信大家已經有獨立讀懂HTML代碼說明的能力了,明天我會為大家講解16進制顏色表示方法。之后會給大家推薦html代碼參考手冊的鏈接。如果您是零基礎的話,學完16進制顏色表示方法后,基本上就可以無障礙的閱讀html代碼參考手冊了,如果閱讀起來還是有困難,請繼續看后面我為大家講解一些常用元素及屬性的文章,已及html中特殊符號的輸入方法,全部做完后再結束這套教程。

          如果您有任何疑問或不解歡迎關注并私信我。

          HTML完整學習目錄

          HTML序章(學習目的、對象、基本概念)——零基礎自學網頁制作

          HTML是什么?——零基礎自學網頁制作

          第一個HTML頁面如何寫?——零基礎自學網頁制作

          HTML頁面中head標簽有啥用?——零基礎自學網頁制作

          初識meta標簽與SEO——零基礎自學網頁制作

          HTML中的元素使用方法1——零基礎自學網頁制作

          HTML中的元素使用方法2——零基礎自學網頁制作

          HTML元素中的屬性1——零基礎自學網頁制作

          HTML元素中的屬性2(路徑詳解)——零基礎自學網頁制作

          使用HTML添加表格1(基本元素)——零基礎自學網頁制作

          使用HTML添加表格2(表格頭部與腳部)——零基礎自學網頁制作

          使用HTML添加表格3(間距與顏色)——零基礎自學網頁制作

          使用HTML添加表格4(行顏色與表格嵌套)——零基礎自學網頁制作

          16進制顏色表示與RGB色彩模型——零基礎自學網頁制作

          HTML中的塊級元素與內聯元素——零基礎自學網頁制作

          初識HTML中的<div>塊元素——零基礎自學網頁制作

          在HTML頁面中嵌入其他頁面的方法——零基礎自學網頁制作

          封閉在家學網頁制作!為頁面嵌入PDF文件——零基礎自學網頁制作

          HTML表單元素初識1——零基礎自學網頁制作

          HTML表單元素初識2——零基礎自學網頁制作

          HTML表單3(下拉列表、多行文字輸入)——零基礎自學網頁制作

          HTML表單4(form的action、method屬性)——零基礎自學網頁制作

          HTML列表制作講解——零基礎自學網頁制作

          為HTML頁面添加視頻、音頻的方法——零基礎自學網頁制作

          音視頻格式轉換神器與html視頻元素加字幕——零基礎自學網頁制作

          HTML中使用<a>標簽實現文本內鏈接——零基礎自學網頁制作


          主站蜘蛛池模板: 国产成人精品亚洲一区| 福利一区二区三区视频午夜观看| 中文字幕av一区| 久久亚洲色一区二区三区| 无码国产精成人午夜视频一区二区| 亚洲AV无码一区二区三区人 | 国产av成人一区二区三区| 激情内射亚洲一区二区三区爱妻| 国产一区二区在线|播放| 亚洲AV无码一区二区三区系列| 免费无码一区二区三区蜜桃大 | 毛片一区二区三区无码| 狠狠综合久久AV一区二区三区| 亚洲高清一区二区三区电影 | 国产精品无码一区二区三区免费| 国产精品丝袜一区二区三区| 蜜臀AV一区二区| 日韩电影一区二区| 精品人妻少妇一区二区| 国产一区视频在线免费观看| 亚洲综合一区无码精品| 激情内射亚洲一区二区三区爱妻| 精品国产一区二区22| 国产MD视频一区二区三区| 日韩精品一区二区三区毛片| 日韩高清国产一区在线| 国产精品福利一区二区| 亚洲精品一区二区三区四区乱码| 国产主播一区二区| 国产91精品一区二区麻豆亚洲| 日韩有码一区二区| 福利一区福利二区| 一区二区视频传媒有限公司| 国产一区二区不卡在线播放| 国产亚洲福利精品一区| 无码人妻久久一区二区三区| 亚洲一区电影在线观看| 国产成人一区二区三区高清| 伊人久久精品一区二区三区| 亚洲国产欧美国产综合一区| 日韩视频一区二区|