日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

Web应用开发中的几个问题

發(fā)布時(shí)間:2023/12/15 编程问答 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Web应用开发中的几个问题 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Introduction

  由于Ajax技術(shù)在Gmail中的成功應(yīng)用和高性能的V8引擎的推出使得編寫(xiě)Web應(yīng)用變得流行 起來(lái),使用前端技術(shù)也可以編寫(xiě)具有復(fù)雜交互的應(yīng)用。相對(duì)于native應(yīng)用,Web應(yīng)用具 有如下優(yōu)點(diǎn):

  • 跨平臺(tái),開(kāi)發(fā)和維護(hù)成本低;
  • 升級(jí)和發(fā)布方便,沒(méi)有版本的概念,隨時(shí)隨地發(fā)布,用戶沒(méi)有感知,不需要安裝;
  • 響應(yīng)式設(shè)計(jì)(Responsive Design)使得Web應(yīng)用可以跨平臺(tái),同一份代碼自適應(yīng)各種 屏幕大小
  • 即使最終不采用Web應(yīng)用方案,也很適合開(kāi)發(fā)原型

  當(dāng)然,Web應(yīng)用也不是沒(méi)有缺點(diǎn)。由于不同平臺(tái)和廠商的瀏覽器并不完全一樣,跨平臺(tái) 也有一些兼容成本。另外,Web應(yīng)用的性能不如native應(yīng)用,交互有時(shí)候不是很流暢, 再加上HTML5的API上的限制,使得有些功能采用Web應(yīng)用不太合適。由于這些原因,結(jié) 合兩者優(yōu)點(diǎn)的混合方案變得流行起來(lái)(比如微信、手機(jī)QQ和手機(jī)QQ瀏覽器中會(huì)嵌入一 些Web頁(yè)面)。

?

  根據(jù)筆者的開(kāi)發(fā)經(jīng)驗(yàn),下面總結(jié)一些Web應(yīng)用開(kāi)發(fā)過(guò)程中的要面臨的幾個(gè)問(wèn)題。

 模塊化編程

  模塊化編程是編寫(xiě)大規(guī)模應(yīng)用必不可少的一個(gè)特性,與其它主流的編程語(yǔ)言相比 Javascript沒(méi)有對(duì)模塊提供直接的支持,更不用說(shuō)維護(hù)模塊之間的依賴關(guān)系,這使得維 護(hù)Javascript代碼變得異常困難,在<script>標(biāo)簽中包含代碼的順序需要人工維護(hù)。

  要支持模塊化編程必須解決兩個(gè)問(wèn)題:

  • 支持編寫(xiě)模塊并為模塊命名,防止名字沖突和全局變量的使用;
  • 支持顯示指定模塊之間的依賴關(guān)系,并在程序執(zhí)行時(shí)自動(dòng)加載依賴的模塊。
  •   Douglas Crockford在”Javascript: The Good Parts”一書(shū)中提出的Module Pattern利 用Javascript的閉包技術(shù)來(lái)模擬模塊的概念,防止名字沖突和全局變量的使用。這解 決了第一個(gè)問(wèn)題。

    ?
    1 2 3 4 5 6 7 8 9 var moduleName = function () { ????// Define private variables and functions ????var private = ... ?? ????// Return public interface. ????return { ????????foo: ... ????}; }();

      為了解決第二個(gè)問(wèn)題CommonJS組織定義了?AMD規(guī)范方便 開(kāi)發(fā)者顯示指定模塊之間的依賴關(guān)系,并在需要時(shí)加載依賴的模塊。?RequireJS是AMD規(guī)范的一個(gè)比較流行的實(shí)現(xiàn)。

      首先我們?cè)赼.js中定義模塊A.

    ?
    1 2 3 4 5 6 define(function () { ????return { ????????color: "black", ????????size: 10 ????}; });

      然后定義模塊B依賴模塊A.

    ?
    1 2 3 define(["a"], function (A) { ????// ... });

      當(dāng)模塊B執(zhí)行時(shí)RequireJS保證模塊A已被加載。具體細(xì)節(jié)可參考RequireJS官方文 檔。

     腳本加載

      最簡(jiǎn)單的腳本加載方式是放在<head>加載。

    ?
    1 2 3 4 <head> ??<script src="base.js" type="text/javascript"></script> ??<script src="app.js" type="text/javascript"></script> </head>

      其缺點(diǎn)是:

  • 加載和解析是順序是同步執(zhí)行的,先下載base.js然后解析和執(zhí)行,然后再下載?app.js;
  • 加載腳本時(shí)還會(huì)阻塞對(duì)<script>之后的DOM元素的渲染。
  •   為了緩解這些問(wèn)題,現(xiàn)在的普遍做法是將<script>放在<body>的底部。

    ?
    1 2 3 ??<script src="base.js" type="text/javascript"></script> ??<script src="app.js" type="text/javascript"></script> </body>

      但并不是所有的腳本都可以放在<body>的底部,比如有些邏輯要在頁(yè)面渲染時(shí)執(zhí)行, 不過(guò)大多數(shù)腳本沒(méi)有這樣的要求。

      將腳本放在<body>底部仍然沒(méi)有解決順序下載的問(wèn)題,一些瀏覽器廠商也意識(shí)到了 這個(gè)問(wèn)題并開(kāi)始支持異步下載。HTML5也提供了標(biāo)準(zhǔn)的解決方案:

    ?
    1 2 <script src="base.js" type="text/javascript" async></script> <script src="app.js" type="text/javascript" async></script>

      標(biāo)上async屬性的腳本表明你沒(méi)有在里面使用document.write之類(lèi)的代碼。瀏覽器 將異步下載和執(zhí)行這些腳本,并且不會(huì)組織DOM樹(shù)的渲染。但是這會(huì)導(dǎo)致另一個(gè)問(wèn)題: 由于是異步執(zhí)行,app.js可能在base.js之前執(zhí)行,如果它們之間有依賴關(guān)系這將 導(dǎo)致錯(cuò)誤。

      講到這里從開(kāi)發(fā)者角度來(lái)看我們其實(shí)需要的是這些特性:

  • 異步下載,不要阻塞DOM的渲染;
  • 按照模塊的依賴關(guān)系解析和執(zhí)行腳本。
  •   所以腳本的加載其實(shí)需要與模塊化編程問(wèn)題結(jié)合起來(lái)解決。RequireJS不僅記錄了模 塊之間的依賴關(guān)系,并且提供了根據(jù)依賴關(guān)系的按需加載和執(zhí)行(詳情請(qǐng)參考 RequireJS官方文檔)。

      關(guān)于腳本加載的更多方案請(qǐng)看?這里.

     靜態(tài)資源文件的部署

      這里的靜態(tài)資源文件是指CSS、Javascript和CSS需要的一些圖片文件。它們的部署需 要考慮兩個(gè)問(wèn)題:

  • 下載速度
  • 版本管理
  •   靜態(tài)資源文件的一個(gè)特點(diǎn)變化不頻繁,且與用戶身份無(wú)關(guān)(即與Cookie無(wú)關(guān)),因此 很適合緩存。另一方面,一旦靜態(tài)資源文件變化時(shí),瀏覽器必須從Web服務(wù)器下載最新 的版本。當(dāng)發(fā)布新版本的Web應(yīng)用時(shí),并不是所有用戶馬上就用上新版本,老版本和新 版本將會(huì)共存,這就涉及到版本匹配問(wèn)題。老版本的應(yīng)用需要下載老版本的CSS和 Javascript,新版本的應(yīng)用需要下載新版本的靜態(tài)資源。

  • 為了防止版本不一致,每當(dāng)發(fā)布新版本的應(yīng)用時(shí)靜態(tài)資源文件都需要改名,讓舊的 HTML引用舊的靜態(tài)文件,新的HTML引用新的靜態(tài)文件。一個(gè)常見(jiàn)辦法就是在文件名 中加時(shí)間戳;
  • 為了防止懸掛引用,資源文件應(yīng)該比HTML先發(fā)布。
  •   上述方案可以解決版本問(wèn)題,這樣每個(gè)靜態(tài)文件的緩存時(shí)間可以設(shè)置得任意大,防止 重復(fù)下載,同時(shí)在新版本發(fā)布時(shí)瀏覽器將及時(shí)更新。

      為解決下載速度問(wèn)題,可以考慮以下幾個(gè)方案:

  • 合并靜態(tài)文件以免文件數(shù)量過(guò)多,過(guò)多的文件需要更多的連接來(lái)下載,瀏覽器通常 對(duì)同一個(gè)域名的連接數(shù)量有限制;
  • 壓縮靜態(tài)文件;為了可讀性,CSS和Javascript通常有很多空行、縮進(jìn)和注釋,這 些在發(fā)布時(shí)都可以去掉;
  • 靜態(tài)文件通常與Cookie沒(méi)有關(guān)系,所以為了減小傳輸大小和增加緩存命中率(緩存 的key需要考慮Cookie),靜態(tài)文件最好托管在沒(méi)有Cookie的域名上;
  •   最后也是最重要的,要使上述過(guò)程自動(dòng)化。

     MVC編程模型

      Web應(yīng)用采用的是事件驅(qū)動(dòng)編程模型,與native應(yīng)用是一樣的,區(qū)別僅在于基礎(chǔ)設(shè)施提 供的API不一樣。UI編程通常采用MVC設(shè)計(jì)模式,以流行的?Backbone.js為例包括如下部分:

  • Model
    • 數(shù)據(jù)的唯一來(lái)源
    • 負(fù)責(zé)獲取和存儲(chǔ)數(shù)據(jù)
    • 可提供緩存機(jī)制
    • 數(shù)據(jù)變化時(shí)通過(guò)事件通知其它對(duì)象
  • View
    • 負(fù)責(zé)渲染
    • 監(jiān)聽(tīng)UI事件和Model事件并重繪UI
    • 渲染結(jié)果取決于兩類(lèi)數(shù)據(jù):Model和UI交互狀態(tài)
    • UI的交互狀態(tài)通常存在View對(duì)象中,有時(shí)候?yàn)榱朔奖阋泊嬖贒OM樹(shù)節(jié)點(diǎn)中
    • 為了降低渲染成本,盡量減少需要渲染的區(qū)域,每次當(dāng)數(shù)據(jù)變化時(shí)只渲染受影響 的區(qū)域
  • Router
    • 負(fù)責(zé)監(jiān)聽(tīng)URL的變化,并通知相應(yīng)的View對(duì)象渲染頁(yè)面
  •   為了有效地使用MVC,有幾個(gè)問(wèn)題需要注意。

      Model應(yīng)與View完全隔離

      Model僅提供數(shù)據(jù)的訪問(wèn),不應(yīng)該依賴View,因此Model不應(yīng)該知道View的存在。所以 Model不能持有對(duì)任何View對(duì)象的引用。Model的數(shù)據(jù)發(fā)生變化時(shí)只能通過(guò)事件通知 View.

      View在初始化時(shí)采用委派方式監(jiān)聽(tīng)UI事件

      這里有兩個(gè)關(guān)鍵點(diǎn):

  • 在初始化時(shí)監(jiān)聽(tīng)事件var View = Backbone.View.extend({ initialize: function () { this.$el.on(‘click’, ‘#id’, function () { // … }); } });
  •   除了一些特殊情況外(請(qǐng)看下文),所有UI事件都應(yīng)該在View初始化時(shí)初始化,防止同 一個(gè)事件被綁定多次。即使有些事件是動(dòng)態(tài)監(jiān)聽(tīng)的(有時(shí)候需要監(jiān)聽(tīng),有時(shí)候有不需要 監(jiān)聽(tīng),比如有些按鈕有時(shí)候是有效的,有時(shí)候又無(wú)效),也需要在初始化時(shí)監(jiān)聽(tīng),然后 在事件回調(diào)函數(shù)里判斷是否需要處理。這樣邏輯更簡(jiǎn)單,更容易維護(hù)。

  • 采用委派方式監(jiān)聽(tīng)UI事件
  •   關(guān)于委派方式監(jiān)聽(tīng)請(qǐng)參考jQuery文檔.

      上面已強(qiáng)調(diào)要在初始化時(shí)監(jiān)聽(tīng)事件,但是初始化時(shí)需要監(jiān)聽(tīng)的DOM節(jié)點(diǎn)可能還不存在, 所以沒(méi)法直接綁定事件,只能采用委派方式。不過(guò)采用委派方式要求事件可以冒泡。

      對(duì)于那些沒(méi)法冒泡的事件(比如<img>的load事件)只能在保證其存在的情況下直 接綁定,而不一定要在初始化時(shí)綁定。

      復(fù)雜的View組織成樹(shù)形層次結(jié)構(gòu)

      函數(shù)太大了需要拆分成幾個(gè)子函數(shù)。同樣,View的邏輯如果過(guò)于復(fù)雜也應(yīng)根據(jù)頁(yè)面結(jié) 構(gòu)拆成幾個(gè)子View:

  • 父View通過(guò)引用訪問(wèn)子View,但是子View不應(yīng)該持有父View的引用;
  • 子View只負(fù)責(zé)自己區(qū)域的渲染,其它區(qū)域由父View負(fù)責(zé)渲染;
  • 父View通過(guò)函數(shù)調(diào)用訪問(wèn)子View的功能,子View通過(guò)事件與父View通信;
  • 子View之間不能直接通信。
  •   其它技巧可查看?Backbone技巧與模式.

     離線應(yīng)用緩存

      為使Web應(yīng)用體驗(yàn)更加流暢,可考慮使用HTML5離線應(yīng)用緩存,不過(guò)有以下幾點(diǎn)需要注 意:

  • 不要將離線應(yīng)用緩存與HTTP緩存機(jī)制搞混淆,前者是HTML5引入的新特性,與HTTP緩 存機(jī)制是相互獨(dú)立并存的;
  • Cache manifest文件不應(yīng)被HTTP緩存太久(通過(guò)HTTP頭Cache-Control控制緩存 時(shí)間),否則發(fā)布新版后瀏覽器不會(huì)及時(shí)監(jiān)測(cè)到變化并下載新文件;
  • 在Cache manifest文件的NETWORK節(jié)放一個(gè)*,否則沒(méi)有列在這個(gè)文件的資源不 會(huì)被請(qǐng)求;
  • 不適合緩存的請(qǐng)求最好都放在NETWORK節(jié);
  • 如果之前使用過(guò)離線應(yīng)用緩存現(xiàn)在不想再使用了,從<html>刪除manifest屬性, 并發(fā)送404響應(yīng)給manifest文件請(qǐng)求。僅僅刪除manifest屬性是沒(méi)有效的。
  •  線上錯(cuò)誤報(bào)告

      Javascript是一個(gè)動(dòng)態(tài)語(yǔ)言,許多檢查都是在運(yùn)行時(shí)執(zhí)行的,所以大多數(shù)錯(cuò)誤只有執(zhí) 行到的時(shí)候才能檢查到,只能在發(fā)布前通過(guò)大量測(cè)試來(lái)發(fā)現(xiàn)。即使這樣仍可能有少數(shù) 沒(méi)有執(zhí)行到的路徑有錯(cuò)誤,這只能通過(guò)線上錯(cuò)誤報(bào)告來(lái)發(fā)現(xiàn)了。

    ?
    1 2 3 4 5 6 7 window.onerror = function (errorMsg, fileLoc, linenumber) { ????var s = 'url: ' + document.URL + '\nfile:? ' + fileLoc ????????+ '\nline number: ' + linenumber ????????+ '\nmessage: ' + errorMsg; ????Log.error(s);?????? // 發(fā)給服務(wù)器統(tǒng)計(jì)監(jiān)控 ????console.log(s); };

      通常線上的Javascript都是經(jīng)過(guò)了合并和壓縮的,上報(bào)的文件名和行號(hào)基本上沒(méi)法對(duì) 應(yīng)到源代碼,對(duì)查錯(cuò)幫助不是很大。不過(guò)最新版的Chrome支持在onerror的回調(diào)函數(shù) 中獲取出錯(cuò)時(shí)的棧軌跡:window.event.error.stack.

    總結(jié)

    以上是生活随笔為你收集整理的Web应用开发中的几个问题的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。