《Vuejs設計與實現》第 13 章(異步組件和函數式組件

目錄

13.1 異步組件的問題與解決方法

13.2 異步組件的實現原理

3.2.1 封裝 defineAsyncComponent 函數

13.2.2 超時與 Error 組件

13.2.3 延遲與 Loading 組件

13.2.4 重試機制

13.3 函數式組件

13.4 總結


在第12章,我們深入探討了組件的基本含義和實現方式。而在本章,我們將重點關注異步組件和函數式組件兩個關鍵概念。
異步組件的特性在于它可以異步地加載和渲染組件,這在進行代碼分割或服務端下發組件時尤其重要。
另一方面,函數式組件則允許我們用一個普通函數定義組件,并以該函數的返回值作為組件的渲染內容。函數式組件特點在于無狀態、簡潔且直觀。
雖然在 Vue2 中,函數式組件相比于有狀態組件有明顯的性能優勢,但在 Vue3 中,這兩者的性能差距已非常小。
如 Vue.js RFC 所言,我們在 Vue3 中使用函數式組件主要是因為其簡單易用,而非性能優越。

13.1 異步組件的問題與解決方法

從核心角度看,用戶完全可以自主實現異步組件,而無需依賴框架。例如,App 組件的同步渲染如下:

import App from 'App.vue'
createApp(App).mount('#app')

上述代碼可以輕松地改為異步渲染:

const loader = () => import('App.vue')
loader().then(App => {createApp(App).mount('#app')
})

此處,我們使用 import() 動態加載組件,返回一個 Promise 實例。組件加載成功后,使用 createApp 函數掛載,實現頁面的異步渲染。
如果我們想要部分頁面異步渲染,我們只需能夠異步加載某個組件。假設下面的代碼是 App.vue 組件:

<template><CompA /><component :is="asyncComp" />
</template><script>import { shallowRef } from 'vue'import CompA from 'CompA.vue'export default {components: { CompA },setup() {const asyncComp = shallowRef(null)// 異步加載 CompB 組件import('CompB.vue').then(CompB => asyncComp.value = CompB)return {asyncComp}}}
</script>

此代碼模板中,頁面由同步渲染的 和動態組件構成,動態組件綁定了 asyncComp 變量。
腳本塊異步加載 CompB 組件,加載成功后,設定 asyncComp 變量的值為 CompB,實現了 CompB 組件的異步加載和渲染。
雖然用戶可以自定義異步組件,但其實現有復雜性,因為完整的異步組件設計包括以下考慮:

  1. 如果組件加載失敗或超時,是否展示 Error 組件?
  2. 是否需要占位內容,例如 Loading 組件,于何時加載時展示?
  3. 是否設定延遲展示 Loading 組件的時間,避免由于組件加載過快導致的閃爍?
  4. 如果組件加載失敗,是否需要重試?

為了更優雅地解決這些問題,我們需在框架層面為異步組件提供封裝支持:

  1. 允許用戶指定加載錯誤時的渲染組件。
  2. 允許用戶指定 Loading 組件及其展示延遲。
  3. 允許用戶設置組件加載超時時長。
  4. 提供組件加載失敗后的重試功能。

總的來說,這些都是異步組件需要解決的核心問題

13.2 異步組件的實現原理

3.2.1 封裝 defineAsyncComponent 函數

異步組件基于封裝理念設計,其目標是提供易用的接口以減輕用戶使用難度。參考以下用戶代碼示例:

<template><AsyncComp />
</template><script>
export default {components: {// 用 defineAsyncComponent 函數定義異步組件,接收一個加載器作為參數AsyncComp: defineAsyncComponent(() => import('CompA'))}
}
</script>

上述代碼,通過 defineAsyncComponent 定義了異步組件,并在 components 組件選項中注冊。
這樣,異步組件可以像普通組件一樣在模板中使用。這種使用 defineAsyncComponent 的方式比我們在 13.1 節中自行實現的異步組件更直觀、簡潔。

defineAsyncComponent 是一個高階組件,它的基本實現如下:

function defineAsyncComponent(loader) {// 存儲異步加載的組件的變量let InnerComp = null// 返回一個包裝組件return {name: 'AsyncComponentWrapper',setup() {// 異步組件加載成功的標記const loaded = ref(false)// 執行加載器函數,返回一個 Promise 實例// 加載成功后,將組件賦值給 InnerComp,并將 loaded 標記為 trueloader().then(c => {InnerComp = cloaded.value = true})return () => {// 如果異步組件加載成功,則渲染該組件,否則渲染一個占位內容return loaded.value ? { type: InnerComp } : { type: Text, children: '' }}}}
}

關鍵點如下:

  1. defineAsyncComponent 本質是一個高階組件,返回一個包裝組件。
  2. 包裝組件根據加載器的狀態決定渲染內容。如果成功加載組件,渲染該組件;否則,渲染占位內容。
  3. 通常占位內容是注釋節點。在組件未成功加載時,頁面渲染一個注釋節點作占位。但在這里,我們用一個空文本節點作為占位。
13.2.2 超時與 Error 組件

異步組件加載通常涉及網絡請求,可能因網速慢導致加載時間過長,特別是在弱網環境下。
為了優化體驗,我們可以允許用戶設定超時時長。超過此時長仍未加載完成,則觸發超時錯誤。如果用戶配置了錯誤組件,此時則渲染錯誤組件。
為了實現這個功能,defineAsyncComponent 函數可以接受一個配置對象:

const AsyncComp = defineAsyncComponent({loader: () => import('CompA.vue'), // 指定異步組件的加載器timeout: 2000, // 設定超時時間(ms)errorComponent: MyErrorComp // 指定在發生錯誤時要渲染的組件
})

有了用戶接口后,我們可以給出實現代碼:

function defineAsyncComponent(options) {// options 可以是配置項,也可以是加載器if (typeof options === 'function') {// 如果 options 是加載器,則將其格式化為配置項形式options = {loader: options}}const { loader } = optionslet InnerComp = nullreturn {name: 'AsyncComponentWrapper',setup() {const loaded = ref(false)// 代表是否超時,默認為 false,即沒有超時const timeout = ref(false)loader().then(c => {InnerComp = cloaded.value = true})let timer = nullif (options.timeout) {// 如果指定了超時時長,則開啟一個定時器計時timer = setTimeout(() => {// 超時后將 timeout 設置為 truetimeout.value = true}, options.timeout)}// 包裝組件被卸載時清除定時器onUmounted(() => clearTimeout(timer))// 占位內容const placeholder = { type: Text, children: '' }return () => {if (loaded.value) {// 如果組件異步加載成功,則渲染被加載的組件return { type: InnerComp }} else if (timeout.value) {// 如果加載超時,并且用戶指定了 Error 組件,則渲染該組件return options.errorComponent ? { type: options.errorComponent } : placeholder}return placeholder}}}
}

關鍵點如下:

  • 異步加載是否超時由 timeout.value 標志。
  • 開始加載組件的同時,啟動一個定時器進行計時。如果超時,將 timeout.value 設置為 true。當包裝組件被卸載時,需要清除定時器。
  • 包裝組件根據 loaded 和 timeout 的值來決定渲染內容。如果加載成功,渲染被加載的組件;如果超時并且用戶指定了錯誤組件,渲染錯誤組件。

為了更全面地處理異步組件加載過程中的錯誤(超時只是其中一種),我們希望為用戶提供以下能力:

  1. 當錯誤發生時,將錯誤對象作為錯誤組件的 props 傳遞,以便用戶做進一步處理。
  2. 除了超時,還能處理其他原因導致的加載錯誤,例如網絡失敗等。

為了達到這兩個目標,我們需要對代碼進行一些調整:

function defineAsyncComponent(options) {if (typeof options === 'function') {options = {loader: options}}const { loader } = optionslet InnerComp = nullreturn {name: 'AsyncComponentWrapper',setup() {const loaded = ref(false)// 定義 error,當錯誤發生時,用來存儲錯誤對象const error = shallowRef(null)loader().then(c => {InnerComp = cloaded.value = true})// 添加 catch 語句來捕獲加載過程中的錯誤.catch(err => (error.value = err))let timer = nullif (options.timeout) {timer = setTimeout(() => {// 超時后創建一個錯誤對象,并復制給 error.valueconst err = new Error(`Async component timed out after ${options.timeout}ms.`)error.value = err}, options.timeout)}const placeholder = { type: Text, children: '' }return () => {if (loaded.value) {return { type: InnerComp }} else if (error.value && options.errorComponent) {// 只有當錯誤存在且用戶配置了 errorComponent 時才展示 Error 組件,同時將 error 作為 props 傳遞return { type: options.errorComponent, props: { error: error.value } }} else {return placeholder}}}}
}

上述代碼,我們添加了對加載過程中的錯誤捕獲。當加載超時時,我們創建一個新的錯誤對象。
在渲染組件時,如果存在 error.value 并且用戶配置了錯誤組件,就直接渲染錯誤組件并將 error.value 傳遞作為 props。
這樣,用戶可以在他們的錯誤組件中接收錯誤對象,從而實現更精細的錯誤處理。

13.2.3 延遲與 Loading 組件

異步加載的組件因網絡因素影響,加載速度可能較慢或非常快。
在網絡環境良好的情況下,異步組件可能很快加載,這可能導致 Loading 組件剛出現就立即消失,導致頁面閃爍,這對用戶體驗來說是不好的。
我們可以通過設置延遲展示 Loading 組件的時間來解決這個問題,比如在超過 200ms 后才展示 Loading 組件。以下是這種策略的實現方法。
首先,定義異步組件時,我們添加 delay 和 loadingComponent 兩個選項:

defineAsyncComponent({loader: () => new Promise(r => { /* ... */ }),delay: 200, // 延遲 200ms 展示 Loading 組件loadingComponent: { // Loading 組件setup() {return () => {return { type: 'h2', children: 'Loading...' }}}}
})

然后在 defineAsyncComponent 函數中實現這兩個選項:

function defineAsyncComponent(options) {if (typeof options === 'function') {options = {loader: options}}const { loader } = optionslet InnerComp = nullreturn {name: 'AsyncComponentWrapper',setup() {const loaded = ref(false)const error = shallowRef(null)// 一個標志,代表是否正在加載,默認為 falseconst loading = ref(false)let loadingTimer = null// 如果配置項中存在 delay,則開啟一個定時器計時,當延遲到時后將 loading.value 設置為 trueif (options.delay) {loadingTimer = setTimeout(() => {loading.value = true}, options.delay)} else {// 如果配置項中沒有 delay,則直接標記為加載中loading.value = true}loader().then(c => {InnerComp = cloaded.value = true}).catch(err => (error.value = err)).finally(() => {loading.value = false// 加載完畢后,無論成功與否都要清除延遲定時器clearTimeout(loadingTimer)})let timer = nullif (options.timeout) {timer = setTimeout(() => {const err = new Error(`Async component timed out after ${options.timeout}ms.`)error.value = err}, options.timeout)}const placeholder = { type: Text, children: '' }return () => {if (loaded.value) {return { type: InnerComp }} else if (error.value && options.errorComponent) {return { type: options.errorComponent, props: { error: error.value } }} else if (loading.value && options.loadingComponent) {// 如果異步組件正在加載,并且用戶指定了 Loading 組件,則渲染 Loading 組件return { type: options.loadingComponent }} else {return placeholder}}}}
}

關鍵改動:

  • 新增了一個狀態 loading,代表是否正在加載。
  • 如果用戶設置了 delay,則在該延遲時間后,如果仍未加載完成,就將 loading 設置為 true。
  • 不論加載是否成功,都要將 loading 設置為 false,并清除定時器。
  • 在渲染函數中,如果正在加載且用戶設置了 loadingComponent ,就渲染該組件。

此外,我們需要支持 loadingComponent 的卸載。因此需要更新 unmount 函數,使其能夠卸載組件實例的渲染內容(即 subTree ):

function unmount(vnode) {if (vnode.type === Fragment) {vnode.children.forEach(c => unmount(c))return} else if (typeof vnode.type === 'object') {// 對于組件的卸載,本質上是卸載其所渲染的內容unmount(vnode.component.subTree)return}const parent = vnode.el.parentNodeif (parent) {parent.removeChild(vnode.el)}
}

組件的卸載,本質上是要卸載組件所渲染的內容,即 subTree。
所以在上面的代碼中,我們通過組件實例的 vnode.component 屬性得到組件實例,再遞歸地調用 unmount 函數完成 vnode.component.subTree 的卸載。

13.2.4 重試機制

重試機制在異步操作(如網絡請求)中非常常見。當異步加載組件失敗,尤其是在網絡不穩定的情況下,我們希望提供一種方式讓加載操作可以自動重試,這有助于提升用戶體驗。

首先,我們創建一個模擬網絡請求的 fetch 函數,該函數在1秒后返回一個錯誤。

function fetch() {return new Promise((resolve, reject) => {// 請求在1秒后失敗setTimeout(() => {reject('err')}, 1000);})
}

接著,創建一個 load 函數來實現請求失敗后的重試:

function load(onError) {const p = fetch() // 發起請求,得到 Promise 實例return p.catch(err => {return new Promise((resolve, reject) => {const retry = () => resolve(load(onError)) // 重試const fail = () => reject(err) // 失敗onError(retry, fail) // 當錯誤發生時,調用 onError 回調})})
}

用戶可以使用 load 函數進行資源加載,并在發生錯誤時重試:

load((retry) => {retry() // 失敗后重試}
).then(res => {console.log(res) // 成功
})

最后,我們可以將這個重試機制應用到異步組件加載中

function defineAsyncComponent(options) {if (typeof options === 'function') {options = {loader: options}}const { loader } = optionslet InnerComp = null// 記錄重試次數let retries = 0// 封裝 load 函數用來加載異步組件function load() {return (loader()// 捕獲加載器的錯誤.catch(err => {// 如果用戶指定了 onError 回調,則將控制權交給用戶if (options.onError) {// 返回一個新的 Promise 實例return new Promise((resolve, reject) => {// 重試const retry = () => {resolve(load())retries++}// 失敗const fail = () => reject(err)// 作為 onError 回調函數的參數,讓用戶來決定下一步怎么做options.onError(retry, fail, retries)})} else {throw error}}))}return {name: 'AsyncComponentWrapper',setup() {const loaded = ref(false)const error = shallowRef(null)const loading = ref(false)let loadingTimer = nullif (options.delay) {loadingTimer = setTimeout(() => {loading.value = true}, options.delay)} else {loading.value = true}// 調用 load 函數加載組件load().then(c => {InnerComp = cloaded.value = true}).catch(err => {error.value = err}).finally(() => {loading.value = falseclearTimeout(loadingTimer)})// 省略部分代碼}}
}

這段代碼與接口請求的重試機制很類似。在異步組件加載過程中,如果加載失敗,我們提供一個新的 Promise 實例,并將重試(retry)和失敗(fail)的處理函數作為 onError 回調的參數,讓用戶決定下一步怎么做。

13.3 函數式組件

函數式組件簡單易實現,其本質是一個返回虛擬 DOM 的函數。
在 Vue3 中,函數式組件的優點主要在于其簡潔性,而非性能。即使是有狀態組件,在 Vue3 中,其初始化的性能消耗也相對較低。
定義函數式組件如下:

function MyFuncComp(props) {return { type: 'h1', children: props.title }
}// 定義 props
MyFuncComp.props = {title: String
}

函數式組件無自身狀態,但仍能接收外部傳入的 props。對于 props 的定義,我們在組件函數上添加靜態的 props 屬性。
我們可以復用 mountComponent 函數來實現函數式組件的掛載,此外需要支持函數類型的 vnode.type。這可以在 patch 函數內實現:

function patch(n1, n2, container, anchor) {if (n1 && n1.type !== n2.type) {unmount(n1)n1 = null}const { type } = n2if (typeof type === 'string') {// 省略部分代碼} else if (type === Text) {// 省略部分代碼} else if (type === Fragment) {// 省略部分代碼} else if (// type 是對象 --> 有狀態組件// type 是函數 --> 函數式組件typeof type === 'object' ||typeof type === 'function') {// componentif (!n1) {mountComponent(n2, container, anchor)} else {patchComponent(n1, n2, anchor)}}
}

vnode.type 的類型用以判斷組件類型:對象類型表示有狀態組件,函數類型則表示函數式組件。
不論是哪種類型,都可以通過 mountComponent 完成掛載和通過 patchComponent 完成更新。
函數式組件的掛載可以在 mountComponent 函數中實現:

function mountComponent(vnode, container, anchor) {// 檢查是否是函數式組件const isFunctional = typeof vnode.type === 'function'let componentOptions = vnode.typeif (isFunctional) {// 如果是函數式組件,則將 vnode.type 作為渲染函數,將 vnode.type.props 作為 props 選項定義componentOptions = {render: vnode.type,props: vnode.type.props}}// 省略部分代碼
}

在 mountComponent 函數內,如果組件類型是函數式組件,則直接將組件函數作為組件選項對象的 render 選項,同時將組件函數的靜態 props 屬性作為組件的 props 選項。
從這里可以看出,由于函數式組件無需初始化 data 和生命周期鉤子,其初始化性能消耗會比有狀態組件少

13.4 總結

本章首先深入探討了異步組件的作用和需求。異步組件在提高頁面性能、進行包裹分解和服務端下發組件等場景中發揮了重要作用。盡管異步組件的實現可以完全在用戶層面完成,但為考慮到加載失敗、加載中的顯示、超時設定以及重試機制等復雜問題,框架的內置支持成為了必要。因此,Vue3 提供了 defineAsyncComponent 函數來定義異步組件。
我們接著討論了異步組件加載超時和加載錯誤的處理。通過給 defineAsyncComponent 函數指定參數,我們可以設置超時時間并指定錯誤發生時展示的組件。
考慮到網絡狀況的不穩定,加載異步組件可能耗時較長。為了提供更好的用戶體驗,我們需要在加載時展示 Loading 組件。同時,我們提供了 loadingComponent 選項和 delay 選項,允許用戶自定義 Loading 組件并設置展示的延遲時間,避免 Loading 組件的閃爍問題。
在面對加載錯誤時,我們設計了重試機制。這種處理方式與處理接口請求錯誤時的重試機制相似。
最后,我們討論了函數式組件。它只是一個返回虛擬 DOM 的函數,它的實現可以復用有狀態組件的邏輯。對于函數式組件,我們在主函數上添加靜態 props 屬性來定義 props。同時,由于函數式組件無狀態且無生命周期概念,我們在初始化函數式組件時選擇性地復用有狀態組件的初始化邏輯。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/92392.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/92392.shtml
英文地址,請注明出處:http://en.pswp.cn/web/92392.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Python的七大框架對比分析

談到“Python 七大框架”時&#xff0c;通常指 Django、Flask、FastAPI、Tornado、Sanic、AIOHTTP 和 Pyramid 這七位“常駐嘉賓”。它們各有氣質&#xff0c;適合的場景也截然不同。1. DjangoDjango 像一輛全副武裝的重型越野&#xff1a;出廠就配好 ORM、后臺管理、權限、緩存…

Redis中String數據結構為什么以長度44為embstr和raw實現的分界線?

? 一道常見Redis面試題。 ? 在Redis的String數據結構中&#xff0c;當字符串的實際長度小于44且包含非整數字符時底層編碼方式為embstr。當超過44時使用raw底層編碼方式。 ? 那么為什么要以字符串的長度44為分界線呢&#xff1f; 信息一 ? 首先要分析embst…

告別人工巡查,校園空調管理邁入智能物聯高效時代

在“雙碳”戰略深入推進和智慧校園建設加速落地的背景下&#xff0c;學校空調的用電管理已經不再是“開與關”的簡單問題&#xff0c;而是涵蓋了能效優化、安全保障、智慧化管理的綜合課題。藍奧聲科技憑借LPIOT低功耗物聯網、ECWAN邊緣協同網絡等優勢技術&#xff0c;打造出面…

Access開發右下角浮窗提醒

Hi&#xff0c;大家好呀&#xff01;感覺又有很長一段時間沒有給大家更新內容了&#xff0c;最近一直在忙&#xff0c;給大家承諾的框架、視頻教程、直播等等感覺又要跳票了&#xff0c;嘿嘿&#xff0c;但大家還是不要急&#xff0c;莫催我&#xff0c;我會慢慢都更新出來的&a…

AI自進化,GPU性能翻三倍——CUDA-L1開啟自動優化新范式

最近看到一篇讓我挺震撼的文章&#xff0c;來自 DeepReinforce 團隊發布的一個新框架——CUDA-L1。說實話&#xff0c;剛看到標題說“AI 讓 GPU 性能提升 3 倍以上”&#xff0c;我心里是有點懷疑的。畢竟我們搞科研的都知道&#xff0c;這種宣傳語很多時候水分不小。但當我靜下…

深入理解 Java AWT Container:原理、實戰與性能優化

以 Container 為核心梳理 AWT 容器體系與事件模型&#xff0c;提供可運行的純 AWT 示例&#xff08;含 Panel、Frame、Dialog、ScrollPane 正確用法&#xff09;&#xff0c;并給出常見問題與性能優化建議。 Java AWT, Container, 容器, 布局管理器, 事件驅動, ScrollPane, 性…

redis--黑馬點評--用戶簽到模塊詳解

用戶簽到假如我們使用一張表來存儲用戶簽到信息&#xff0c;其結構應該如下&#xff1a;CREATE TABLE tb_sign (id bigint unsigned NOT NULL AUTO_INCREMENT COMMENT 主鍵,user_id bigint unsigned NOT NULL COMMENT 用戶id,year year NOT NULL COMMENT 簽到的年,month tinyin…

Shell、Python對比

在 Shell 腳本&#xff08;sh/bash&#xff09; 和 Python 之間選擇時&#xff0c;主要取決于具體的使用場景和需求。以下是兩者的對比分析&#xff0c;幫助你判斷哪種更方便&#xff1a;1. Shell 腳本&#xff08;sh/bash&#xff09;的優勢適用場景系統管理任務&#xff1a;如…

自適應反步控制:理論與設計

自適應反步控制 文章目錄自適應反步控制1. 基本思想A. 第一步B. 第二步1. 基本思想 基于傳統反步法&#xff0c;考慮了系統方程中以線性形式出現的未知參數。核心思想包括參數估計率和控制率。 考慮二階系統&#xff1a; {x˙1x2φ1T(x1)θx˙2uφ2T(x1,x2)θ(1)\begin{cases…

[Oracle] LEAST()函數

LEAST() 是 Oracle 中一個非常有用的函數&#xff0c;用于從一組表達式中返回最小值LEAST()函數會從給定的參數列表中返回最小的值&#xff0c;它與GREATEST()函數正好相反語法格式LEAST(expr1, expr2 [, expr3, ...])參數說明expr1, expr2, ...&#xff1a;要比較的表達式(至少…

SVM算法實戰應用

目錄 用 SVM 實現鳶尾花數據集分類&#xff1a;從代碼到可視化全解析 一、算法原理簡述 二、完整代碼實現 三、代碼解析 1. 導入所需庫 2. 加載并處理數據 3. 劃分訓練集和測試集 4. 訓練 SVM 模型 5. 計算決策邊界參數 6. 生成決策邊界數據 7. 繪制樣本點 8. 繪制…

深度虛值期權合約有什么特點?

本文主要介紹深度虛值期權合約有什么特點&#xff1f;深度虛值期權合約是期權市場中一類特殊且風險收益特征鮮明的合約&#xff0c;其核心特點可歸納為以下六點。深度虛值期權合約有什么特點&#xff1f;一、定義&#xff1a;執行價與標的價差距極大深度虛值期權是指執行價&…

(LeetCode 面試經典 150 題) 86. 分隔鏈表(鏈表+雙指針)

題目&#xff1a;86. 分隔鏈表 思路&#xff1a;雙指針&#xff0c;時間復雜度0(n)。 雙指針來維護小于x的鏈表和不小于x的鏈表即可&#xff0c;后面將兩個鏈表連起來即可。 C版本&#xff1a; /*** Definition for singly-linked list.* struct ListNode {* int val;* …

安全掃描:檢測到目標站點存在javascript框架庫漏洞問題(vue)

如果升級Vue版本有限制或者時間比較緊急&#xff0c;可以暫時用下面方式來&#xff0c;規避檢測到目標站點存在javascript框架庫vue漏洞。 在 vue.config.js 中配置: module.exports {configureWebpack: {optimization: {minimizer: [new (require(terser-webpack-plugin))({t…

【性能測試】-2- JMeter工具的使用

一、基礎腳本搭建&#x1f3af; 核心目標&#xff1a;用 JMeter 搭性能測試 “骨架”&#xff08;測試計劃、線程組、取樣器、監聽器&#xff09;&#x1f4cb; 測試計劃&#xff1a;整個測試的 “容器”&#xff0c;所有測試組件都放這里&#x1f9f5; 線程組&#xff1a;模擬…

從零構建桌面寫作軟件的書籍管理系統:Electron + Vue 3 實戰指南

&#x1f4da; 從零構建桌面寫作軟件的書籍管理系統&#xff1a;Electron Vue 3 實戰指南 &#x1f4a1; 本文深入探討了基于 Electron Vue 3 技術棧的桌面寫作軟件中書籍管理系統的設計與實現&#xff0c;涵蓋了書籍的創建、編輯、刪除等核心功能的完整技術方案&#xff0c;…

2025華數杯數學建模A題【 多孔膜光反射性能的優化與控制】原創論文講解(含完整python代碼)

大家好呀&#xff0c;從發布賽題一直到現在&#xff0c;總算完成了2025華數杯數學建模A題【 多孔膜光反射性能的優化與控制】完整的成品論文。本論文可以保證原創&#xff0c;保證高質量。絕不是隨便引用一大堆模型和代碼復制粘貼進來完全沒有應用糊弄人的垃圾半成品論文。A題論…

網絡相關(AI回答)

網管交換機都支持帶tag的以太幀嗎DeepSeek-R1 回答完成深度思考完成 用時24秒&#xff0c;搜索全網20篇資料是的&#xff0c;所有網管交換機都支持處理和轉發帶Tag&#xff08;802.1Q VLAN標簽&#xff09;的以太網幀&#xff0c;這是其核心功能之一。以下是關鍵要點&#xff1…

每日五個pyecharts可視化圖表-bars(5)

探索pyecharts庫中條形圖的高級用法與定制技巧&#xff0c;打造精美數據可視化圖表 在數據可視化中&#xff0c;條形圖是最常用的圖表類型之一。它能夠清晰地展示不同類別的數據對比&#xff0c;幫助我們快速理解數據特征。本文將為您介紹pyecharts庫中條形圖的5種高級用法&…

分布式版本控制工具Git

一.開發中為什么需要Git因為在多人開發中Git可以管理代碼&#xff0c;而且每個人都可以從庫里面下載代碼進行修改&#xff0c;每個人上傳和修改Git都會有記錄&#xff0c;如果出現大錯誤&#xff0c;還可以回退到正常版本。二.Git原理我們首先從代碼庫(Remote)下載代碼到工作區…