整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          如何使用Proxy實現JavaScript中的觀察者模式

          軟件開發中,尤其是JavaScript中,觀察者模式是一種行為設計模式,它定義了一種一對多的關系。它允許多個觀察者對象監聽一個主題對象,并在主題狀態發生變化時自動得到通知。這種模式常用于事件系統、數據綁定等場景。

          在JavaScript中,我們可以利用Proxy對象來實現觀察者模式。Proxy對象允許我們攔截和自定義對目標對象的操作,如屬性訪問、賦值、枚舉和函數調用。

          本文將逐步講解如何使用Proxy在JavaScript中實現觀察者模式。我們將創建一個觀察者類,定義一個處理程序對象,并創建一個可觀察對象。此外,我將展示一個常見的前端場景,應用我們的Proxy基礎觀察者實現來解決問題。最后,我將對文章內容進行總結。

          1. 什么是觀察者模式?

          觀察者模式是一種設計模式,其中一個對象(主題)維護一組依賴于它的對象(觀察者),并在其狀態發生變化時通知這些觀察者,通常是通過調用它們的方法。此模式常用于實現分布式事件處理系統。

          2. 使用Proxy實現觀察者模式

          第一步:創建觀察者類

          首先,我們需要創建一個觀察者類,該類將包含添加、刪除和通知觀察者的方法。

          class Observer {
              constructor() {
                  this.observers = [];
              }
          
              addObserver(observer) {
                  this.observers.push(observer);
              }
          
              removeObserver(observer) {
                  this.observers = this.observers.filter(obs => obs !== observer);
              }
          
              notifyObservers(message) {
                  this.observers.forEach(observer => observer.update(message));
              }
          }
          
          class ConcreteObserver {
              update(message) {
                  console.log('Received message:', message);
              }
          }

          在這個例子中,Observer類維護一個觀察者列表,并提供添加、刪除和通知觀察者的方法。ConcreteObserver類是一個具體的觀察者,實現了處理接收通知的update方法。

          第二步:定義處理程序對象

          接下來,我們定義一個處理程序對象,以攔截和處理對可觀察對象的操作。

          const handler = {
              set(target, property, value, receiver) {
                  target[property] = value;
                  target.notifyObservers({ property, value });
                  return true;
              }
          };

          在這個例子中,處理程序對象包含一個set方法,用于攔截對可觀察對象的屬性賦值操作。每當可觀察對象的屬性發生變化時,處理程序將通知所有觀察者。

          第三步:創建可觀察對象

          然后,我們創建一個可觀察對象并用Proxy包裝它。

          class Observable extends Observer {
              constructor(target) {
                  super();
                  return new Proxy(target, handler);
              }
          }
          
          const observableObject = new Observable({ name: 'John', age: 30 });

          在這個例子中,Observable類繼承了Observer類,并用Proxy包裝目標對象,以攔截和處理屬性操作。

          3. 在前端場景中應用觀察者模式

          接下來,我們將展示如何在一個經典的前端數據綁定場景中使用Proxy實現觀察者模式。假設我們有一個簡單的HTML表單,需要實現雙向數據綁定。

          <!DOCTYPE html>
          <html lang="en">
          <head>
              <meta charset="UTF-8">
              <title>Observer Pattern with Proxy</title>
          </head>
          <body>
              <input type="text" id="nameInput" placeholder="Enter your name">
              <p id="nameDisplay"></p>
              <script>
                  // 觀察者類和具體觀察者類
                  class Observer {
                      constructor() {
                          this.observers = [];
                      }
                      addObserver(observer) {
                          this.observers.push(observer);
                      }
                      removeObserver(observer) {
                          this.observers = this.observers.filter(obs => obs !== observer);
                      }
                      notifyObservers(message) {
                          this.observers.forEach(observer => observer.update(message));
                      }
                  }
                  class ConcreteObserver {
                      constructor(element) {
                          this.element = element;
                      }
                      update(message) {
                          this.element.textContent = message.value;
                      }
                  }
                  // 處理程序對象
                  const handler = {
                      set(target, property, value, receiver) {
                          target[property] = value;
                          target.notifyObservers({ property, value });
                          return true;
                      }
                  };
                  // 可觀察類
                  class Observable extends Observer {
                      constructor(target) {
                          super();
                          return new Proxy(target, handler);
                      }
                  }
                  // 創建可觀察對象
                  const data = new Observable({ name: '' });
                  // 創建具體觀察者
                  const nameDisplayObserver = new ConcreteObserver(document.getElementById('nameDisplay'));
                  data.addObserver(nameDisplayObserver);
                  // 處理輸入更改事件
                  document.getElementById('nameInput').addEventListener('input', (event) => {
                      data.name = event.target.value;
                  });
              </script>
          </body>
          </html>

          在這個例子中,我們創建了一個可觀察對象data,并將其name屬性綁定到一個輸入字段和一個顯示段落。當用戶在輸入字段中鍵入時,data.name的值會發生變化。處理程序會攔截此更改并通知所有觀察者。觀察者nameDisplayObserver隨后更新顯示段落的內容,實現了雙向數據綁定。

          通過使用Proxy實現觀察者模式,我們可以有效地攔截和處理對象上的屬性操作,實現雙向數據綁定和響應式更新。本文介紹了觀察者模式的基本概念,并詳細講解了如何在JavaScript中使用Proxy實現該模式。希望本文能幫助你更好地理解和應用這種強大的設計模式在你的項目中。

          天給大家講解的是include標簽,在打代碼的時候總會出現一些重復的樣式,這個時候就可以用include標簽來減少打代碼的次數。


          文件名index.html,代碼:

          {% from 'macros/forms.html' import input %}<!DOCTYPE html><html lang="en"><head>
              <meta charset="UTF-8">
              <title>宏</title>
              <style>
                  *{            list-style: none;            text-decoration: none;        }
                  .header{            height: 60px;            background: #3a3a3a;            color: #fff;            margin-bottom: 20px;        }
                  .header .nav-group{            margin-left: 10px;        }
                  .header .nav-group li{            float: left;            line-height: 60px;            margin: 0px 20px;        }
                  .nav-group li a{            color: #fff;        }
                  .footer{            height: 60px;            background: #3a3a3a;        }
                  .footer p{            color: #fff;            margin-left: 30px;            padding-top: 20px;        }
              </style></head><body>
              <div class="header">
                  <ul class="nav-group">
                      <li><a href="#">新聞</a></li>
                      <li><a href="#">音樂</a></li>
                      <li><a href="#">貼吧</a></li>
                      <li><a href="#">視頻</a></li>
                  </ul>
              </div>
              <table>
                  <tbody>
                      <tr>
                          <td>賬號</td>
                          <td>{{ input(placeholder="請輸入賬號") }}</td>
                      </tr>
                      <tr>
                          <td>密碼</td>
                          <td>{{ input(type="password", placeholder="請輸入密碼") }}</td>
                      </tr>
                      <tr>
                          <td></td>
                          <td>{{ input(type="submit", value="提交") }}</td>
                      </tr>
                  </tbody>
              </table>
              <div class="footer">
                  <p>頁面底部</p>
              </div></body></html>
          

          現在考慮這樣一個問題,如果頁面頭部和底部是很多頁面要用的樣式,那么如果在每一個新的文件中都要復制相同的代碼肯定不是我們希望的,這時候就可以用到include標簽了:

          用法

          {% include '引用文件路徑' %}
          

          用include前提是把相同的代碼先提取出來,所以我們將對應的代碼先提取成文件:

          文件結構:

          headers.html

          <style>
              *{        list-style: none;        text-decoration: none;    }
              .header{        height: 60px;        background: #3a3a3a;        color: #fff;        margin-bottom: 20px;    }
              .header .nav-group{        margin-left: 10px;    }
              .header .nav-group li{        float: left;                line-height: 60px;                margin: 0px 20px;        }
              .nav-group li a{        color: #fff;        }</style><div class="header">
              <ul class="nav-group">
                  <li><a href="#">新聞</a></li>
                  <li><a href="#">音樂</a></li>
                  <li><a href="#">貼吧</a></li>
                  <li><a href="#">視頻</a></li>
              </ul></div>
          

          footers.html

          <style>
              .footer{        height: 60px;        background: #3a3a3a;    }
              .footer p{        color: #fff;        margin-left: 30px;                padding-top: 20px;        }</style><div class="footer">
              <p>頁面底部</p></div>
          

          將公共部分提取出以后在調用的地方只需要用include標簽調用即可:

          index.html

          {% from 'macros/forms.html' import input %}<!DOCTYPE html><html lang="en"><head>
              <meta charset="UTF-8">
              <title>宏</title></head><body>
              {% include 'index/headers.html' %}    <table>
                  <tbody>
                      <tr>
                          <td>賬號</td>
                          <td>{{ input(placeholder="請輸入賬號") }}</td>
                      </tr>
                      <tr>
                          <td>密碼</td>
                          <td>{{ input(type="password", placeholder="請輸入密碼") }}</td>
                      </tr>
                      <tr>
                          <td></td>
                          <td>{{ input(type="submit", value="提交") }}</td>
                      </tr>
                  </tbody>
              </table>
              {% include 'index/footers.html' %}</body></html>
          

          如果還有一個詳情頁,那么只需要:

          detail.html

          <!DOCTYPE html><html lang="en"><head>
              <meta charset="UTF-8">
              <title>Detail</title></head><body>
              {% include 'index/headers.html' %}        <p>這是詳情頁</p>
              {% include 'index/footers.html' %}</body></html>
          

          顯示

          如果對接口、性能、自動化測試、面試經驗交流等感興趣的,可以關注我的頭條號,我會不定期的發放免費的資料,這些資料都是從各個技術網站搜集、整理出來的,如果你有好的學習資料可以私聊發我,我會注明出處之后分享給大家。歡迎分享,歡迎評論,歡迎轉發。需要資料的同學可以關注小編+轉發文章+私信【測試資料】

          文為大家介紹如何使用 CSS 創建一個帶搜索的導航欄。

          以下實例均是響應式的。

          可以先看下效果圖:

          創建一個搜索欄

          HTML 代碼

          <div class="topnav">

          <a class="active" href="#home">主頁</a>

          <a href="#about">關于</a>

          <a href="#contact">聯系我們</a>

          <input type="text" placeholder="搜索..">

          </div>

          CSS 代碼

          /* 在頂部導航欄中添加黑色背景顏色 */

          .topnav {

          overflow: hidden;

          background-color: #e9e9e9;

          }


          主站蜘蛛池模板: 日韩人妻无码一区二区三区99 | 亚洲一区二区三区香蕉| 福利一区二区视频| 内射一区二区精品视频在线观看| 国产精品视频无圣光一区| 日韩精品无码一区二区三区免费| 狠狠色成人一区二区三区| 91精品一区二区三区在线观看| 无码人妻一区二区三区av| 国模丽丽啪啪一区二区| 国产精品一区二区久久| 人妻无码一区二区视频| 91久久精品国产免费一区| 精彩视频一区二区三区| 久久久av波多野一区二区| 无码毛片一区二区三区视频免费播放| 高清一区二区三区日本久| 国产丝袜一区二区三区在线观看 | 日韩一区二区三区在线观看| 亚洲国产成人一区二区三区| 秋霞日韩一区二区三区在线观看| 亚洲一区精品无码| 精品一区二区三区在线观看l | 人妻在线无码一区二区三区| A国产一区二区免费入口| 亚洲av色香蕉一区二区三区 | 久久久久久人妻一区二区三区| 中文字幕日本精品一区二区三区| 伊人色综合网一区二区三区| 国产一区在线视频| 波多野结衣中文字幕一区二区三区| 人妻无码第一区二区三区| 变态拳头交视频一区二区| 国产精品免费视频一区| 精品人妻系列无码一区二区三区| 香蕉一区二区三区观| 国产在线观看一区二区三区四区| AV鲁丝一区鲁丝二区鲁丝三区 | 无码人妻久久一区二区三区| 国产精品被窝福利一区| 国产免费私拍一区二区三区|