国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > JavaScript > 正文

[js高手之路]設計模式系列課程-發布者,訂閱者重構購物車的實例

2019-11-19 15:38:57
字體:
來源:轉載
供稿:網友

發布者訂閱者模式,是一種很常見的模式,比如:

一、買賣房子

生活中的買房,賣房,中介就構成了一個發布訂閱者模式,買房的人,一般需要的是房源,價格,使用面積等信息,他充當了訂閱者的角色

中介拿到賣主的房源信息,根據手頭上掌握的客戶聯系信息(買房的人的手機號),通知買房的人,他充當了發布者的角色

賣主想賣掉自己的房子,就需要告訴中介,把信息交給中介發布

二,網站訂閱信息的用戶

訂閱者角色:需要訂閱某類信息的網民,如某個網站的javascript類型文章

發布者角色:郵箱服務器,根據網站收集到的用戶訂閱郵箱,通知用戶.

網站主想把信息告訴訂閱者,需要把文章相關內容告訴郵箱服務器去發送

等等非常多的例子,不一一列舉

本文用網站訂閱的方式,推導發布者-訂閱者框架,然后用發布者-訂閱者框架來重構一個簡單的購物車

var Site = {};    Site.userList = [];    Site.subscribe = function( fn ){      this.userList.push( fn );    }    Site.publish = function(){      for( var i = 0, len = this.userList.length; i < len; i++ ){        this.userList[i].apply( this, arguments );      }     }    Site.subscribe( function( type ){      console.log( "網站發布了" + type + "內容" );    });    Site.subscribe( function( type ){      console.log( "網站發布了" + type + "內容" );    });    Site.publish( 'javascript' );    Site.publish( 'html5' );

Site.userList就是用來保存訂閱者

Site.subscribe就是具體的訂閱者,把每一個訂閱者訂閱的具體信息保存在Site.userList

Site.publish就是發布者:根據保存的userList,一個個遍歷(通知),執行里面的業務邏輯

但是這個,發布訂閱者模式,有個問題,不能訂閱想要的類型,上例我加了2個訂閱者(第11行,第14行),只要網站發了信息,全部能收到,但是有些用戶可能只想收到javascript或者html5的,所以,接下來,我們需要繼續完善,希望能夠接收到具體的信息,不是某人訂閱的類型,就不接收

var Site = {};    Site.userList = {};    Site.subscribe = function (key, fn) {      if (!this.userList[key]) {        this.userList[key] = [];      }      this.userList[key].push(fn);    }    Site.publish = function () {      var key = Array.prototype.shift.apply(arguments),        fns = this.userList[key];      if ( !fns || fns.length === 0) {        console.log( '沒有人訂閱' + key + "這個分類的文章" );        return false;      }      for (var i = 0, len = fns.length; i < len; i++) {        fns[i].apply(this, arguments);      }    }    Site.subscribe( "javascript", function( title ){      console.log( title );    });    Site.subscribe( "es6", function( title ){      console.log( title );    });    Site.publish( "javascript", "[js高手之路]寄生組合式繼承的優勢" );    Site.publish( "es6", "[js高手之路]es6系列教程 - var, let, const詳解" );    Site.publish( "html5", "html5新的語義化標簽" );

輸出結果:

[js高手之路]寄生組合式繼承的優勢

[js高手之路]es6系列教程 - var, let, const詳解

沒有人訂閱html5這個分類的文章

我們可以看到,只有訂閱了javascript類型文章的人,才能收到 ”寄生組合式繼承的優勢” 這篇文章,發布html5類型的時候,沒有任何人會收到.

es6類型的,只有訂閱es6的人,才能收到

我們已經有了一個基本的發布訂閱者框架,接下來,把他完善成一個框架,便于其他功能或者其他網站系統的相同功能可以重用他

var Event = {      userList : {},      subscribe : function (key, fn) {        if (!this.userList[key]) {          this.userList[key] = [];        }        this.userList[key].push(fn);      },      publish : function () {        var key = Array.prototype.shift.apply(arguments),          fns = this.userList[key];        if (!fns || fns.length === 0) {          console.log('沒有人訂閱' + key + "這個分類的文章");          return false;        }        for (var i = 0, len = fns.length; i < len; i++) {          fns[i].apply(this, arguments);        }      }    };    var extend = function( dstObj, srcObj ){      for( var key in srcObj ){        dstObj[key] = srcObj[key];      }    }    var Site = {};    extend( Site, Event );     Site.subscribe( "javascript", function( title ){      console.log( title );    });    Site.subscribe( "es6", function( title ){      console.log( title );    });    Site.publish( "javascript", "寄生組合式繼承的優勢" );    Site.publish( "es6", "es6系列教程 - var, let, const詳解" );    Site.publish( "html5", "html5新的語義化標簽" );

然后,我們來重構一個購物車實例,沒有重構之前,我的購物車用的是面向過程:

<!DOCTYPE html><html lang="en"><head>  <meta charset="UTF-8">  <title>Title</title>  <script src="js/cart.js"></script></head><body><div id="box">  <ul>    <li>      <input type="button" value="-">      <span class="num">0</span>      <input type="button" value="+">      <span>單價:</span>      <span class="unit">15元;</span>      <span class="label">小計:</span>      <span class="subtotal">0</span>元    </li>    <li>      <input type="button" value="-">      <span class="num">0</span>      <input type="button" value="+">      <span>單價:</span>      <span class="unit">10元;</span>      <span class="label">小計:</span>      <span class="subtotal">0</span>元    </li>    <li>      <input type="button" value="-">      <span class="num">0</span>      <input type="button" value="+">      <span>單價:</span>      <span class="unit">5元;</span>      <span class="label">小計:</span>      <span class="subtotal">0</span>元    </li>    <li>      <input type="button" value="-">      <span class="num">0</span>      <input type="button" value="+">      <span>單價:</span>      <span class="unit">2元;</span>      <span class="label">小計:</span>      <span class="subtotal">0</span>元    </li>    <li>      <input type="button" value="-">      <span class="num">0</span>      <input type="button" value="+">      <span>單價:</span>      <span class="unit">1元;</span>      <span class="label">小計:</span>      <span class="subtotal">0</span>元    </li>  </ul>  <div class="total-box">    商品一共    <span id="goods-num">0</span>    件;    一共花費    <span id="total-price">0</span>    元;    其中最貴的商品單價是<span id="unit-price">0</span>元  </div></div></body></html>

cart.js文件:

function getByClass(cName, obj) {  var o = null;  if (arguments.length == 2) {    o = obj;  } else {    o = document;  }  var allNode = o.getElementsByTagName("*");  var aNode = [];  for( var i = 0 ; i < allNode.length; i++ ){    if( allNode[i].className == cName ){     aNode.push( allNode[i] );    }  }  return aNode;}function getSubTotal( unitPrice, goodsNum ){  return unitPrice * goodsNum;}function getSum(){ //計算總花費  var aSubtotal = getByClass("subtotal");  var res = 0;  for( var i = 0; i < aSubtotal.length; i++ ){    res += parseInt(aSubtotal[i].innerHTML);  }  return res;}function compareUnit() { //比單價,找出最高的單價  var aNum = getByClass( "num");  var aUnit = getByClass( "unit");  var temp = 0;  for( var i = 0; i < aNum.length; i++ ){    if( parseInt(aNum[i].innerHTML) != 0 ){      if( temp < parseInt(aUnit[i].innerHTML) ) {        temp = parseInt(aUnit[i].innerHTML);      }    }  }  return temp;}window.onload = function () {  var aInput = document.getElementsByTagName("input");  var total = 0;  var oGoodsNum = document.getElementById("goods-num");  var oTotalPrice = document.getElementById("total-price");  var oUnitPrice = document.getElementById("unit-price");  for (var i = 0; i < aInput.length; i++) {    if (i % 2 != 0) { //加號      aInput[i].onclick = function () {        //當前加號所在行的數量        var aNum = getByClass( "num", this.parentNode );        var n = parseInt( aNum[0].innerHTML );        n++;        aNum[0].innerHTML = n;        //獲取單價        var aUnit = getByClass( "unit", this.parentNode );        var unitPrice = parseInt(aUnit[0].innerHTML);        var subtotal = getSubTotal( unitPrice, n );        var aSubtotal = getByClass( "subtotal", this.parentNode );        aSubtotal[0].innerHTML = subtotal;        total++; //商品總數        oGoodsNum.innerHTML = total;        oTotalPrice.innerHTML = getSum();        oUnitPrice.innerHTML = compareUnit();      }    }else {      aInput[i].onclick = function(){        var aNum = getByClass( "num", this.parentNode );        if ( parseInt( aNum[0].innerHTML ) != 0 ){          var n = parseInt( aNum[0].innerHTML );          n--;          aNum[0].innerHTML = n;          //獲取單價          var aUnit = getByClass( "unit", this.parentNode );          var unitPrice = parseInt(aUnit[0].innerHTML);          var subtotal = getSubTotal( unitPrice, n );          var aSubtotal = getByClass( "subtotal", this.parentNode );          aSubtotal[0].innerHTML = subtotal;          total--; //商品總數          oGoodsNum.innerHTML = total;          oTotalPrice.innerHTML = getSum();          oUnitPrice.innerHTML = compareUnit();        }      }    }  }}

耦合度太高,可維護性很差.

重構之后的購物車:

window.onload = function () {  var Event = {    userList: {},    subscribe: function (key, fn) {      if (!this.userList[key]) {        this.userList[key] = [];      }      this.userList[key].push(fn);    },    publish: function () {      var key = Array.prototype.shift.apply(arguments),        fns = this.userList[key];      if (!fns || fns.length === 0) {        return false;      }      for (var i = 0, len = fns.length; i < len; i++) {        fns[i].apply(this, arguments);      }    }  };  (function(){    var aBtnMinus = document.querySelectorAll( "#box li>input:first-child"),      aBtnPlus = document.querySelectorAll( "#box li>input:nth-of-type(2)"),      curNum = 0, curUnitPrice = 0;    for( var i = 0, len = aBtnMinus.length; i < len; i++ ){      aBtnMinus[i].index = aBtnPlus[i].index = i;      aBtnMinus[i].onclick = function(){        (this.parentNode.children[1].innerHTML > 0) && Event.publish( "total-goods-num-minus" );        --this.parentNode.children[1].innerHTML < 0 && (this.parentNode.children[1].innerHTML = 0);        curUnitPrice = this.parentNode.children[4].innerHTML;        Event.publish( "minus-num" + this.index,           parseInt( curUnitPrice ),          parseInt( this.parentNode.children[1].innerHTML )        );      };      aBtnPlus[i].onclick = function(){        (this.parentNode.children[1].innerHTML >= 0) && Event.publish( "total-goods-num-plus" );        this.parentNode.children[1].innerHTML++;        curUnitPrice = this.parentNode.children[4].innerHTML;        Event.publish( "plus-num" + this.index,           parseInt( curUnitPrice ),          parseInt( this.parentNode.children[1].innerHTML )        );      }    }  })();  (function(){    var aSubtotal = document.querySelectorAll("#box .subtotal"),      oGoodsNum = document.querySelector("#goods-num"),      oTotalPrice = document.querySelector("#total-price");      Event.subscribe( 'total-goods-num-plus', function(){        ++oGoodsNum.innerHTML;      });      Event.subscribe( 'total-goods-num-minus', function(){        --oGoodsNum.innerHTML;      });    for( let i = 0, len = aSubtotal.length; i < len; i++ ){      Event.subscribe( 'minus-num' + i, function( unitPrice, num ){        aSubtotal[i].innerHTML = unitPrice * num;      });      Event.subscribe( 'plus-num' + i, function( unitPrice, num ){        aSubtotal[i].innerHTML = unitPrice * num;      });    }  })();  console.log( Event.userList );}

以上這篇[js高手之路]設計模式系列課程-發布者,訂閱者重構購物車的實例就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支持武林網。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 留坝县| 独山县| 临沧市| 景泰县| 正蓝旗| 肥乡县| 运城市| 疏勒县| 宣威市| 荔波县| 阿勒泰市| 什邡市| 资源县| 翁源县| 金华市| 视频| 永泰县| 寿阳县| 洪雅县| 仁布县| 同德县| 上林县| 榆树市| 任丘市| 铅山县| 克拉玛依市| 平果县| 化德县| 蓬安县| 资溪县| 大新县| 英山县| 秭归县| 闽侯县| 连山| 双牌县| 黔东| 孝感市| 安顺市| 沙田区| 丹凤县|