国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

SPA那點(diǎn)事

Lsnsh / 2402人閱讀

摘要:單頁面應(yīng)用的出現(xiàn)依然存在著爭議性,我們該如何看待他的兩面性呢接下來小生給大家總結(jié)一下他的優(yōu)缺點(diǎn)。單頁面應(yīng)用的優(yōu)勢無刷新體驗(yàn)沒有了令人詬病的頁面頻繁刷新,同時(shí)節(jié)約瀏覽器資源,路由響應(yīng)比較及時(shí),提升了用戶的體驗(yàn)。

前端猿一天不學(xué)習(xí)就沒飯吃了,后端猿三天不學(xué)習(xí)仍舊有白米飯擺于桌前。IT行業(yè)的快速發(fā)展一直在推動著前端技術(shù)棧在不斷地更新?lián)Q代,前端的發(fā)展成了互聯(lián)網(wǎng)時(shí)代的一個(gè)縮影。而單頁面應(yīng)用的發(fā)展給前端猿分了一杯羹。

認(rèn)識SPA

最早單頁面的應(yīng)用無從知曉,在2004年,google的Gmail就使用了單頁面。到了2010年,隨著Backbone的問世之后,此概念才慢慢熱了起來。隨著后來React、Angular、Vue的興起,單頁面應(yīng)用才成了前端圈里人人皆知的架構(gòu)模式。接下來小生將通過對比傳統(tǒng)頁面應(yīng)用和單頁面應(yīng)用來說明SPA具體是什么。

傳統(tǒng)的頁面應(yīng)用

早期web應(yīng)用的前后端交互模式是這樣的,每個(gè)html作為一個(gè)功能元件,通過刷新、超鏈接、表單提交等方式,將頁面組織起來后給用戶提供交互。

后期很多流行的框架都是基于此模式進(jìn)行設(shè)計(jì)的,比如 Ruby on Rails,Spring MVC,Express 等等

傳統(tǒng)的web應(yīng)用中,瀏覽器只是作為展示層,路由、服務(wù)調(diào)用、頁面跳轉(zhuǎn)都是服務(wù)端來處理的。也就是MVC的架構(gòu)都是放在后端的,只有V這一層,將頁面通過網(wǎng)絡(luò)發(fā)送到瀏覽器端,渲染給用戶。

傳統(tǒng)的模式具有以下特點(diǎn):

重服務(wù)端:瀏覽器只作為展示層,將MVC全置于后端,加重了服務(wù)端的體量,開發(fā)中主要以后端為主。

頻繁刷新:頁面展示依賴于不同的功能元件,所以必須依靠刷新頁面,或者跳轉(zhuǎn)路由來實(shí)現(xiàn)功能塊的切換,這種方式嚴(yán)重耗費(fèi)資源,同時(shí)用戶體驗(yàn)很差。

單頁面應(yīng)用

和傳統(tǒng)應(yīng)用相比較,單頁面應(yīng)用就是將MVC個(gè)架構(gòu)搬到了前端來實(shí)現(xiàn)

控制器:將處理路由的功能放在前端,當(dāng)瀏覽器的路由發(fā)生變化時(shí),由控制器來響應(yīng)其變化,指向其對應(yīng)的處理邏輯(組件),最終將頁面展現(xiàn)給用戶。

視圖:這一層就是功能元件,也就是單個(gè)的組件,當(dāng)路由發(fā)生變化的時(shí)候由組件來處理,只處理變化的那部分,最后組織成頁面。

數(shù)據(jù)層:單頁面應(yīng)用有自己的數(shù)據(jù)層定義,簡化了后端服務(wù)的復(fù)雜度,后端只要提供公共的數(shù)據(jù)接口即可,而數(shù)據(jù)層會對數(shù)據(jù)服務(wù)API進(jìn)行進(jìn)一步的封裝,然后提供數(shù)據(jù)給視圖層。

如此看來單頁面應(yīng)用很像移動客戶端,后端的精力就是提供高質(zhì)量的、可復(fù)用的Rest API服務(wù)。

世間萬物皆有裂痕,哪又怎樣?裂痕,那是光照進(jìn)來的地方。

單頁面應(yīng)用的出現(xiàn)依然存在著爭議性,我們該如何看待他的兩面性呢?接下來小生給大家總結(jié)一下他的優(yōu)缺點(diǎn)。

單頁面應(yīng)用的優(yōu)勢:

無刷新體驗(yàn):沒有了令人詬病的頁面頻繁刷新,同時(shí)節(jié)約瀏覽器資源,路由響應(yīng)比較及時(shí),提升了用戶的體驗(yàn)。

共享組件:前端組件化是將獨(dú)立完整的功能模塊封裝到一個(gè)組件中,代碼結(jié)構(gòu)更加規(guī)范,便于代碼維護(hù),同時(shí)模塊化后的組件可以在不同的場景中進(jìn)行復(fù)用,極大地加快了迭代開發(fā)的速度。這也是為什么主流的前端框架都提倡組件化編程的原因。

共享API:給后端減負(fù),前端加碼的好處就是,前端能有一點(diǎn)口糧吃了(開玩笑,前端那么牛怎么能沒飯吃呢?),前端擔(dān)起家務(wù)的事,后端就可以安心地處理業(yè)務(wù)邏輯了,于是才能寫出高質(zhì)量并可共享的API,供自己或者其他的合作伙伴使用。一個(gè)優(yōu)秀的產(chǎn)品背后,一定有一群出色的前端(小生臉皮太厚)。

單頁面應(yīng)用的劣勢:

抬高了前端門檻:SPA模式的流行,引領(lǐng)了前端技術(shù)的飛速發(fā)展,與此同時(shí)對前端人員在學(xué)習(xí)和使用上的能力就有了更高的要求,同時(shí)工作量也增加了,前端想活的更好就要付出的更多,所以不要再以為前端就是切切圖,畫畫頁面這么簡單。too young, too naive。

首次加載大量資源:既然只有一個(gè)頁面顯示,那許多功能元件(組件)所依賴的靜態(tài)資源就需要在初次時(shí)進(jìn)行加載,加載時(shí)間相對比較長。

不利于SEO:單頁面應(yīng)用,數(shù)據(jù)都是在前端進(jìn)行渲染的,所以就影響了SEO。

徒手實(shí)現(xiàn)SPA

隨著SPA的流行,目前主流的框架都實(shí)現(xiàn)了SPA模式,包括我們夏洛克產(chǎn)品里面用到的Angular和Vue。但是作為一家愛折騰公司里面愛折騰的前端團(tuán)隊(duì)里面愛折騰的人,我們總想跟自己較勁來試試自己去實(shí)現(xiàn)簡單的模式,這次小生也簡單地實(shí)現(xiàn)了一把,于是將其分享于諸位,目前只是簡單的模型,不能用于生產(chǎn)(主流框架都有,干嘛用我的?學(xué)習(xí)一下思想即可),除非你愿意折騰。在此之前需要介紹幾個(gè)核心點(diǎn):

路由:小生使用H5中的History API來管理路由的更新(地址欄URL更新、前進(jìn)、后退)。

視圖:小生還是使用原生的Document來操作,目前渲染的內(nèi)容比較簡單。

數(shù)據(jù)層:小生使用XMLHttpRequest寫了一個(gè)Ajax服務(wù),幫助請求后端數(shù)據(jù)(此服務(wù)較簡單,不適用生產(chǎn)環(huán)境)。

H5 History API

關(guān)于H5 History API在此需要介紹一下,他是HTML5引入的操作瀏覽器路由歷史堆棧的內(nèi)容,其中兩個(gè)主要的方法為history.pushState(stateObj, title, URL) 和 history.replaceState(stateObj, title, URL) 方法,它們分別可以添加和修改歷史記錄條目。這些方法通常與window.onpopstate 配合使用。三個(gè)參數(shù)分別為:

狀態(tài)對象 — 狀態(tài)對象是一個(gè)JavaScript對象,通過pushState () 創(chuàng)建新的歷史記錄條目。無論什么時(shí)候用戶導(dǎo)航到新的狀態(tài),popstate事件就會被觸發(fā),且該事件的state屬性包含該歷史記錄條目狀態(tài)對象的副本。

title — Firefox 目前忽略這個(gè)參數(shù),但未來可能會用到。

URL — 該參數(shù)定義了新的歷史URL記錄。注意,調(diào)用 pushState() 后瀏覽器并不會立即加載這個(gè)URL,但可能會在稍后某些情況下加載這個(gè)URL,比如在用戶重新打開瀏覽器時(shí)。新URL不必須為絕對路徑。如果新URL是相對路徑,那么它將被作為相對于當(dāng)前URL處理。新URL必須與當(dāng)前URL同源,否則 pushState() 會拋出一個(gè)異常。該參數(shù)是可選的,缺省為當(dāng)前URL。

小生結(jié)合window.onpopstate事件來監(jiān)聽瀏覽器前進(jìn)和后退的動作來重新請求數(shù)據(jù)服務(wù),更新視圖。

每當(dāng)處于激活狀態(tài)的歷史記錄條目發(fā)生變化時(shí), popstate事件就會在對應(yīng)window對象上觸發(fā)。 如果當(dāng)前處于激活狀態(tài)的歷史記錄條目是由history.pushState()方法創(chuàng)建, 或者由history.replaceState()方法修改過的, 則popstate事件對象的state屬性包含了這個(gè)歷史記錄條目的state對象的一個(gè)拷貝。

調(diào)用history.pushState()或者h(yuǎn)istory.replaceState()不會觸發(fā)popstate事件. popstate事件只會在瀏覽器某些行為下觸發(fā), 比如點(diǎn)擊后退、前進(jìn)按鈕(或者在JavaScript中調(diào)用history.back()、history.forward()、history.go()方法)。

目錄結(jié)構(gòu)
-- data
  -- auto.json
  -- contact.json
  -- home.json
  -- platform.json
  -- sharplook.json
-- ajax.js
-- index.js
-- index.html
-- index.css
源碼分享

data文件下是模擬的后端數(shù)據(jù),數(shù)據(jù)的結(jié)構(gòu)都與下面一樣,比如home.json

{
 "content": "上海擎創(chuàng)信息技術(shù)有限公司是專業(yè)服務(wù)于企業(yè)級客戶的ITOA智能運(yùn)營大數(shù)據(jù)分析解決方案提供商,專注于將人工智能技術(shù)賦予IT運(yùn)維管理,創(chuàng)造具備分析和思考能力的IT管理軟件,讓每家企業(yè)都擁有自己的IT運(yùn)維專家。"
}

ajax.js的代碼如下:

function ajax() {
  const ajaxData = {
    type: arguments[0].type || "GET",
    url: arguments[0].url || "",
    async: arguments[0].async || "true",
    data: arguments[0].data || null,
    dataType: arguments[0].dataType || "text",
    contentType: arguments[0].contentType || "application/x-www-form-urlencoded",
    beforeSend: arguments[0].beforeSend || function () {},
    success: arguments[0].success || function () {},
    error: arguments[0].error || function () {}
  }
  ajaxData.beforeSend()
  const xhr = _createxmlHttpRequest();
  xhr.responseType = ajaxData.dataType;
  xhr.open(ajaxData.type, ajaxData.url, ajaxData.async);
  xhr.setRequestHeader("Content-Type", ajaxData.contentType);
  xhr.send(_convertData(ajaxData.data));
  xhr.onreadystatechange = function () {
    if (xhr.readyState == 4) {
      if (xhr.status == 200) {
        ajaxData.success(xhr.response);
      } else {
        ajaxData.error();
      }
    }
  }
}

function _createxmlHttpRequest() {
  if (window.ActiveXObject) {
    return new ActiveXObject("Microsoft.XMLHTTP");
  } else if (window.XMLHttpRequest) {
    return new XMLHttpRequest();
  }
}

function _convertData(data) {
  if (typeof data === "object") {
    let convertResult = "";
    for (let c in data) {
      convertResult += `${c}=${data[c]}&`;
    }
    convertResult = convertResult.substring(0, convertResult.length - 1);
    return convertResult;
  } else {
    return data;
  }
}

index.html的代碼如下:






  SPA
  
  
  



  
SHARPLOOK 大數(shù)據(jù)運(yùn)維監(jiān)控平臺

index.js的代碼如下:

class SPA {
  constructor () {
    this.elment = void 0;
    this.menu = Array.from(document.getElementsByTagName("a"));
  }

  getCurrentHash() {
    return window.history.state ? window.history.state.hash : "/home";
  }

  isSupportH5History() {
    return !!(window.history && window.history.pushState);
  }

  setElement(hash) {
    if (!hash) { // 默認(rèn)為根路由 ‘/’
      this.elment = this.menu[0];
    } else {
      this.menu.forEach(item => {
        if(item.getAttribute("href") === hash) {
          this.elment = item;
        }
      });
    }
  }

  renderData() {
    const contentElement = document.getElementById("p");
    this.loadData(contentElement, this.elment.getAttribute("href").split("/")[1]);
  }

  addHistory(hash, isReplace) {
    const stateObj = { hash };
    if(isReplace) {
      window.history.replaceState(stateObj, null, hash);
    } else {
      window.history.pushState(stateObj, null, hash);
    }
  }

  loadData(contentElement, type) {
    ajax({
      type: "get",
      url: `/data/${type}.json`,
      dataType: "json",
      success: function(msg) {
        console.log(msg);
        contentElement.innerText = msg.content;
      },
      error: function() {
        console.log("error")
      }
    })
  };

  popStateHandler(linkHash, isPopState = false) {
    if(!linkHash) {// 刷新界面時(shí)候,默認(rèn)獲取刷新之前的路由信息
      this.addHistory(this.getCurrentHash(), true);
    } else {
      if(!isPopState) this.addHistory(linkHash, false);
    }
    this.setElement(this.getCurrentHash());
    this.renderData();
    this.addActiveClass();
  }

  bindLiClick() {
    const list = document.getElementsByTagName("li");
    Array.from(list).forEach(item => {
      item.onclick = (event) => {
        const linkHash = item.childNodes[0].getAttribute("href");
        this.popStateHandler(linkHash);
      }
    });
  }

  addActiveClass() {
    this.menu.forEach(item => {
      item.parentNode.classList.remove("active");
    })
    this.elment.parentNode.classList.add("active");
  }

  init() {
    if(!this.isSupportH5History()) throw new Error("對不起!不支持 H5 History API!");
    this.bindLiClick();
    window.onpopstate = (event) => {
      this.popStateHandler(event.state.hash, true);
    }
    // 首次默認(rèn)首次進(jìn)入頁面
    this.popStateHandler();
  }
}

index.css的代碼如下:

* {
  margin: 0;
  padding: 0;
}

html, body {
  height: 100%;
}

.container {
  height: 100%;
  display: flex;
  flex-direction: column;
}

.bar {
  background-color: #213442;
  color: white;
  height: 60px;
  display: flex;
  align-items: center;
  font-size: 20px;
}

.body {
  display: flex;
  height: calc(100% - 60px);
  border-top: 1px solid #ccc;
}

#content {
  border: 1px solid #ccc;
  border-radius: 3px;
  padding: 10px;
  width: 600px;
  box-shadow: 5px 5px 15px 0 #bbb;
}

#nav {
  background-color: #213442;
  width: 120px;
  text-align: center;
}

a {
  color: white;
  text-decoration: none;
  pointer-events: none;
}

#content-main {
  flex: 1;
  display: flex;
  justify-content: center;
  align-items: center;
}

.title {
  padding-left: 20px;
}
 li {
  margin: 10px 0;
  line-height: 30px;
  cursor: pointer;
 }

 li:hover {
   background-color: #00A5D5;
 }

 .active {
  background-color: #00A5D5;
 }

代碼的具體邏輯不做過多介紹,特別需要注意的是請將代碼部署到web服務(wù)器上查看效果,因?yàn)閔istory api需要在同域里面才能使用,否則報(bào)錯(cuò),愛學(xué)習(xí)的小伙伴請自行學(xué)習(xí)。 完整代碼

效果圖

小結(jié)

小生給大家介紹了目前web開發(fā)的SPA模式,希望諸君在使用主流框架時(shí)能進(jìn)一步了解其原理,你我共勉。小生基于H5的History實(shí)現(xiàn)了一個(gè)簡單的SPA模式,僅供學(xué)習(xí)之用,最后小生想說,身為后端轉(zhuǎn)為前端的前端猿,感覺前端的技術(shù)棧應(yīng)是最有活力的,因?yàn)橐坏┠悴幌雱恿耍腿鐪厮锏那嗤埽嚯x另一個(gè)世界也就近了,祝君能像前端的發(fā)展勢頭一樣,活力四射,不斷進(jìn)步。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/88620.html

相關(guān)文章

  • SPA點(diǎn)事

    摘要:單頁面應(yīng)用的出現(xiàn)依然存在著爭議性,我們該如何看待他的兩面性呢接下來小生給大家總結(jié)一下他的優(yōu)缺點(diǎn)。單頁面應(yīng)用的優(yōu)勢無刷新體驗(yàn)沒有了令人詬病的頁面頻繁刷新,同時(shí)節(jié)約瀏覽器資源,路由響應(yīng)比較及時(shí),提升了用戶的體驗(yàn)。 前端猿一天不學(xué)習(xí)就沒飯吃了,后端猿三天不學(xué)習(xí)仍舊有白米飯擺于桌前。IT行業(yè)的快速發(fā)展一直在推動著前端技術(shù)棧在不斷地更新?lián)Q代,前端的發(fā)展成了互聯(lián)網(wǎng)時(shí)代的一個(gè)縮影。而單頁面應(yīng)用的發(fā)展...

    PumpkinDylan 評論0 收藏0
  • SPA點(diǎn)事

    摘要:單頁面應(yīng)用的出現(xiàn)依然存在著爭議性,我們該如何看待他的兩面性呢接下來小生給大家總結(jié)一下他的優(yōu)缺點(diǎn)。單頁面應(yīng)用的優(yōu)勢無刷新體驗(yàn)沒有了令人詬病的頁面頻繁刷新,同時(shí)節(jié)約瀏覽器資源,路由響應(yīng)比較及時(shí),提升了用戶的體驗(yàn)。 前端猿一天不學(xué)習(xí)就沒飯吃了,后端猿三天不學(xué)習(xí)仍舊有白米飯擺于桌前。IT行業(yè)的快速發(fā)展一直在推動著前端技術(shù)棧在不斷地更新?lián)Q代,前端的發(fā)展成了互聯(lián)網(wǎng)時(shí)代的一個(gè)縮影。而單頁面應(yīng)用的發(fā)展...

    lijinke666 評論0 收藏0
  • 移動端鍵盤和光標(biāo)的兼容點(diǎn)事

    摘要:解決方法如果使用頁面數(shù)據(jù)不超過一屏禁止?jié)L動,那么即使變成了頁面也不會有什么變化。 作者:@micky思 @wupq @yewq 在H5的開發(fā)中,個(gè)人的制作頁面布局習(xí)性不同,多多少少會產(chǎn)生在真機(jī)上input的光標(biāo)和鍵盤的彈出會出現(xiàn)的各種BUG,文中整理了部分遇到的問題,歡迎新增 ios移動端輸入框上浮導(dǎo)致輸入位置偏移 問題原因:遮罩層定位為fixed,當(dāng)鍵盤彈起時(shí),ios11以及以下...

    XboxYan 評論0 收藏0
  • 移動端鍵盤和光標(biāo)的兼容點(diǎn)事

    摘要:解決方法如果使用頁面數(shù)據(jù)不超過一屏禁止?jié)L動,那么即使變成了頁面也不會有什么變化。 作者:@micky思 @wupq @yewq 在H5的開發(fā)中,個(gè)人的制作頁面布局習(xí)性不同,多多少少會產(chǎn)生在真機(jī)上input的光標(biāo)和鍵盤的彈出會出現(xiàn)的各種BUG,文中整理了部分遇到的問題,歡迎新增 ios移動端輸入框上浮導(dǎo)致輸入位置偏移 問題原因:遮罩層定位為fixed,當(dāng)鍵盤彈起時(shí),ios11以及以下...

    Kerr1Gan 評論0 收藏0

發(fā)表評論

0條評論

Lsnsh

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<