亚洲乱色熟女一区二区三区丝袜,天堂√中文最新版在线,亚洲精品乱码久久久久久蜜桃图片,香蕉久久久久久av成人,欧美丰满熟妇bbb久久久

LOGO OA教程 ERP教程 模切知識交流 PMS教程 CRM教程 開發(fā)文檔 其他文檔  
 
網(wǎng)站管理員

前端的能力邊界

freeflydom
2025年9月10日 10:1 本文熱度 73

本系列來自曾供職于Google的知名前端技術(shù)專家馬特·弗里斯比編寫的 《JavaScript高級程序設(shè)計》(第5版)

了解一門語言能做什么很重要,既是學(xué)習(xí)的起點,也是應(yīng)用的落點。

JavaScript曾被認(rèn)為是“玩具”語言,誰都想不到,它后來把觸角伸到了服務(wù)端、工具鏈、App、桌面端、甚至是硬件和深度學(xué)習(xí)。

本文是此系列的最終篇,我們來探究一下,除了按照正確的語法和良好的組織去寫代碼,前端到底能做什么?

網(wǎng)絡(luò)請求

動態(tài)數(shù)據(jù)是給網(wǎng)頁注入活力的重要因素,可以使得每天的內(nèi)容,每個人看到的內(nèi)容,都不同。

靠手寫是不行的,需要發(fā)起網(wǎng)絡(luò)請求。

在過去,請求任務(wù)由XMLHttpRequest來完成的,但在現(xiàn)代Web開發(fā)中,已經(jīng)被Fetch替代。

Fetch

前面提過,F(xiàn)etch是基于Promise的,它能以更簡潔清晰的方式實現(xiàn)異步,并且它支持流式響應(yīng)、請求取消和自動請求重發(fā)。

fetch()方法只有一個必須的參數(shù),即請求的url,其他參數(shù)按需配置,一個基本的POST請求寫法如下:

const payload = JSON.stringify({
  foo:"bar"
});
fetch("url", {
  method"POST",
  body: payload,
  headers: {
    "Content-Type""application/json",
  },
})
  .then((res) => {
    if (res.status == 200) {
      console.log(res.text());
    }
  })

這段代碼較為完整地展現(xiàn)了POST請求的大概結(jié)構(gòu),請求返回后,可以通過返回的狀態(tài)碼,及各種不同數(shù)據(jù)的處理方法,來接收結(jié)果。

數(shù)據(jù)的處理方法有多種,除了text(),還有json()、blob()等,可根據(jù)返回數(shù)據(jù)的類型和需求進行選用。

Web Socket

Fetch請求是由客戶端發(fā)起,服務(wù)端做響應(yīng)的單向通信,但有時候我們需要實現(xiàn)雙向通信,服務(wù)端主動向客戶端推送數(shù)據(jù),主流方案就是 Web Socket。

簡單使用:

const socket = new WebSocket("ws://localhost:8080");
  socket.onopen = () => {
    console.log("連接成功");
  };
  socket.onmessage = (e) => {
    console.log("收到消息", e.data);
  };

EventSource API

這是一種比較新的API,但這兩年應(yīng)用很廣,大家看到的關(guān)于AI的信息交互,返回結(jié)果像打字機一樣輸出,起關(guān)鍵作用的就是它。

示例如下:

const eventSource = new EventSource("http://localhost:8080/stream");
eventSource.onmessage = (e) => {
  console.log("收到消息", e.data);
};

應(yīng)用比較簡單,但有一點需要說明,看起來它只支持get請求,無法傳參?如果需要傳參,怎么辦,有一個包可以幫助我們實現(xiàn)——@microsoft/fetch-event-source。

File上傳

豐富的網(wǎng)頁功能,不僅讓用戶能輸入內(nèi)容,還要能上傳文件。

在早期,處理文件的唯一方式是把<input type="file">放到一個表單里。

File API 與 Blob API 就是為了讓W(xué)eb開發(fā)者更好地與文件交互而設(shè)計。它仍然以表單中的文件為基礎(chǔ),但增加了訪問文件信息的能力。

File類型

HTML5在DOM上為文件輸入元素添加了files集合,它包含一組File對象,表示被選中的文件。

每個File對象都有一些只讀屬性:name(文件名);size(文件大?。?;type(文件MIME類型);lastModifiedDate(文件最后修改時間)

FileReader類型

File API還提供了FileReader類型,用于從文件中讀取數(shù)據(jù)。

每個FileReader會發(fā)布幾個事件,最有用的是progress、error和load。

const reader = new FileReader();
    reader.readAsText(file);
    // 還有數(shù)據(jù)
    reader.onprogress = (e) => {
      if (e.lengthComputable) {
        const percentLoaded = Math.round((e.loaded / e.total) * 100);
        console.log(`File loading progress: ${percentLoaded}%`);
      }
    };
    // 讀取完成
    reader.onload = () => {
      console.log('File content:', reader.result);
    };
    // 發(fā)生錯誤
    reader.onerror = () => {
      console.error('Error reading file:', reader.error);
    };

某些情況下,可能需要讀取部分文件而不是整個文件。為此,F(xiàn)ile對象提供了一個名為slice()的方法。

Blob URL

有時候你會看到一個blob開頭的字符串來展示文件,它就是對象URL,也稱作Blob URL,是指引用存儲在File或Blob中數(shù)據(jù)的URL。

對象URL的優(yōu)點是不用把文件內(nèi)容讀取到JavaScript也可以使用文件。

要創(chuàng)建對象URL,可以使用window.URL.createObjectURL()方法并傳入File或Blob對象,這個函數(shù)返回的值是一個指向內(nèi)存中地址的字符串,因為這個字符串是URL,所以可以在DOM中直接使用。

拖拽上傳

除了點擊選擇上傳,將拖放API與File API結(jié)合使用,可實現(xiàn)拖拽上傳,在頁面上創(chuàng)建放置目標(biāo)后,把文件拖動到放置目標(biāo)。會觸發(fā)drop事件,被放置的文件可通過事件的event.dataTransfer.files屬性讀到。

圖形渲染

圖形圖像是網(wǎng)頁不可缺少的部分,我們見到所有亮眼、炫酷的效果,都由它來完成,會給網(wǎng)頁吸引力加分。

最常見的img元素,但它只能用來展示圖片,想要實現(xiàn)更多,如圖形繪制、圖片處理,或者復(fù)雜動畫,就要用到Canvas。

const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
// 設(shè)定寬高
canvas.width = 200;
canvas.height = 100;
// 設(shè)定填充色
ctx.fillStyle = 'red';
// 繪制矩形
ctx.fillRect(101018080);
document.body.appendChild(canvas);

上面這段代碼,繪制了一個“紅色矩形”,屬于圖形界的“Hello World”。

Canvas能做的事情,包括且不限于:畫線、各種形狀、文本、陰影、漸變、繪制圖像、填充圖案。

還有一項重要能力是獲取和操作圖像數(shù)據(jù)。

// 獲取圖像數(shù)據(jù)
const imageData = ctx.getImageData(00, canvas.width, canvas.height);
const data = imageData.data;
// 灰度處理
for (let i = 0; i < data.length; i += 4) {
  const avg = (data[i] + data[i + 1] + data[i + 2]) / 3;
  data[i] = avg;     // Red
  data[i + 1] = avg; // Green
  data[i + 2] = avg; // Blue
}
// 修改重新繪制到畫布
ctx.putImageData(imageData, 00);

當(dāng)你拿到圖像的像素值,就可以為所欲為,當(dāng)然,需要具備一定的圖像知識。

這是2D繪制,還可以進行3D繪制,是現(xiàn)在很熱門的領(lǐng)域,同樣是用Canvas,但需要額外用到WebGL,WebGL并不屬于W3C標(biāo)準(zhǔn),且涉及OpenGL語言,超出了常規(guī)前端范疇,學(xué)習(xí)曲線比較陡峭,深入掌握的人少之又少,平時大家常用Three.js等工具庫做3D效果展示,這里不再贅述。

客戶端存儲

通常,網(wǎng)頁端的數(shù)據(jù)來自兩處:接口獲取、代碼定義。

代碼中的需考慮維護性、靈活性,同時無法跨項目。

接口獲取的每次需要都得重新請求,消耗時間,特別是更新頻率很低時,會造成資源浪費。

于是,就有客戶端存儲這樣一種機制,將數(shù)據(jù)暫存在瀏覽器。

主要方案有:

  • cookie:與特定域綁定的,長度有限,數(shù)量有限,通常用于存儲較簡單的值。

    需要注意的是,所有名和值都是URL編碼的,須用decodeURIComponent()解碼。

  • WebStorage:包括localStorage和sessionStorage。

    localStorage是永久存儲機制,sessionStorage是跨會話的存儲機制。

    這兩種存儲方式都不受頁面刷新影響,且容量比cookie大得多。

  • IndexedDB:IndexedDB在瀏覽器層面創(chuàng)建了一個數(shù)據(jù)庫,但它的形式不是表,是對象。

    它的應(yīng)用通常是大對象或者文件,可省去用戶反復(fù)上傳或者頻繁請求的消耗。

富文本編輯

怎樣實現(xiàn)一個可編輯的輸入框?

大部分人的第一反應(yīng)是input或者textarea,這兩種確實比較常用,但它們是單純用于“輸入”,別的干不了。

還有少部分可能會說contenteditable,能想起這個算不錯。

還有第三種,就是在頁面中嵌入一個iframe,給它的designMode屬性設(shè)置為“on”。

通常的做法像這樣:

<iframe name="richedit"></iframe>;
window.addEventListener("load"() => {
  frames["richedit"].document.designMode = "on";
});

這樣以來,被嵌入的那部分整個都可編輯。

但只是可編輯并不滿足需求,能交互才行,與富文本編輯器交互的方法有兩種:

execCommand()

它的作用是,將字體變成“粗體、斜體”,或者改變文本背景,添加下劃線,插入“p、hr”等元素。

document.addEventListener('keydown'(e) => {
    if ((e.ctrlKey || e.metaKey) && e.key === 'b') {
        e.preventDefault();
        if (document.execCommand) {
            document.execCommand('bold'falsenull);
        }
    }
});

注意的點是,它用于修改內(nèi)嵌窗格(iframe)中富文本區(qū)域的外觀,如果想更加精細(xì)地控制當(dāng)前窗口的文本,要用第二種。

getSelection()

這個方法可以獲得富文本編輯器的選區(qū),其暴露在document和window對象上,返回表示當(dāng)前選中文本的Selection對象。

拿到對象后,其中有特別多的方法可用。直接看代碼:

const selection = window.getSelection();
if (selection.toString().length > 0) {
    const range = selection.getRangeAt(0); // 獲取選區(qū)的第一個范圍
    const selectedText = range.extractContents(); // 提取選區(qū)范圍的內(nèi)容
    const highlightSpan = document.createElement('span'); // 創(chuàng)建一個新的 span 元素
    highlightSpan.style.backgroundColor = 'yellow'// 設(shè)置 span 元素的背景顏色為黃色
    highlightSpan.appendChild(selectedText); // 將選中文本添加到 span 元素中
    range.insertNode(highlightSpan); // 將 span 元素插入到選區(qū)范圍中
    selection.removeAllRanges(); // 移除選區(qū)的所有范圍
    selection.addRange(range); // 將修改后的范圍添加回選區(qū)
}

上面這段代碼實現(xiàn)的是,將鼠標(biāo)劃過選中的文本背景設(shè)為黃色。

JavaScript API

網(wǎng)頁的載體是瀏覽器,產(chǎn)品能實現(xiàn)什么,開發(fā)者能做什么,取決于瀏覽器。

如今的瀏覽器已經(jīng)成為集各種API于一身的“瑞士軍刀”,擇取一些功能性較強的API給大家。

Clipboard API

肯定有人和我一樣,得知這個API的時候,才知道在網(wǎng)頁端實現(xiàn)復(fù)制如此簡單。

其實不是到這個API才具備這個能力,但Clipboard API使得這件事變得簡單優(yōu)雅。

它通過readText() 和 writeText()方法實現(xiàn)讀取和寫入字符串。

navigator.clipboard.readText().then((text) => {
  console.log("剪貼板內(nèi)容:", text);
});
navigator.clipboard.writeText("Hello, World!").then(() => {
  console.log("剪貼板內(nèi)容已更新");
});

同時,可以有剪貼板事件cut、copy、paste等進行監(jiān)聽。

跨上下文通信

跨文檔消息,也簡稱XDM(cross-document messaging),是一種在不同工作線程或不同源的頁面間傳遞信息的能力。

它的核心是postMessage()方法,接收到XDM消息后,window對象上會觸發(fā)message事件。

但最好只通過postMessage()發(fā)送字符串。如果需要傳遞結(jié)構(gòu)化數(shù)據(jù),最好先對該數(shù)據(jù)調(diào)用JSON.stringify(),通過postMessage()傳過去之后,再在onmessage事件處理程序中調(diào)用JSON.parse()。

除此之外,現(xiàn)在還比較常用的有 MessageChannel() 和 BroadcastChannel(),一個典型場景是,同域名下部署了幾個相互獨立的項目,要么一個內(nèi)嵌了另一個,要么在一個頁面上產(chǎn)生交互,另一個頁面需要接收狀態(tài)變化,這時候,相互通信的感知能力就很有用。

Observer API

開發(fā)者所期望的重要能力之一,就是“監(jiān)聽變化”,對變化的監(jiān)測會產(chǎn)生安全感。

DOM的變化在很長時間里是無法感知的,直到Observer API的出現(xiàn)。

現(xiàn)代瀏覽器支持的觀察者有如下幾個。

MutationObserver:監(jiān)聽DOM的修改,用于觀察整個文檔、DOM子樹或者一個元素,還能觀察元素屬性、子節(jié)點、文本等變化。

ResizeObserver:用于跟蹤DOM元素尺寸的變化,適用于響應(yīng)式Web設(shè)計或動態(tài)布局更新。

IntersectionObserver:監(jiān)聽DOM元素相對于指定視口或容器元素的可見性及位置。特別適合實現(xiàn)基于滾動的動畫、圖片懶加載、無窮滾動等性能優(yōu)化的實施。

以MutationObserver為例:

const observer = new MutationObserver((mutationsList) => {
  for (let mutation of mutationsList) {
    if (mutation.type === "childList") {
      console.log("A child node has been added or removed.");
    } else if (mutation.type === "attributes") {
      console.log("The " + mutation.attributeName + " attribute was modified.");
    }
  }
});

使用Observer API時,關(guān)鍵要處理好回調(diào)的性能,它可能會以驚人的頻率執(zhí)行,從而影響性能。一種方式是防抖,另一種方式是在不需要時把觀察者刪除。

Device API

現(xiàn)代網(wǎng)頁需要我們提供細(xì)致的個性化設(shè)計,而個性化離不開對網(wǎng)頁環(huán)境和設(shè)備的檢測,包括且不限于:設(shè)備類型、瀏覽器類型、操作系統(tǒng)等,這時就需要 Device API 的能力。

主要通過暴露在navigator對象上的一組屬性得到,比如:oscpu(系統(tǒng))、userAgent(瀏覽器)、orientation(屏幕朝向)等。

同時,還可通過Connection State 和 Networkinformation API 獲取到用戶的網(wǎng)絡(luò)連接情況,以便做出斷網(wǎng)或弱網(wǎng)處理,它們同樣暴露在navigator上,以及有相應(yīng)的 online、offline 事件可監(jiān)聽。

Page Visiblily API

Web開發(fā)中有個常見問題,就是不知道用戶當(dāng)前在使用頁面,還是切到別的界面做其他事情去了。

最常見的場景就是視頻網(wǎng)站播廣告,你停在當(dāng)前頁面看,它才會播,否則就是浪費資源。

Page Visibily API就提供了這個能力。

document.visibilyState有三個值:visible(當(dāng)前可見)、hidden(不可見)、prerender(頁面在預(yù)渲染)。

其中不可見包括“標(biāo)簽頁切換”和“最小化”,同時,還可通過 visibilityChange 事件監(jiān)聽可視狀態(tài)的變化。

URL API

這個API的存在讓人覺得很貼心,因為你總會需要在URL中攜帶信息,獲取URL信息是特別常見的需求。

但在之前,需要通過拼接組件、正則匹配、字符串查找等一系列繁瑣操作,而URL API 使這件事變得簡單。

你只需要把URL傳進去,就能直接獲得一系列有價值的信息。

const url = new URL('https://example.com/8080/page?q1=vall#fragment');
console.log('Protocol:', url.protocol); // https
console.log('Search Parameters:', url.search); // ?q1=vall

其中的參數(shù)更是能夠直接用過 URL的 searchParams 屬性輕易獲得和操作。

let qs = "?q1=vall"
let searchParams = new URLSearchParams(qs);
searchParams.has(q1) // true
searchParams.get(q1) // vall

計時API

關(guān)于時間,多數(shù)人知道Date,但是Date的本意是日期,它更適用于日期相關(guān)處理,在時間精度上只能做到毫秒,對一些精度要求更高的場景無法滿足。

于是有了performance,它包含一批API,用在不同場景。

performance.now():從0開始計時,返回微妙精度的浮點值。

performance.mark():記錄自定義性能條目。

performance.getEntriesByType:度量當(dāng)前頁面加載速度,或者資源加載速度。

這些能力,可以輔助我們對用戶的真實體驗數(shù)據(jù)做收集和分析,以便做針對性的優(yōu)化。

工作者線程

前端開發(fā)者常說:“JavaScript是單線程的”。所以經(jīng)常會面對一個問題—要做的事情太多,瀏覽器“忙不過來”,產(chǎn)生卡頓。

工作者線程,就是瀏覽器可以在原始頁面環(huán)境之外再分配一個完全獨立的二級子環(huán)境。這個子環(huán)境不能與依賴單線程交互的API(如DOM)互操作,但可以與父環(huán)境并行執(zhí)行代碼。

較為常見的就是“Web Worker”,通常會用來做文件的輸入輸出,進行密集型計算,處理大數(shù)據(jù)。

創(chuàng)建Web Woker的常見方式,是建立一個任務(wù)執(zhí)行腳本,然后把文件路徑給Worker構(gòu)造函數(shù)。

const webWorker = new Worker("worker.js");
webWorker.postMessage({
  cmd"init",
});
webWorker.onmessage = (e) => {
  console.log("主線程收到消息", e.data);
};

還有一種常見的稱作“Service Worker”(服務(wù)工作者線程),類似一個代理服務(wù)器,用于攔截外出請求和緩存響應(yīng)。可以讓網(wǎng)頁在沒有網(wǎng)絡(luò)連接的時候正常使用。

它最大的使用場景就是開發(fā)離線應(yīng)用,是開發(fā)PWA(漸進式Web應(yīng)用)的關(guān)鍵技術(shù)。

WebAssembly

書中并未涉及WebAssembly,但這是前端開發(fā)在瀏覽器變得更強大繞不開的話題。

正常來說,圖片處理、音視頻處理、模型應(yīng)用等都是JavaScript不能辦到的,需要借助C++或者Python,但前端要做的話,有沒有辦法,答案就是WebAssembly。

比如,可以借助OpenCV.js、FFmpeg.js進行圖片和音視頻處理,可以借助TensorFlow.js、Transformer.js做模型訓(xùn)練和應(yīng)用。它們無一例外都用到了WebAssembly。

所以,WebAssembly的設(shè)計目標(biāo)就是為C/C++、Rust等語言提供高效的編譯目標(biāo),使其在瀏覽器中以接近原生性能運行。感興趣的朋友可進一步拓展學(xué)習(xí)。

?轉(zhuǎn)自https://juejin.cn/post/7546564423894564879


該文章在 2025/9/10 10:01:32 編輯過
關(guān)鍵字查詢
相關(guān)文章
正在查詢...
點晴ERP是一款針對中小制造業(yè)的專業(yè)生產(chǎn)管理軟件系統(tǒng),系統(tǒng)成熟度和易用性得到了國內(nèi)大量中小企業(yè)的青睞。
點晴PMS碼頭管理系統(tǒng)主要針對港口碼頭集裝箱與散貨日常運作、調(diào)度、堆場、車隊、財務(wù)費用、相關(guān)報表等業(yè)務(wù)管理,結(jié)合碼頭的業(yè)務(wù)特點,圍繞調(diào)度、堆場作業(yè)而開發(fā)的。集技術(shù)的先進性、管理的有效性于一體,是物流碼頭及其他港口類企業(yè)的高效ERP管理信息系統(tǒng)。
點晴WMS倉儲管理系統(tǒng)提供了貨物產(chǎn)品管理,銷售管理,采購管理,倉儲管理,倉庫管理,保質(zhì)期管理,貨位管理,庫位管理,生產(chǎn)管理,WMS管理系統(tǒng),標(biāo)簽打印,條形碼,二維碼管理,批號管理軟件。
點晴免費OA是一款軟件和通用服務(wù)都免費,不限功能、不限時間、不限用戶的免費OA協(xié)同辦公管理系統(tǒng)。
Copyright 2010-2025 ClickSun All Rights Reserved