Web APIs

来源:https://www.cnblogs.com/SRIGT/p/18134525
-Advertisement-
Play Games

0x01 概述 API 是一些預先定義的函數,提供應用程式與開發人員基於某軟體或硬體訪問一組常式的能力 Web APIs 是 W3C 組織的標準,是 JS 獨有的部分 Web API 是瀏覽器提供的一套操作瀏覽器功能和頁面元素的 API,即 DOM 與 BOM 0x02 DOM (1)簡介 文檔對象 ...


0x01 概述

  • API 是一些預先定義的函數,提供應用程式與開發人員基於某軟體或硬體訪問一組常式的能力
  • Web APIs 是 W3C 組織的標準,是 JS 獨有的部分
  • Web API 是瀏覽器提供的一套操作瀏覽器功能和頁面元素的 API,即 DOM 與 BOM

0x02 DOM

(1)簡介

  • 文檔對象模型(Document Object Model)是 W3C 組織推薦的處理可擴展標記語言的標準編程介面

    • 可以改變網頁內容、結構和樣式
  • DOM 樹:DOM 對象

    graph TB 文檔-->0[根元素<br/>< html >]-->1[元素<br/>< head >] & 2[元素<br/>< body >] 1-->11[元素<br/>< title >]-->111[文本<br/>文檔標題] 2-->21[元素<br/>< a >] & 22[元素<br/>< h1 >] 21-->211[屬性<br/>href] & 212[文本<br/>鏈接文本] 22-->221[文本<br/>一級標題]
    • 文檔:即頁面,DOM 中使用 document 表示
    • 元素:頁面中的任何標簽,DOM 中使用 element 表示
    • 節點:頁面中的任何內容,DOM 中使用 node 表示

(2)獲取元素

a. 根據 id 屬性

  • getElementById()

  • 返回帶有指定 id元素對象

<p id="content">This is a paragraph.</p>
<script>
  const pElement = document.getElementById("content");
  console.dir(pElement);
</script>

b. 根據標簽名

  • getElementByTagName()

  • 返回帶有指定標簽名的元素對象集合

<ul>
  <li>Item 1</li>
  <li>Item 2</li>
  <li>Item 3</li>
</ul>
<script>
  const liElements = document.getElementsByTagName("li");
  console.log(liElements);
</script>
  • 也可以用於獲取父元素內所有指定標簽名的子元素

    • 父元素必須為單個對象
    <ul>
      <li>Item 1</li>
      <li>Item 2</li>
      <li>Item 3</li>
    </ul>
    <script>
      const ulElement = document.getElementsByTagName("ul");
      const liElements = ulElement[0].getElementsByTagName("li");
      console.log(liElements);
    </script>
    

c. 通過 HTML5 新方法

  • 根據類名返回元素對象集合

    • getElementByClassName()
    <div class="item">Item 1</div>
    <div class="item">Item 2</div>
    <div class="item">Item 3</div>
    <script>
      const divElements = document.getElementsByClassName("item");
      console.log(divElements);
    </script>
    
  • 根據指定選擇器返回第一個元素對象

    • querySelector()
    <div class="item">Item 1</div>
    <div class="item">Item 2</div>
    <div class="item">Item 3</div>
    <script>
      const divElement = document.querySelector(".item");
      console.log(divElement);
    </script>
    
  • 根據指定選擇器返回元素對象集合

    • querySelectorAll()
    <div class="item">Item 1</div>
    <div class="item">Item 2</div>
    <div class="item">Item 3</div>
    <script>
      const divElements = document.querySelectorAll(".item");
      console.log(divElements);
    </script>
    

d. 特殊元素

  • html 元素

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8" />
        <title>Document</title>
      </head>
      <body>
        This is a simple page.
        <script>
          const htmlElement = document.documentElement;
          console.dir(htmlElement);
        </script>
      </body>
    </html>
    
  • body 元素

    <body>
      This is a simple page.
      <script>
        const bodyElement = document.body;
        console.dir(bodyElement);
      </script>
    </body>
    

(3)事件基礎

  • JavaScript 可用於創建動態頁面,事件是可以被 JavaScript 偵測到的行為

  • 頁面中每個元素都可以產生某些可以觸發 JavaScript 的事件

    <p>This is a paragraph.</p>
    <script>
      const pElement = document.querySelector("p");
      pElement.onclick = function (e) {
        console.log(e);
      };
    </script>
    
  • 事件三要素包括:

    1. 事件源:事件被觸發的對象
    2. 事件類型:觸發事件的方式
    3. 事件處理:通過函數處理事件
  • 執行事件的步驟:

    1. 獲取事件源
    2. 註冊(或綁定)事件
    3. 添加事件處理程式
      • 採用函數賦值形式
  • 常見滑鼠事件

    事件 條件
    onclick 左鍵點擊後觸發
    onmouseover 經過時觸發
    onmouseout 離開時觸發
    onfocus 獲得焦點觸發
    onblur 失去焦點觸發
    onmousemove 移動觸發
    onmouseup 彈起觸發
    onmousedown 按下觸發

(4)操作元素

  • 使用 DOM 操作可以改變網頁內容、結構和樣式

a. 內容

  • innerHTML:起始位置到終止位置的全部內容,包括 HTML 標簽、空格、換行等
  • innerText:類似 innerHTML不包括 HTML 標簽、空格、換行等
<p>
  This is a paragraph.<br />
  <span>Text in span</span>
</p>
<script>
  const pElement = document.querySelector("p");
  console.log(pElement.innerHTML);
  console.log(pElement.innerText);
</script>

b. 屬性

  • srchrefidvalue

  • 舉例 1:圖片切換至下一張

    <button id="next">下一張圖片</button>
    <img src="./1.png" alt="圖片1" />
    <script>
      const next = document.getElementById("next");
      const imgElement = document.querySelector("img");
      next.onclick = () => {
        imgElement.src = "./2.png";
        imgElement.alt = "圖片2";
        next.disabled = true;
      };
    </script>
    
  • 舉例 2:顯隱密碼

    <input type="password" name="password" autofocus />
    <label>顯示密碼</label>
    <script>
      const label = document.querySelector("label");
      const input = document.querySelector("input");
      let flag = 1;
      label.onclick = () => {
        if (flag) {
          label.innerText = "隱藏密碼";
          input.type = "text";
          flag = 0;
        } else {
          label.innerText = "顯示密碼";
          input.type = "password";
          flag = 1;
        }
      };
    </script>
    

c. 樣式

  • 行內樣式操作

    <div style="width: 300px; height: 300px; background-color: red"></div>
    <script>
      const div = document.querySelector("div");
      div.onclick = () => {
        div.style.backgroundColor = "blue";
      };
    </script>
    
    • JavaScript 中,樣式採取駝峰命名法,如 backgroundColor
    • JavaScript 修改樣式操作產生的是行內樣式,CSS 的權重更高
  • 類名樣式操作

    <div style="width: 300px; height: 300px; background-color: red"></div>
    <script>
      const div = document.querySelector("div");
      div.onclick = () => {
        div.className = "clicked";
      };
    </script>
    
    • className 會更改(覆蓋)元素的類名
  • 舉例 1:密碼框格式錯誤提示信息

    <div>
      <input type="password" />
      <p>輸入 3~10 個字元</p>
    </div>
    <script>
      const input = document.querySelector("input")
      const p = document.querySelector("p");
      input.onblur = function() {
        if (this.value.length < 3 || this.value.length > 10) {
          p.className = 'error'
          p.innerText = "字元數錯誤"
        } else {
          p.className = 'right'
          p.innerText = "字元數正確"
        }
      }
    </script>
    
  • 舉例 2:(排他思想)

    <button>按鈕 1</button>
    <button>按鈕 2</button>
    <button>按鈕 3</button>
    <script>
      const buttons = document.querySelectorAll("button");
      for (let i = 0; i < buttons.length; i++) {
        buttons[i].onclick = function () {
          for (let j = 0; j < buttons.length; j++) {
            buttons[j].style.backgroundColor = "";
          }
          this.style.backgroundColor = "red";
        };
      }
    </script>
    
  • 舉例 3:表格行在滑鼠懸浮時換色

    <table border="1">
      <thead>
        <tr>
          <th>Name</th>
          <th>Age</th>
          <th>Gender</th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <td>John</td>
          <td>20</td>
          <td>Male</td>
        </tr>
        <tr>
          <td>Jane</td>
          <td>21</td>
          <td>Female</td>
        </tr>
        <tr>
          <td>Jim</td>
          <td>22</td>
          <td>Male</td>
        </tr>
      </tbody>
    </table>
    <script>
      const trs = document.querySelector("tbody").querySelectorAll("tr");
      for (let i = 0; i < trs.length; i++) {
        trs[i].onmouseover = function () {
          this.style.backgroundColor = "red";
        };
        trs[i].onmouseout = function () {
          this.style.backgroundColor = "";
        };
      }
    </script>
    
  • 舉例 4:表單全選的選中與取消

    <table border="1">
      <thead>
        <tr>
          <th><input type="checkbox" id="selectAll" /></th>
          <th>Name</th>
          <th>Age</th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <td><input type="checkbox" /></td>
          <td>John</td>
          <td>20</td>
        </tr>
        <tr>
          <td><input type="checkbox" /></td>
          <td>Jane</td>
          <td>21</td>
        </tr>
        <tr>
          <td><input type="checkbox" /></td>
          <td>Jim</td>
          <td>22</td>
        </tr>
      </tbody>
    </table>
    <script>
      const selectAll = document.getElementById("selectAll");
      const checkboxes = document.querySelector("tbody").querySelectorAll("input");
      selectAll.onchange = function () {
        checkboxes.forEach(function (checkbox) {
          checkbox.checked = selectAll.checked;
        });
      };
      for (let i = 0; i < checkboxes.length; i++) {
        checkboxes[i].onchange = function () {
          if (!this.checked) {
            selectAll.checked = false;
          } else {
            let allChecked = true;
            checkboxes.forEach(function (checkbox) {
              if (!checkbox.checked) {
                allChecked = false;
              }
            });
            selectAll.checked = allChecked;
          }
        };
      }
    </script>
    

d. 自定義屬性

  • element.屬性 獲取的是內置屬性(即元素本身自帶的屬性)
  • element.getAttribute('屬性') 獲取的是自定義和內置的屬性
<div></div>
<script>
  const div = document.querySelector("div");
  div.setAttribute("data-tabindex", 1); 				 // 設置屬性
  const tabindex = div.getAttribute("data-tabindex");    // 獲取屬性
  console.log(tabindex);
  div.removeAttribute("data-tabindex"); 				 // 移除屬性
</script>
  • 自定義屬性的目的:保存並使用數據

    • 對於可以簡單且可以明文展示的數據可以保存在頁面中,省去使用資料庫
  • HTML5 規定,自定義屬性使用 data- 首碼命名並賦值

  • HTML5 新增以下方法獲取屬性值:

    <div data-class-name="div"></div>
    <script>
      const div = document.querySelector("div");
      console.log(div.dataset.className); 	 // 方法一
      console.log(div.dataset["className"]); // 方法二
    </script>
    

(5)節點操作

a. 簡介

  • 節點操作主要是利用節點層級關係獲取元素

    • 利用父子兄節點關係獲取元素
    • 邏輯性強
    • 相容性差
  • 節點是頁面中的任何內容,DOM 中使用 node 表示,均可使用 JavaScript 訪問

  • 一般地,節點至少擁有以下基本屬性:

    • 節點類型:nodeType

      節點類型 nodeType
      HTML 元素 1
      屬性 2
      文本 3
    • 節點名稱:nodeName

    • 節點值:nodeValue

b. 父節點

<div id="parent">
  <div id="child"></div>
</div>
<script>
  const parent = document.getElementById("child").parentNode;
  console.log(parent);
</script>

c. 子節點

  • 獲取子節點集合,包括元素節點、文本節點等

    <div id="parent">
      <div id="child1"></div>
      <div id="child2"></div>
      <div id="child3"></div>
    </div>
    <script>
      const children = document.getElementById("parent").childNodes;
      console.log(children);
    </script>
    
  • 只獲取子節點集合中的元素節點

    const children = document.getElementById("parent").childNodes;
    for (let i = 0; i < children.length; i++) {
      if (children[i].nodeType === 1) {
        console.log(children[i]);
      }
    }
    

    const children = document.getElementById("parent").children;
    console.log(children);
    
  • 第一個子節點

    const first = document.getElementById("parent").firstChild;
    console.log(first);
    

    第一個元素子節點

    • 推薦方法

      const first = document.getElementById("parent").children[0];
      console.log(first);
      
    • 存在相容性問題,需要 IE9+

      const first = document.getElementById("parent").firstElementChild;
      console.log(first);
      
  • 最後一個子節點

    const last = document.getElementById("parent").lastChild;
    console.log(last);
    

    最後一個元素子節點

    • 推薦方法

      const parent = document.getElementById("parent");
      const last = parent.children[parent.children.length - 1];
      console.log(last);
      
    • 存在相容性問題,需要 IE9+

      const last = document.getElementById("parent").lastElementChild;
      console.log(last);
      
  • 舉例:導航欄及其下拉菜單

    <ul id="nav">
      <li>
        Item 1
        <ul style="display: none">
          <li>Subitem 1</li>
          <li>Subitem 2</li>
        </ul>
      </li>
      <li>
        Item 2
        <ul style="display: none">
          <li>Subitem 1</li>
          <li>Subitem 2</li>
        </ul>
      </li>
    </ul>
    <script>
      const nav = document.body.children[0];
      const items = nav.children;
      for (let i = 0; i < items.length; i++) {
        items[i].onmouseover = function () {
          this.children[0].style.display = "block";
        };
        items[i].onmouseout = function () {
          this.children[0].style.display = "none";
        };
      }
    </script>
    

d. 兄弟節點

  • 獲取當前元素的下一個兄弟節點

    <h1>Title</h1>
    <p>This is a paragraph.</p>
    <script>
      const p = document.querySelector("h1").nextSibling;
      console.log(p);
    </script>
    
    • 元素節點

      const p = document.querySelector("h1").nextElementSibling;
      console.log(p);
      
  • 獲取當前元素的上一個兄弟節點

    <h1>Title</h1>
    <p>This is a paragraph.</p>
    <script>
      const h1 = document.querySelector("p").previousSibling;
      console.log(h1);
    </script>
    
    • 元素節點

      const h1 = document.querySelector("p").previousElementSibling;
      console.log(h1);
      
  • 上述獲取兄弟元素節點的方法,均存在相容性問題,需要 IE9+,為解決此問題,可以封裝以下方法:

    function getNextElementSibling(element) {
      let next = element.nextSibling;
      while (next && next.nodeType !== 1) {
        next = next.nextSibling;
      }
      return next;
    }
    
    function getPreviousElementSibling(element) {
      let prev = element.previousSibling;
      while (prev && prev.nodeType !== 1) {
        prev = prev.previousSibling;
      }
      return prev;
    }
    

e. 創建與添加節點

  • 動態創建元素節點:createElement()

    const p = document.createElement("p");
    
  • 添加節點至指定父節點的子節點的末尾:appendChild()

    p.innerText = "This is a paragraph"; // 設置標簽內容
    document.body.appendChild(p);		 // 添加節點
    
  • 在指定元素前面插入元素:insertBefore()

    const h1 = document.createElement("h1");
    h1.innerText = "Title";
    document.body.insertBefore(h1, p);
    
  • 舉例:發佈留言

    <textarea></textarea>
    <button>發佈</button>
    <ul></ul>
    <script>
      const btn = document.querySelector("button");
      btn.onclick = function () {
        const text = document.querySelector("textarea");
        if (text) {
          const ul = document.querySelector("ul");
          const li = document.createElement("li");
          li.innerHTML = text.value;
          // ul.appendChild(li);
          ul.insertBefore(li, ul.firstChild)
        } else {
          alert("發佈內容不能為空");
        }
      };
    </script>
    
  • 直接將內容寫入頁面的文檔流:write()

    <script>
      document.write("<button>點擊</button>");
      const btn = document.querySelector("button");
      btn.onclick = () => document.write("<p>This is a paragraph.</p>");
    </script>
    
  • write()innerHTML()createElement() 三種方法區別:

    • write() 在當文檔流執行完成後,會導致頁面重繪
    • innerHTML() 是將內容寫入某個 DOM 節點,適合創建多個元素,結構稍複雜
    • createElement() 結構清晰,效率較低

f. 刪除節點

  • 刪除一個節點:removeChild()

    <p>This is a paragraph.</p>
    <button>刪除節點</button>
    <script>
      document.querySelector("button").onclick = () =>
        document.body.removeChild(document.querySelector("p"));
    </script>
    
  • 舉例 1:刪除留言(在“發佈留言”案例的基礎上修改)

    const btn = document.querySelector("button");
    btn.onclick = function () {
      const text = document.querySelector("textarea");
      if (text) {
        const ul = document.querySelector("ul");
        const li = document.createElement("li");
        li.innerHTML = text.value + "<a href='javascript:;'>刪除</a>";
        ul.insertBefore(li, ul.firstChild);
        const as = document.querySelectorAll("a");
        for (let i = 0; i < as.length; i++) {
          as[i].onclick = function () {
            // this.parentNode.remove();
            ul.removeChild(this.parentNode);
          };
        }
      } else {
        alert("發佈內容不能為空");
      }
    };
    
  • 舉例 2:動態表格

    <table border="1">
      <thead>
        <tr>
          <th>姓名</th>
          <th>年齡</th>
          <th>操作</th>
        </tr>
      </thead>
      <tbody></tbody>
    </table>
    <script>
      let data = [
        { name: "張三", age: 24 },
        { name: "李四", age: 22 },
        { name: "王五", age: 26 },
        { name: "趙六", age: 21 },
      ];
      const tbody = document.querySelector("tbody");
      for (let i = 0; i < data.length; i++) {
        const tr = document.createElement("tr");
        for (const key in data[i]) {
          const td = document.createElement("td");
          td.innerText = data[i][key];
          tr.appendChild(td);
        }
        const td = document.createElement("td");
        td.innerHTML = "<a href='javascript:;'>刪除</a>";
        tr.appendChild(td);
        tbody.appendChild(tr);
      }
      const as = document.querySelectorAll("a");
      for (let i = 0; i < data.length; i++) {
        as[i].onclick = function () {
          tbody.removeChild(as[i].parentNode.parentNode);
        };
      }
    </script>
    

g. 複製節點

  • 克隆一個節點:cloneNode()

    <p>This is a paragraph.</p>
    <script>
      const p = document.querySelector("p").cloneNode(true);
      document.body.appendChild(p);
    </script>
    
  • 其中,cloneNode() 的參數預設為 false,即淺拷貝,不會拷貝子節點

0x03 事件高級

(1)註冊事件

a. 簡介

  • 註冊事件又稱綁定事件,給元素添加事件
  • 註冊事件方式包括:
    • 傳統方式
      • on 為首碼的事件,如 onclickonchange
      • 註冊事件的唯一性,即同一元素同一事件只能設置一個處理函數,最後註冊的處理函數會覆蓋前面註冊的
    • 方法監聽註冊方式
      • 採用 W3C 標準
      • 使用 addEventListener() 監聽
      • IE9 之前可以使用 attachEvent() 代替
      • 同一元素同一事件可以註冊多個監聽器,並按註冊順序執行

b. addEventListener

  • 將指定的監視器註冊到目標對象上,當該對象觸髮指定事件時,就會執行事件處理函數

  • 語法:addEventListener(type, listener[, useCapture])

    • type:事件類型字元串,如 clickchange

    • listener:事件處理函數,即監聽函數

    • useCapture:(可選)是否在捕獲階段觸發,是布爾值,預設 false

      “事件捕獲”在本章節第(3)節說明

    <button>點擊</button>
    <script>
      document.querySelector("button").addEventListener("click", () => {
        alert("觸發點擊事件");
      });
    </script>
    

c. attachEvent

  • 將指定的監視器註冊到目標對象上,當該對象觸髮指定事件時,就會執行指定的回調函數
  • 語法:attachEvent(eventNameWiteOn, callback)
    • eventNameWithOn:事件類型字元串,如 onclickonchange
    • callback:回調函數,用於事件處理

d. 相容性解決方案

相容性處理原則:首先照顧大多數瀏覽器,再處理特殊瀏覽器

function addEventListener(element, eventName, callback) {
  if (element.addEventListener) {
    element.addEventListener(eventName, eventName);
  } else if (element.attachEvent) {
    element.attachEvent(eventName, callback);
  } else {
    element["on" + eventName] = callback;
  }
}

(2)刪除事件

  • 刪除事件又稱解綁事件

  • 刪除事件方式包括:

    • 傳統方式

      <button>點擊</button>
      <script>
        document.querySelector("button").onclick = null;
      </script>
      
    • 方法監聽刪除方式

      • 使用 removeEventListener() 刪除

        <button>點擊</button>
        <script>
          const btn = document.querySelector("button");
          function clickEvent() {
            alert("觸發點擊事件");
            btn.removeEventListener("click", clickEvent);
          }
          btn.addEventListener("click", clickEvent);
        </script>
        
      • IE9 之前可以使用 detachEvent() 代替

  • 相容性解決方案

    function removeEventListener(element, eventName, callback) {
      if (element.removeEventListener) {
        element.removeEventListener(eventName, callback);
      } else if (element.attachEvent) {
        element.detachEvent("on" + eventName, callback);
      } else {
        element["on" + eventName] = null;
      }
    }
    

(3)DOM 事件流

  • 事件流描述的是從頁面中接收事件的順序

  • DOM 事件流:事件發生時會在元素節點之間按照特定順序的傳播過程

  • DOM 事件流分三個階段:

    1. 捕獲階段
      • 事件捕獲:由 DOM 最頂層節點開始,逐級向下傳播到最具體的元素接收的過程
    2. 當前目標階段
    3. 冒泡階段
      • 事件冒泡:事件開始時,由最具體的元素接收,之後逐級向上傳播到 DOM 最頂層節點的過程
  • 舉例:註冊事件採取捕獲階段觸發,先父元素節點,後子元素節點

    <div id="parent" style="width: 200px; height: 200px; background: red">
      <div id="child" style="width: 100px; height: 100px; background: green"></div>
    </div>
    <script>
      document.getElementById("parent").addEventListener(
        "click",
        () => {
          alert("parent");
        },
        true
      );
      document.getElementById("child").addEventListener(
        "click",
        () => {
          alert("child");
        },
        true
      );
    </script>
    
  • 部分事件沒有冒泡,如 onblur

(4)事件對象

  • 事件對象代表事件的狀態,是事件一系列相關數據的集合,包括滑鼠坐標等數據

  • 在以下代碼中,形參 event 就是事件對象

    <button>點擊</button>
    <script>
      document.querySelector("button").onclick = function (event) {
        console.log(event);
      };
    </script>
    
  • IE6~8 使用 window.event 寫法,相容性寫法為:

    e = event || window.event;
    
  • 常見屬性和方法

    屬性方法 說明
    target 返回觸發事件的對象
    srcElement 返回觸發事件的對象(在 IE6~8 中使用)
    type 返回事件類型,如 click 等
    stopPropagation() 阻止冒泡
    cancelBubble 阻止冒泡(在 IE6~8 中使用)
    preventDefault() 阻止預設事件
    returnValue 阻止預設事件(在 IE6~8 中使用)
  • 阻止事件冒泡的相容性寫法

    if (e & e.stopPropagation) {
      e.stopPropagation();
    } else {
      window.event.cancelBubble = true;
    }
    

(5)事件委托

  • 事件委托又稱事件代理,在 jQuery 中稱為事件委派

  • 原理:將每個子節點的事件監聽器統一設置在其父節點上,利用冒泡原理影響每個子節點

  • 作用:提高性能

  • 舉例:

    <ul>
      <li>Item 1</li>
      <li>Item 2</li>
      <li>Item 3</li>
      <li>Item 4</li>
      <li>Item 5</li>
      <li>Item 6</li>
    </ul>
    <script>
      document.querySelector("ul").addEventListener("mouseover", function (e) {
        e.target.style.backgroundColor = "red";
      });
    </script>
    

(6)常用滑鼠事件

  • 禁用右鍵菜單

    document.addEventListener("contextmenu", function (e) {
      e.preventDefault();
    });
    
  • 禁止滑鼠選中

    document.addEventListener("selectstart", function (e) {
      e.preventDefault();
    });
    
  • 舉例:跟隨滑鼠移動的方框

    <div
      style="
        width: 100px;
        height: 100px;
        background-color: red;
        position: absolute;
        transform: translate(-50%, -50%);
      "
    ></div>
    <script>
      const div = document.querySelector("div");
      document.addEventListener("mousemove", (e) => {
        div.style.left = e.pageX + "px";
        div.style.top = e.pageY + "px";
      });
    </script>
    
  • mouseentermouseover 的區別在於:mouseenter 不會冒泡

    • mouseenter 只在滑鼠經過盒子自身時觸發,而 mouseover 經過其子盒子也會觸發
    <div
      style="
        width: 200px;
        height: 200px;
        background-color: red;
        position: relative
      "
    >
      <div
        style="
          width: 100px;
          height: 100px;
          background-color: green;
          position: absolute;
          top: 50px;
          left: 50px;
        "
      ></div>
    </div>
    <script>
      const parent = document.querySelector("div");
      const child = document.querySelector("div div");
      parent.addEventListener("mouseenter", function () {
        console.log("mouseenter");
      });
      parent.addEventListener("mouseover", function () {
        console.log("mouseover");
      });
    </script>
    

(7)常用鍵盤事件

  • 常用鍵盤事件

    事件 說明
    keyup 按鍵鬆開時觸發
    keydown 按鍵按下時觸發
    keypress 按鍵按下時觸發(區別大小寫,不識別功能鍵,如 Ctrl 等)
    keyCode 返回按鍵的 ASCII 值(區分大小寫)
  • 按鍵執行順序:

    graph LR keydown-->keypress-->keyup
  • 舉例:按 / 鍵選中輸入框

    <input />
    <script>
      const input = document.querySelector("input");
      document.addEventListener("keyup", function (e) {
        if (e.keyCode === 191) {
          input.focus();
        }
      });
    </script>
    

0x04 BOM

(1)簡介

  • 瀏覽器對象模型(Browser Object Model)提供了獨立於內容而與瀏覽器視窗進行交互的對象

  • BOM 由一系列相關對象構成

  • BOM 缺乏標準,最初是 Netscape 瀏覽器標準的一部分

  • 與 DOM 對比:

    DOM BOM
    名稱 文檔對象模型 瀏覽器對象模型
    對象 文檔 瀏覽器
    頂級對象 document window
    功能 操作頁面元素 瀏覽器視窗交互
    標準 W3C 根據瀏覽器廠商
  • BOM 構成:

    graph TB window-->document & location & navigation & screen & history
    • document:BOM 中包含 DOM
    • window:是瀏覽器的頂級對象,既是 JS 訪問瀏覽器視窗的介面,也是全局對象
      • 調用 window 對象方法時可以省略,如 alert(),除了 window.name

(2)window 對象常見事件

  • 視窗載入完成事件

    window.onload = function () {};
    // 或
    window.addEventListener("load", function () {});
    
    • DOM 載入完成事件(需要 IE9+)

      window.addEventListener("DOMContentLoaded", function () {});
      
  • 視窗大小調整事件

    window.onresize = function () {};
    // 或
    window.addEventListener("resize", function () {});
    

(3)定時器

a. timeout

  • 設置計時器

    • 語法:setTimeout(callback[, timeMS])

    • 作用:經過指定毫秒後執行回調函數

  • 清除定時器

    • 語法:clearTimeout(timer)
    • 作用:清除 setTimeout() 設置的定時器
  • 舉例:

    let timer = setTimeout(function() {}, 1000);
    clearTimeout(timer);
    

b. interval

  • 設置計時器

    • 語法:setInterval(callback[, timeMS])

    • 作用:間隔指定毫秒後重覆執行回調函數

    • 舉例:倒計時器

      <div>
        <span class="hour">00</span>
        <span class="minute">00</span>
        <span class="second">00</span>
      </div>
      <script>
        const hour = document.querySelector(".hour");
        const minute = document.querySelector(".minute");
        const second = document.querySelector(".second");
        function countDown() {
          const now = new Date();
          console.log(now);
          const target = new Date(2024, 1, 1, 0, 0, 0);
          const diff = target - now;
          hour.innerHTML = Math.floor(diff / 1000 / 60 / 60);
          minute.innerHTML = Math.floor((diff / 1000 / 60) % 60);
          second.innerHTML = Math.floor((diff / 1000) % 60);
        }
        setInterval(countDown, 500);
      </script>
      
  • 清除定時器

    • 語法:clearInterval(timer)
    • 作用:清除 setInterval() 設置的定時器
  • 舉例:發送簡訊間隔

    手機號: <input type="number" /><button>獲取驗證碼</button>
    <script>
      document.querySelector("button").addEventListener("click", callback);
      function callback() {
        let phone = document.querySelector("input").value;
        if (!/^1[3-9]\d{9}$/.test(phone)) {
          alert("手機號格式不正確");
          return;
        }
        this.disabled = true;
        let time = 10;
        let timer = setInterval(() => {
          this.innerHTML = `重新發送(${time})`;
          time--;
          if (time === 0) {
            clearInterval(timer);
            this.innerHTML = "獲取驗證碼";
            this.disabled = false;
            time = 10;
          }
        }, 1000);
      }
    </script>
    

(4)執行隊列

a. 執行過程

  • JavaScript 的特點是單線程,即同一時間只做一件事

    • 缺點:當 JS 執行時間過長,會導致頁面渲染不連貫,產生阻塞的感受
  • HTML5 提出 Web Worker 標準,允許 JavaScript 腳本創建多個線程,即同步非同步

    • 同步:順序依次執行
    • 非同步:多任務同時執行
  • 同步任務都在主線程上執行,形成執行棧

  • 非同步任務通過回調函數實現,分為以下類型:

    1. 普通事件:如 click
    2. 資源載入:如 load
    3. 定時器

    非同步任務相關回調函數會被添加到任務隊列(又稱消息隊列)中

b. 執行機制

  • JavaScript 執行機制如下:
    1. 先執行執行棧中的同步任務
    2. 將非同步任務放入任務隊列
    3. 完成執行棧後,按次序讀取任務隊列,將非同步任務放入執行棧並執行
  • 由於主線程不斷地重覆獲取任務、執行任務,因此該機制稱為事件迴圈

(5)location 對象

  • 用於獲取或設置窗體的 URL,並且可以用於解析 URL

  • 屬性:

    屬性 說明
    href 獲取或設置 URL
    host 返回主機(功能變數名稱)
    port 返回埠號
    pathname 返迴路徑
    search 返回參數
    hash 返回片段
    • 舉例:獲取 URL 中攜帶的參數

      <div></div>
      <script>
        const params = location.search.substr(1);
        const array = params.split("=");
        document.querySelector("div").innerHTML = array[1];
      </script>
      
  • 常用方法:

    方法 說明
    assign() 重定向頁面,與屬性 href 類似,可以跳轉頁面
    replace() 替換當前頁面,替換後不能後退
    reload() 重新載入頁面,相當於刷新或 F5
    參數為 true 表示強制刷新或 Ctrl+F5

(6)navigator 對象

  • 包含有關瀏覽器的信息

  • 舉例:根據終端(瀏覽器)的不同跳轉相應的頁面

    if((navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|iPad|ios|Android|BlackBerry|IEMobile|Opera Mini|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i))) {
      window.location.href = "https://m.example.com/";   // Mobile
    } else {
      window.location.href = "https://www.example.com/"; // PC
    }
    

(7)history 對象

  • 用於與瀏覽器歷史記錄進行交互,包含用戶(在瀏覽器視窗中)訪問過的 URL

  • 方法:

    方法 說明
    back() 後退
    forward() 前進
    go(arg) 參數為正數:前進 arg 個頁面
    參數為負數:後退 arg 個頁面
  • 常見於 OA 辦公系統

0x05 PC 端網頁特效

(1)元素偏移量 offset

a. 簡介

  • 動態獲取元素的位置(偏移)、大小等

    • 獲取元素距離帶有定位父元素的位置
    • 獲取元素自身的大小(寬高)
    • 獲取的數值不攜帶單位
  • 常用屬性:

    屬性 說明
    offsetParent 返回作為該元素帶有定位的父級元素
    offsetTop 返回元素相對帶有定位父元素上方的偏移
    offsetLeft 返回元素相對帶有定位父元素左邊框的偏移
    offsetWidth 返回自身包括內邊距、邊框、內容的寬度
    offsetHeight 返回自身包括內邊距、邊框、內容的高度
  • 相比之下,offset 更適合獲取元素的大小與位置,而 style 更適合修改元素

b. 獲取滑鼠在盒子中的坐標

<div style="width: 200px; height: 200px; background-color: red"></div>
<script>
  document.querySelector("div").addEventListener("mousemove", function (e) {
    let x = e.pageX - this.offsetLeft;
    let y = e.pageY - this.offsetTop;
    this.innerText = `x: ${x}, y: ${y}`;
  });
</script>

c. 拖動模態框

  • HTML

    <button id="open">點擊登錄</button>
    <div id="mask"></div>
    <div id="card">
      <h3 id="header">登錄框標題</h3>
      <button id="close">關閉</button>
    </div>
    
  • CSS

    #mask {
      width: 100%;
      height: 100%;
      position: fixed;
      top: 0;
      left: 0;
      background-color: rgba(0, 0, 0, 0.3);
      display: none;
    }
    #card {
      width: 400px;
      height: 300px;
      position: fixed;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
      z-index: 10;
      background-color: white;
      border-radius: 30px;
      box-shadow: 0 0 10px rgb(0, 0, 0);
      text-align: center;
      line-height: 40px;
      display: none;
    }
    #header {
      width: 100%;
      margin-top: 0;
      border-bottom: 2px solid rgba(0, 0, 0, 0.3);
      cursor: move;
    }
    
  • JavaScript

    const mask = document.querySelector("#mask");
    const card = document.querySelector("#card");
    const header = document.querySelector("#header");
    document.querySelector("#open").addEventListener("click", () => {
      mask.style.display = "block";
      card.style.display = "block";
    });
    document.querySelector("#close").addEventListener("click", () => {
      mask.style.display = "none";
      card.style.display = "none";
    });
    header.addEventListener("mousedown", function (e) {
      e.preventDefault();
      let x = e.clientX - card.offsetLeft;
      let y = e.clientY - card.offsetTop;
      function move(e) {
        card.style.left = e.pageX - x + "px";
        card.style.top = e.pageY - y + "px";
      }
      document.addEventListener("mousemove", move);
      document.addEventListener("mouseup", function (e) {
        document.removeEventListener("mousemove", move);
      });
    });
    

d. 圖片放大鏡

  • HTML

    <div id="image">
      <div id="mask"></div>
      <div id="preview">
        <img src="./image.jpg" alt="" id="previewImg" />
      </div>
    </div>
    
  • CSS

    #image {
      position: relative;
      width: 200px;
      height: 200px;
      background-image: url("./image.jpg");
      background-size: cover;
      border: 1px solid black;
    }
    #mask {
      position: absolute;
      top: 0;
      left: 0;
      width: 100px;
      height: 100px;
      background-color: red;
      opacity: 0.5;
      cursor: move;
      display: none;
    }
    #preview {
      position: absolute;
      top: 0;
      left: 210px;
      width: 300px;
      height: 300px;
      overflow: hidden;
      z-index: 10;
      border: 1px solid black;
      display: none;
    }
    #previewImg {
      position: absolute;
      top: 0;
      left: 0;
    }
    
  • JavaScript

    const image = document.querySelector("#image");
    const mask = document.querySelector("#mask");
    image.addEventListener("mouseover", () => {
      mask.style.display = "block";
      preview.style.display = "block";
    });
    image.addEventListener("mouseout", () => {
      mask.style.display = "none";
      preview.style.display = "none";
    });
    image.addEventListener("mousemove", function (e) {
      let x = e.pageX - this.offsetLeft;
      let y = e.pageY - this.offsetTop;
      let maskX = x - mask.offsetWidth / 2;
      let maskY = y - mask.offsetHeight / 2;
      let maskMaxX = this.offsetWidth - mask.offsetWidth;
      let maskMaxY = this.offsetHeight - mask.offsetHeight;
      if (maskX < 0) {
        maskX = 0;
      } else if (maskX > maskMaxX) {
        maskX = this.offsetWidth - mask.offsetWidth;
      }
      if (maskY < 0) {
        maskY = 0;
      } else if (maskY > maskMaxY) {
        maskY = this.offsetHeight - mask.offsetHeight;
      }
      mask.style.left = maskX + "px";
      mask.style.top = maskY + "px";
    
      const preview = document.querySelector("#preview");
      const previewImg = document.querySelector("#previewImg");
      let previewMaxX = previewImg.offsetWidth - preview.offsetWidth;
      let previewMaxY = previewImg.offsetHeight - preview.offsetHeight;
      previewImg.style.left = -((maskX * previewMaxX) / maskMaxX) + "px";
      previewImg.style.top = -((maskY * previewMaxY) / maskMaxY) + "px";
    });
    

(2)元素可視區 client

  • 獲取元素可視區相關信息,如邊框大小、元素大小等

  • 常見屬性:

    屬性 說明
    clientTop 返回元素上邊框的大小
    clientLeft 返回元素左邊框的大小
    clientWidth 返回自身包括內邊距、內容的寬度
    clientHeight 返回自身包括內邊距、內容的高度

立即執行函數:(function() {})()

主要作用:創建一個獨立的作用域

(3)元素滾動 scroll

  • 獲取元素的大小、滾動距離等

  • 如果瀏覽器的高度(寬度)不足以顯示全部內容,則會自動出現滾動條

    • 當滾動條向下(向右)滾動後,未顯示在當前視窗的頁面稱為被捲去的頁面
    • 滾動條在滾動時會觸發 onscroll 事件
  • 常見屬性:

    屬性 說明
    scrollTop 返回被捲去的上側距離
    scrollLeft 返回被捲去的左側距離
    scrollWidth 返回自身內容的寬度
    scrollHeight 返回自身內容的高度
  • 被捲去的頭部相容性寫法

    function getScroll() {
      return {
        left:
          window.pageXOffset ||
          document.documentElement.scrollLeft ||
          document.body.scrollLeft ||
          0,
        top:
          window.pageYOffset ||
          document.documentElement.scrollTop ||
          document.body.scrollTop ||
          0,
      };
    }
    
  • 舉例:側邊欄

    • HTML

      <header></header>
      <div id="content"></div>
      <div id="bar">
        <button>回到頂部</button>
      </div>
      
    • CSS

      header {
        width: 90%;
        height: 200px;
        background-color: #ccc;
        margin: 10px auto;
      }
      #content {
        width: 90%;
        height: 1000px;
        background-color: #eee;
        margin: 10px auto;
      }
      #bar {
        position: absolute;
        top: 300px;
        right: 0;
        width: 30px;
        height: 150px;
        background-color: #ddd;
      }
      button {
        display: none;
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
      }
      
    • JavaScript

      const bar = document.querySelector("#bar");
      const btn = document.querySelector("button");
      let ctnTop = document.querySelector("#content").offsetTop;
      let barTop = bar.offsetTop - ctnTop;
      document.addEventListener("scroll", () => {
        if (window.scrollY > ctnTop) {
          bar.style.position = "fixed";
          bar.style.top = barTop + "px";
          btn.style.display = "block";
        } else {
          bar.style.position = "absolute";
          bar.style.top = "300px";
          btn.style.display = "none";
        }
      });
      btn.addEventListener("click", () => {
        window.scrollTo({
          top: 0,
          behavior: "smooth",
        });
      });
      

(4)動畫函數封裝

  • 原理:通過定時器 setInterval() 不斷移動盒子的位置

    • 盒子需要定位才能使用動畫
    <button>開始</button>
    <div
      style="
        width: 200px;
        height: 200px;
        background-color: red;
        position: absolute;
        left: 0;
      "
    ></div>
    <script>
      document.querySelector("button").addEventListener("click", () => {
        const div = document.querySelector("div");
        let timer = setInterval(() => {
          if (div.offsetLeft >= 400) {
            clearInterval(timer);
          }
          div.style.left = div.offsetLeft + 1 + "px";
        }, 25);
      });
    </script>
    
  • 動畫函數的簡單封裝需要傳遞兩個參數:動畫對象、移動距離

    function animate(obj, target) {
      clearInterval(obj.timer);
      obj.timer = setInterval(() => {
        if (obj.offsetLeft >= target) {
          clearInterval(obj.timer);
        }
        obj.style.left = obj.offsetLeft + 1 + "px";
      }, 25);
    }
    document.querySelector("button").addEventListener("click", () => {
      animate(document.querySelector("div"), 500);
    });
    
  • 緩動動畫是讓元素的運動速度發生變化(即,將移動距離遞減)

    • 步長需要取整
    • 正步長向上取整,負步長向下取整
    function animate(obj, target) {
      clearInterval(obj.timer);
      obj.timer = setInterval(() => {
        if (obj.offsetLeft === target) {
          clearInterval(obj.timer);
        }
        let step = (target - obj.offsetLeft) / 50;
        step = step > 0 ? Math.ceil(step) : Math.floor(step);
        obj.style.left = obj.offsetLeft + step + "px";
      }, 25);
    }
    
  • 在動畫函數中引入回調函數

    function animate(obj, target, callback) {
      clearInterval(obj.timer);
      obj.timer = setInterval(() => {
        if (obj.offsetLeft === target) {
          clearInterval(obj.timer);
          if (callback) callback();
        }
        let step = (target - obj.offsetLeft) / 50;
        step = step > 0 ? Math.ceil(step) : Math.floor(step);
        obj.style.left = obj.offsetLeft + step + "px";
      }, 25);
    }
    document.querySelector("button").addEventListener("click", () => {
      animate(document.querySelector("div"), 500, () => {
        alert("移動結束");
      });
    });
    
  • 將動畫函數封裝到單獨的 JavaScript 文件中

    1. 創建 animate.js

      /**
       * 實現元素的平滑移動動畫。
       * @param {Object} obj - 需要進行動畫的DOM對象。
       * @param {number} target - 目標位置,即元素移動到的左偏移量。
       * @param {Function} callback - 動畫完成後的回調函數。
       */
      function animate(obj, target, callback) {
        // 停止當前正在進行的動畫
        clearInterval(obj.timer);
      
        // 設置定時器,每25毫秒執行一次動畫邏輯
        obj.timer = setInterval(() => {
          // 當元素移動到目標位置時,停止動畫
          if (obj.offsetLeft === target) {
            clearInterval(obj.timer);
            // 如果設置了回調函數,則動畫完成後執行回調
            if (callback) callback();
          }
      
          // 計算每次移動的距離,平滑移動
          let step = (target - obj.offsetLeft) / 50;
          // 確保移動方向正確,且移動步長為整數
          step = step > 0 ? Math.ceil(step) : Math.floor(step);
      
          // 更新元素的左偏移量
          obj.style.left = obj.offsetLeft + step + "px";
        }, 25);
      }
      
    2. 在頁面中使用

      <script src="./animate.js"></script>
      <script>
        document.querySelector("button").addEventListener("click", () => {
          animate(document.querySelector("div"), 500, () => {
            alert("移動結束");
          });
        });
      </script>
      

0x06 本地存儲

  • 本地存儲特性:
    • 數據存儲在用戶瀏覽器中
    • 存儲與讀寫方便
    • 容量大(sessionStorage - 5M,localStorage - 20M)
    • 只能存儲字元串,可以將對象使用 JSON.stringify() 編碼後存儲

(1)sessionStorage

  • 當瀏覽器視窗關閉後,sessionStorage 生命周期終止

  • 在同一視窗(頁面)下,數據可以共用

  • 鍵值對的形式存儲和使用

  • 舉例:

    <input type="text" />
    <button id="save">存儲</button>
    <button id="read">讀取</button>
    <button id="delete">刪除</button>
    <button id="clear">清空</button>
    <script>
      let input = document.querySelector("input");
      document.querySelector("#save").addEventListener("click", () => {
        sessionStorage.setItem("value", input.value);
        alert("存儲成功");
      });
      document.querySelector("#read").addEventListener("click", () => {
        let value = sessionStorage.getItem("value");
        alert(`讀取內容: ${value}`);
      });
      document.querySelector("#delete").addEventListener("click", () => {
        sessionStorage.removeItem("value");
        alert("刪除成功");
      });
      document.querySelector("#clear").addEventListener("click", () => {
        sessionStorage.clear();
        alert("清空成功");
      });
    </script>
    

(2)localStorage

  • 生命周期永久有效,只能手動刪除

  • 在同一瀏覽器下,數據可以共用

  • 鍵值對的形式存儲和使用

  • 舉例:

    <input type="text" />
    <button id="save">存儲</button>
    <button id="read">讀取</button>
    <button id="delete">刪除</button>
    <button id="clear">清空</button>
    <script>
      let input = document.querySelector("input");
      document.querySelector("#save").addEventListener("click", () => {
        localStorage.setItem("value", input.value);
        alert("存儲成功");
      });
      document.querySelector("#read").addEventListener("click", () => {
        value = localStorage.getItem("value");
        alert(`讀取內容: ${value}`);
      });
      document.querySelector("#delete").addEventListener("click", () => {
        localStorage.removeItem("value");
        alert("刪除成功");
      });
      document.querySelector("#clear").addEventListener("click", () => {
        localStorage.clear();
        alert("清空成功");
      });
    </script>
    

(3)記住用戶名

<input type="text" id="username" />
<input type="checkbox" id="rememberMe" />
<label for="rememberMe">記住我</label>
<script>
  const username = document.querySelector("#username");
  const rememberMe = document.querySelector("#rememberMe");
  if (localStorage.getItem("username")) {
    username.value = localStorage.getItem("username");
    rememberMe.checked = true;
  }
  rememberMe.addEventListener("change", function () {
    if (this.checked) {
      localStorage.setItem("username", username.value);
    } else {
      localStorage.removeItem("username");
    }
  });
</script>

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一、Tabs Tabs組件是一種常見的用戶界面(UI)組件,它是一個可以容納多個選項卡的容器組件。每個選項卡通常包含一個面板和一個標簽,用戶可以通過點擊標簽來切換面板。Tabs組件通常用於展示多個相關但又不需要同時展示的數據集合或功能集合,以提高頁面的可維護性和可用性。 Tabs組件的主要功能包 ...
  • 變數是一種使用方便的占位符,用於引用電腦記憶體地址。 我們可以把變數看做存儲數據的容器。 TypeScript 變數的命名規則: 變數名稱可以包含數字和字母。 除了下劃線 _ 和美元 $ 符號外,不能包含其他特殊字元,包括空格。 變數名不能以數字開頭。 變數使用前必須先聲明,我們可以使用 var 來 ...
  • 一、Navigation Navigation組件通常作為頁面的根容器,支持單頁面、分欄和自適應三種顯示模式。開發者可以使用Navigation組件提供的屬性來設置頁面的標題欄、工具欄、導航欄等。 在Navigation組件中,頁面分為主頁和內容頁。主頁由標題欄、內容區和工具欄組成,並且可以使用 ...
  • TypeScript 包含的數據類型如下表: 註意: TypeScript 和 JavaScript 沒有整數類型。 Any 類型 任意值是 TypeScript 針對編程時類型不明確的變數使用的一種數據類型,它常用於以下三種情況。 1、變數的值會動態改變時,比如來自用戶的輸入,任意值類型可以讓這些 ...
  • iOS系統崩潰的捕獲 相信大家在開發iOS程式的時候肯定寫過各種Bug,而其中最為嚴重的Bug就是會導致崩潰的Bug(一般來說妥妥的P1級)。在應用軟體大大小小的各種異常中,崩潰確實是最讓人難以接受的行為。畢竟崩潰意味著用戶將丟失應用程式運行中的所有上下文環境,丟失其所有未保存的數據,會帶給用戶最糟 ...
  • 隨著互聯網技術的迅速發展,用戶對網頁的載入速度和交互體驗有了更高的期待。作為開發者,我們常常需要在伺服器端渲染(SSR)與客戶端渲染(CSR)之間做出選擇。這兩種渲染方式各有特點,適用於不同的場景和需求。今天,就讓我們一起來探索SSR和CSR的世界,幫助你為你的應用選擇最合適的渲染策略。 什麼是渲染 ...
  • 錨點鏈接 <a href="#Cat"></a> 點擊這個鏈接將為跳轉到這個頁面上id為Cat的頁面 利用這個功能,我們可以實現給一個頁面插眼的功能。 比如我們想建一個動物園的網站 <!-- 動物園導航欄--> <header> <ul> <li><a href="cat">Cats</a></li ...
  • 關於微信小程式轉發&保存圖片 已經好多年沒寫博客了,最近使用在用uniapp開發一個移動版管理後臺,記錄下自己踩過的一些坑 微信小程式圖片轉發保存簡單說明 微信小程式圖片轉發保存,依賴小程式的轉發api—— wx.showShareImageMenu(Object object) 通過調用這個api ...
一周排行
    -Advertisement-
    Play Games
  • GoF之工廠模式 @目錄GoF之工廠模式每博一文案1. 簡單說明“23種設計模式”1.2 介紹工廠模式的三種形態1.3 簡單工廠模式(靜態工廠模式)1.3.1 簡單工廠模式的優缺點:1.4 工廠方法模式1.4.1 工廠方法模式的優缺點:1.5 抽象工廠模式1.6 抽象工廠模式的優缺點:2. 總結:3 ...
  • 新改進提供的Taurus Rpc 功能,可以簡化微服務間的調用,同時可以不用再手動輸出模塊名稱,或調用路徑,包括負載均衡,這一切,由框架實現並提供了。新的Taurus Rpc 功能,將使得服務間的調用,更加輕鬆、簡約、高效。 ...
  • 本章將和大家分享ES的數據同步方案和ES集群相關知識。廢話不多說,下麵我們直接進入主題。 一、ES數據同步 1、數據同步問題 Elasticsearch中的酒店數據來自於mysql資料庫,因此mysql數據發生改變時,Elasticsearch也必須跟著改變,這個就是Elasticsearch與my ...
  • 引言 在我們之前的文章中介紹過使用Bogus生成模擬測試數據,今天來講解一下功能更加強大自動生成測試數據的工具的庫"AutoFixture"。 什麼是AutoFixture? AutoFixture 是一個針對 .NET 的開源庫,旨在最大程度地減少單元測試中的“安排(Arrange)”階段,以提高 ...
  • 經過前面幾個部分學習,相信學過的同學已經能夠掌握 .NET Emit 這種中間語言,並能使得它來編寫一些應用,以提高程式的性能。隨著 IL 指令篇的結束,本系列也已經接近尾聲,在這接近結束的最後,會提供幾個可供直接使用的示例,以供大伙分析或使用在項目中。 ...
  • 當從不同來源導入Excel數據時,可能存在重覆的記錄。為了確保數據的準確性,通常需要刪除這些重覆的行。手動查找並刪除可能會非常耗費時間,而通過編程腳本則可以實現在短時間內處理大量數據。本文將提供一個使用C# 快速查找並刪除Excel重覆項的免費解決方案。 以下是實現步驟: 1. 首先安裝免費.NET ...
  • C++ 異常處理 C++ 異常處理機制允許程式在運行時處理錯誤或意外情況。它提供了捕獲和處理錯誤的一種結構化方式,使程式更加健壯和可靠。 異常處理的基本概念: 異常: 程式在運行時發生的錯誤或意外情況。 拋出異常: 使用 throw 關鍵字將異常傳遞給調用堆棧。 捕獲異常: 使用 try-catch ...
  • 優秀且經驗豐富的Java開發人員的特征之一是對API的廣泛瞭解,包括JDK和第三方庫。 我花了很多時間來學習API,尤其是在閱讀了Effective Java 3rd Edition之後 ,Joshua Bloch建議在Java 3rd Edition中使用現有的API進行開發,而不是為常見的東西編 ...
  • 框架 · 使用laravel框架,原因:tp的框架路由和orm沒有laravel好用 · 使用強制路由,方便介面多時,分多版本,分文件夾等操作 介面 · 介面開發註意欄位類型,欄位是int,查詢成功失敗都要返回int(對接java等強類型語言方便) · 查詢介面用GET、其他用POST 代碼 · 所 ...
  • 正文 下午找企業的人去鎮上做貸後。 車上聽同事跟那個司機對罵,火星子都快出來了。司機跟那同事更熟一些,連我在內一共就三個人,同事那一手指桑罵槐給我都聽愣了。司機也是老社會人了,馬上聽出來了,為那個無辜的企業經辦人辯護,實際上是為自己辯護。 “這個事情你不能怪企業。”“但他們總不能讓銀行的人全權負責, ...