ホームページ > ウェブフロントエンド > jsチュートリアル > jsパブリッシャー・サブスクライバーパターンの使用方法の詳細な説明

jsパブリッシャー・サブスクライバーパターンの使用方法の詳細な説明

php中世界最好的语言
リリース: 2018-04-18 15:21:17
オリジナル
3006 人が閲覧しました

今回は、js パブリッシャー-サブスクライバー モデルの使用方法について詳しく説明します。 js パブリッシャー-サブスクライバー モデルを使用する際の 注意事項 について、実際のケースを見てみましょう。

パブリッシャーとサブスクライバーのモデルは、次のような非常に一般的なモデルです。

1. 家の売買

人生における住宅の売買では、仲介業者は出版・購読者モデルを形成します。住宅を購入する人は一般に、住宅の空室状況、価格、使用可能な面積などの情報を必要とします。彼は購読者の役割を果たします

。 エージェントは売主の住宅情報を取得し、手元にある顧客の連絡先情報(住宅を購入する人の携帯電話番号)を基に買主に通知し、発行者としての役割を果たします

売主が家を売りたい場合は、仲介業者にその旨を伝え、情報を解放してもらう必要があります

2. ウェブサイト上の情報を購読するユーザー

購読者の役割: Web サイトで

javascript タイプの記事

など、特定の種類の情報を購読する必要があるインターネット ユーザー パブリッシャーの役割: メールボックス サーバー。Web サイトによって収集されたユーザー サブスクリプション メールボックスに基づいてユーザーに通知します。

ウェブサイトの所有者が購読者に情報を伝えたい場合は、送信する記事の関連コンテンツを電子メール サーバーに伝える必要があります

例はたくさんあるので、すべてをリストすることはできません

この記事では、Web サイトのサブスクリプションを使用してパブリッシャーとサブスクライバーのフレームワークを導出し、その後、パブリッシャーとサブスクライバーのフレームワークを使用して単純なショッピング カートを再構築します

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( &#39;javascript&#39; );
    Site.publish( &#39;html5&#39; );
ログイン後にコピー

Site.userList は購読者を保存するために使用されます

Site.subscribeは特定の購読者であり、各購読者が購読した特定の情報をSite.userListに保存します

Site.publish はパブリッシャーです。保存された userList に従って、1 つずつトラバース (通知) し、内部のビジネス ロジックを実行します

しかし、このパブリッシュ サブスクライバー モデルには問題があります。上の例では、2 つのサブスクライバー (行 11、行 14) を追加しましたが、Web サイトが情報を送信する限り、すべてのメッセージを受信できます。ただし、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( &#39;没有人订阅&#39; + 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 Master's Road】寄生組み合わせ継承のメリット

【jsマスターへの道】es6シリーズチュートリアル - var、let、constを詳しく解説

カテゴリ html5 の記事を購読している人はいません

JavaScript タイプの記事を購読した人だけが「寄生組み合わせ継承の利点」記事を受け取ることができることがわかります。HTML5 タイプを公開すると、誰も受け取らないことがわかります。 es6タイプ、es6に加入している方のみ受け取れます

基本的なパブリッシャーとサブスクライバーのフレームワークはすでにあります。次に、それを他の機能や他の Web サイト システムの同じ機能で再利用できるようにフレームワークに改良します

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(&#39;没有人订阅&#39; + 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>
<p 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>
  <p class="total-box">
    商品一共
    <span id="goods-num">0</span>
    件;
    一共花费
    <span id="total-price">0</span>
    元;
    其中最贵的商品单价是<span id="unit-price">0</span>元
  </p>
</p>
</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 );
}
ログイン後にコピー
この記事の事例を読んだ後は、この方法を習得したと思います。さらに興味深い情報については、php 中国語 Web サイトの他の関連記事に注目してください。

推奨読書:

es6を分解する方法とは何ですか


Node.jsファイルシステム操作

以上がjsパブリッシャー・サブスクライバーパターンの使用方法の詳細な説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート