ホームページ > 記事 > ウェブフロントエンド > jsパブリッシャー・サブスクライバーパターンの使用方法の詳細な説明
今回は、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( 'javascript' ); Site.publish( 'html5' );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( '没有人订阅' + 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('没有人订阅' + 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を分解する方法とは何ですか
以上がjsパブリッシャー・サブスクライバーパターンの使用方法の詳細な説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。