vue/微信小程序/h5 實現react的boundary

ErrorBoundary

  • react的boundary
    • 實現核心邏輯
    • 無法處理的情況
    • 包含函數詳細介紹getDerivedStateFromError和componentDidCatch
      • 作用
      • 為什么分開調用
    • 代碼實現(補充其他異常捕捉)
      • 函數組件與useErrorBoundary(需自定義Hook)
  • vue的boundary
    • 實現代碼:
    • 全局異常捕捉:
    • 全局異步異常捕捉:
  • nuxt 的 Error boundary
    • 插件捕捉
  • 微信小程序 Error boundary
    • 實現方式
  • h5的Error boundary
  • 總結

react的boundary

react-boundary文檔地址
如果沒有找到 ErrorBoundary,錯誤會傳播到全局,導致應用崩潰。

實現核心邏輯

在 React 中,當子組件拋出錯誤時,React 會執行以下步驟:

  1. 查找最近的 ErrorBoundary: React 會從拋出錯誤的組件向上查找其父組件樹,尋找最近的 ErrorBoundary 組件。
  2. 調用 componentDidCatch: 如果找到 ErrorBoundary,React 會調用該組件的 componentDidCatch(error, info) 方法,傳遞錯誤信息和其他信息(如錯誤發生的組件樹)。
  3. 更新狀態: ErrorBoundary 可以根據捕獲的錯誤更新自身的狀態,通常用于顯示備用 UI(如錯誤提示)。
  4. 渲染備用 UI: 一旦狀態更新,ErrorBoundary 會重新渲染,展示備用 UI,而不是子組件的正常內容。

無法處理的情況

  • 事件處理函數(比如 onClick,onMouseEnter)
  • 異步代碼(如 requestAnimationFrame,setTimeout,promise)
  • 服務端渲染
  • ErrorBoundary 組件本身的錯誤。

包含函數詳細介紹getDerivedStateFromError和componentDidCatch

作用

getDerivedStateFromErrorcomponentDidCatch 都是 React 的錯誤邊界方法,用于處理子組件的錯誤。這兩個方法共同作用,確保組件能夠優雅地處理和恢復錯誤。它們的觸發時間點和方式如下:

  1. getDerivedStateFromError:
    • 觸發時機: 當子組件拋出錯誤時,React 會首先調用這個靜態方法。
    • 功能: 允許你更新狀態以便在渲染錯誤界面之前準備新狀態。
    • 返回值: 返回一個對象來更新組件狀態,或者返回 null
  2. componentDidCatch:
    • 觸發時機: 在 getDerivedStateFromError 之后調用,主要用于執行副作用,比如日志記錄。
    • 功能: 可以處理錯誤信息,進行記錄或其他操作。
    • 參數: 接收兩個參數:錯誤信息和錯誤的組件棧。

為什么分開調用

分開調用 getDerivedStateFromErrorcomponentDidCatch 的原因主要有以下幾點:

  1. 職責分離:
    • getDerivedStateFromError 專注于根據錯誤更新狀態,以便渲染一個替代的 UI。
    • componentDidCatch 處理副作用(如日志記錄),關注于錯誤的處理和反饋。
  2. 性能優化:
    • 分開調用允許 React 在渲染過程中優化性能,避免不必要的重新渲染。
  3. 靈活性:
    • 這種設計允許開發者在狀態更新和副作用處理之間做出不同的決策,使得組件更具靈活性。
  4. 一致性:
    • getDerivedStateFromError 是一個靜態方法,適用于類組件,而 componentDidCatch 是實例方法,保持了 API 的一致性。
      通過分開處理,React 能夠提供更清晰的錯誤處理機制,提高了組件的可維護性和可讀性。

代碼實現(補充其他異常捕捉)

當你想補充異步等異常也同步到錯誤邊界組件,如在一個 try-catch 語句中捕獲異常并將其同步到錯誤邊界組件,如下:

  • 事件處理函數(比如 onClick,onMouseEnter)
  • 異步代碼(如 requestAnimationFrame,setTimeout,promise)
  • 服務端渲染
  • ErrorBoundary 組件本身的錯誤。
  1. 自定義錯誤邊界:首先,創建一個錯誤邊界組件,使用 componentDidCatch 捕捉錯誤。
class ErrorBoundary extends React.Component {constructor(props) {super(props);this.state = { hasError: false };}static getDerivedStateFromError(error) {return { hasError: true };}componentDidCatch(error, info) {// 你可以在這里記錄錯誤信息console.error("Error caught in ErrorBoundary:", error, info);}render() {if (this.state.hasError) {return <h1>Something went wrong.</h1>;}return this.props.children;}
}
  1. 在組件中使用 try-catch:在你的組件中,使用 try-catch 捕獲異常,并調用 setState 來更新錯誤狀態。
    直接在render拋出異常throw this.state.error; // 拋出錯誤以讓錯誤邊界捕獲
class MyComponent extends React.Component {constructor(props) {super(props);this.state = { error: null };}handleClick = () => {try {// 可能拋出錯誤的代碼} catch (error) {this.setState({ error: true });}};render() {try {// 可能拋出異常的代碼} catch (error) {this.setState({ error });}if (this.state.error) {throw this.state.error; // 拋出錯誤以讓錯誤邊界捕獲}return <div>正常內容button onClick={this.handleClick}>Click me</button>;</div>;}
}
  1. 包裹組件:在應用中使用錯誤邊界包裹你的組件。
<ErrorBoundary><MyComponent />
</ErrorBoundary>

函數組件與useErrorBoundary(需自定義Hook)

   function useErrorBoundary() {const [error, setError] = useState(null);const [info, setInfo] = useState(null);const handleError = (err, errorInfo) => {setError(err);setInfo(errorInfo);// 上報錯誤};useEffect(() => {const errorBoundary = React.useErrorBoundary(handleError);return () => errorBoundary.unsubscribe();}, []);if (error) {return <div>錯誤:{error.message}</div>;}return null;}

幾個關鍵點,完善一下(還是建議官方的類方式處理):

  • 使用 useCallback 緩存錯誤處理函數,避免重復渲染
  • 通過動態創建類組件的方式實現錯誤邊界功能
  • 提供了錯誤狀態重置功能(重試按鈕)
  • 展示了更友好的錯誤 UI,包括錯誤信息和組件堆棧
  • 實現了組件卸載時的資源清理
    在生產環境中使用時,還應該考慮添加以下功能:
  • 更完善的錯誤上報邏輯
  • 錯誤 UI 的樣式定制
  • 錯誤邊界的嵌套策略
  • 與 Suspense 的集成(處理異步加載錯誤)
import { useEffect, useState, useCallback } from 'react';function useErrorBoundary() {const [hasError, setHasError] = useState(false);const [error, setError] = useState(null);const [errorInfo, setErrorInfo] = useState(null);// 錯誤處理函數const handleError = useCallback((err, info) => {setHasError(true);setError(err);setErrorInfo(info);// 上報錯誤到監控系統console.error('Error Boundary Captured:', err, info);reportErrorToService(err, info); // 假設這是一個錯誤上報函數}, []);// 用于捕獲后代組件錯誤的 effectuseEffect(() => {// 創建一個錯誤邊界實例class ErrorBoundary extends React.Component {componentDidCatch(error, errorInfo) {handleError(error, errorInfo);}render() {return this.props.children;}}// 為當前組件創建一個錯誤邊界包裝器const ErrorBoundaryWrapper = ({ children }) => (<ErrorBoundary>{children}</ErrorBoundary>);// 將錯誤邊界包裝器掛載到當前組件const wrapperElement = document.createElement('div');document.body.appendChild(wrapperElement);// 渲染錯誤邊界組件const root = ReactDOM.createRoot(wrapperElement);root.render(<ErrorBoundaryWrapper>{children}</ErrorBoundaryWrapper>);// 清理函數return () => {root.unmount();document.body.removeChild(wrapperElement);};}, [handleError]);// 重置錯誤狀態const resetErrorBoundary = useCallback(() => {setHasError(false);setError(null);setErrorInfo(null);}, []);// 錯誤發生時返回錯誤 UIif (hasError) {return (<div className="error-boundary"><div className="error-message"><h2>發生錯誤</h2><p>{error?.message || '未知錯誤'}</p>{errorInfo && (<div className="error-details"><h3>錯誤詳情</h3><pre>{errorInfo.componentStack}</pre></div>)}</div><button onClick={resetErrorBoundary}>重試</button></div>);}// 沒有錯誤時返回 nullreturn null;
}// 示例使用方法
function MyComponent() {const errorBoundary = useErrorBoundary();return (<div>{errorBoundary}<RiskyComponent /> {/* 可能拋出錯誤的組件 */}</div>);
}

vue的boundary

在 Vue 中,實現這個用errorCaptured捕捉
其中,errorCaptured 鉤子可以捕捉到以下類型的錯誤:

  1. 子組件的生命周期鉤子中的錯誤:如 createdmounted 等。
  2. 渲染函數中的錯誤:在模板或渲染函數中發生的錯誤。
  3. 事件處理器中的錯誤:在事件處理函數中拋出的錯誤。
    但是,errorCaptured 無法捕捉到以下類型的錯誤:
  4. 全局未處理的 Promise 拒絕:這些錯誤需要使用全局的 window.onunhandledrejection 來捕獲。
  5. 異步操作中的錯誤:如 setTimeoutsetInterval 中的錯誤,除非在其中手動捕獲并處理。
  6. Vue 實例的錯誤:如在根實例中發生的錯誤,需在全局范圍內捕獲。
    總之,errorCaptured 主要用于捕捉組件內部的錯誤,而不適用于全局或異步錯誤。

實現代碼:

<!-- AdvancedErrorBoundary.vue -->
<template><div><slot v-if="!errorState" name="default"></slot><slot v-else name="fallback" :error="errorState"><div class="error-view"><h3>?? 組件異常</h3><p>{{ errorState.message }}</p><button @click="reset">重新加載</button></div></slot></div>
</template><script>
export default {data: () => ({errorState: null}),errorCaptured(err, vm, info) {this.errorState = {error: err,component: vm,info,timestamp: Date.now()};this.reportError(err); // 錯誤上報return false;},methods: {reset() {this.errorState = null;},reportError(err) {// 發送錯誤到監控系統}}
};
</script>

實際應用(異步捕捉手動觸發錯誤邊界):


export default {components: { ErrorBoundary },methods: {async fetchData() { //handleClick 點擊事件同理try {// 異步操作await apiCall();} catch (e) {// 1. 手動觸發錯誤邊界this.$emit('error', e); // 2. 或調用父組件方法if (this.parentErrorHandler) {this.parentErrorHandler(e);}}},
};
</script>

全局異常捕捉:

// vue2
Vue.config.errorHandler = (err, vm, info) => {// 1. 處理全局錯誤console.error('Global error:', err, info);// 2. 顯示全局錯誤提示showGlobalErrorOverlay();
};
// vue3
app.config.errorHandler = (err, vm, info) => {// 錯誤處理邏輯
};

全局異步異常捕捉:

通過 window.addEventListener('unhandledrejection') 捕獲。

nuxt 的 Error boundary

nuxt的組件方式實現,是基于vue的errorCaptured,全局如下:

插件捕捉

// 創建插件 plugins/error-handler.js
export default function ({ error }) {// 可在此處添加錯誤上報邏輯console.error('Nuxt 錯誤捕獲:', error);
}
// 并在 nuxt.config.js 中注冊
export default {plugins: ['~/plugins/error-handler'],
};

微信小程序 Error boundary

實現方式

// components/ErrorBoundary/index.js
Component({options: {multipleSlots: true, // 啟用多slot支持},properties: {fallback: {type: String,value: '頁面加載失敗,請稍后再試',},showError: {type: Boolean,value: false,},},data: {hasError: false,errorInfo: '',},methods: {// 重置錯誤狀態resetErrorBoundary() {this.setData({hasError: false,errorInfo: '',});// 觸發自定義事件通知父組件this.triggerEvent('reset');},},// 組件生命周期函數,在組件實例進入頁面節點樹時執行attached() {this.setData({hasError: this.properties.showError,});},// 錯誤捕獲處理函數pageLifetimes: {show() {// 頁面顯示時重置錯誤狀態(可選)if (this.data.hasError) {this.resetErrorBoundary();}},},// 捕獲當前組件錯誤lifetimes: {error(err) {console.error('ErrorBoundary捕獲到錯誤:', err);this.setData({hasError: true,errorInfo: err.toString(),});// 觸發自定義事件通知父組件this.triggerEvent('error', { error: err });},},
});    

使用方式

// wxml
<!-- 在頁面中使用ErrorBoundary -->
<ErrorBoundary fallback="組件加載失敗" bind:error="handleError" bind:reset="handleReset"><!-- 可能出錯的組件 --><RiskyComponent />
</ErrorBoundary>
// js
// 頁面JS
Page({methods: {handleError(e) {console.log('頁面收到錯誤信息:', e.detail.error);// 可以在這里添加錯誤上報邏輯},handleReset() {console.log('用戶點擊了重試按鈕');// 可以在這里添加重新加載數據的邏輯},},
});

h5的Error boundary

在純HTML/JavaScript環境中實現類似React的Error Boundaries功能需要創建一個自定義的錯誤邊界組件,能夠捕獲子元素的渲染錯誤并提供降級UI。

<script>// 錯誤邊界實現const errorBoundaries = {};function createErrorBoundary(containerId) {const container = document.getElementById(containerId);let hasError = false;let error = null;let errorInfo = null;function render() {if (!hasError) {container.innerHTML = `<div class="error-boundary-content"><div class="safe-component"><div class="component-title">安全組件</div><div class="component-content">這個組件運行正常</div></div><div class="unstable-component"><div class="component-title">不穩定組件</div><div class="component-content">點擊按鈕觸發錯誤</div></div></div>`;} else {container.innerHTML = `<div class="error-ui"><div class="error-header"><span class="error-icon">??</span><div class="error-title">組件渲染錯誤</div></div><div class="error-message">${error.message}</div><div class="actions"><button class="retry-btn" onclick="resetBoundary('${containerId}')">重試</button><button class="report-btn" onclick="reportError()">報告問題</button></div></div>`;}}function captureError(err, info) {hasError = true;error = err;errorInfo = info;render();console.error('ErrorBoundary caught:', err, info);}function reset() {hasError = false;error = null;errorInfo = null;render();}// 初始渲染render();return {captureError,reset};}// 創建錯誤邊界實例errorBoundaries['boundary1'] = createErrorBoundary('boundary1');errorBoundaries['boundary2'] = createErrorBoundary('boundary2');// 觸發錯誤函數function triggerError(boundaryId) {try {// 模擬一個可能出錯的函數const invalidObj = null;// 故意訪問null對象的屬性來拋出錯誤invalidObj.someProperty = 'test';} catch (error) {// 捕獲錯誤并傳遞給錯誤邊界errorBoundaries[`boundary${boundaryId}`].captureError(new Error('組件渲染時發生錯誤: ' + error.message),{ componentStack: '在UnstableComponent中' });}}// 重置錯誤邊界function resetBoundary(boundaryId) {errorBoundaries[boundaryId].reset();}// 報告錯誤function reportError() {alert('錯誤已報告給開發團隊,感謝您的反饋!');}// 初始化時隨機觸發一個錯誤setTimeout(() => {if (Math.random() > 0.5) {triggerError(2);}}, 1500);
</script>

使用方式

// 創建錯誤邊界
const boundary = createErrorBoundary('containerId');// 在可能出錯的地方捕獲錯誤
try {// 可能出錯的代碼
} catch (error) {boundary.captureError(error, { componentStack: '...' });
}// 重置錯誤邊界
boundary.reset();

總結

Vue 與 React 的差異:

  1. Vue 的錯誤捕獲是單向的(父 → 子),而 React 是雙向的(子 → 父)。
    Vue 的 errorCaptured 鉤子僅捕獲渲染期間的錯誤,不捕獲異步錯誤(如 Promise 錯誤)。
  2. 異步錯誤處理:
    全局異步錯誤需通過 window.addEventListener(‘unhandledrejection’) 捕獲。
    在 Nuxt 中,異步錯誤可通過 try…catch 或全局錯誤頁面處理。
  3. 生產環境錯誤上報:
    建議集成 Sentry 等錯誤監控工具,在錯誤捕獲時自動上報。

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

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

相關文章

Day113 切換Node.js版本、多數據源配置

切換Node.js版本 1.nvm簡介nvm(Node Version Manager)&#xff0c;在Windows上管理Node.js版本&#xff0c;可以在同一臺電腦上輕松管理和切換多個Node.js版本 nvm下載地址&#xff1a;https://github.com/coreybutler/nvm-windows/2.配置nvm安裝之后檢查nvm是否已經安裝好了&a…

應急響應靶機-linux2-知攻善防實驗室

題目&#xff1a; 1.提交攻擊者IP2.提交攻擊者修改的管理員密碼(明文)3.提交第一次Webshell的連接URL(http://xxx.xxx.xxx.xx/abcdefg?abcdefg只需要提交abcdefg?abcdefg)4.提交Webshell連接密碼5.提交數據包的flag16.提交攻擊者使用的后續上傳的木馬文件名稱7.提交攻擊者隱藏…

新手前端使用Git(常用命令和規范)

發一篇文章來說一下前端在開發項目的時候常用的一些git命令 注&#xff1a;這篇文章只說最常用的&#xff0c;最下面有全面的 一&#xff1a;從git倉庫拉取項目到本地 1&#xff1a;新建文件夾存放項目代碼 2&#xff1a;在git上復制一下項目路徑&#xff08;看那個順眼復制…

【面試題】常用Git命令

【面試題】常用Git命令1. 常用Git命令1. 常用Git命令 1.git clone git clone https://gitee.com/Blue_Pepsi_Cola/straw.git 2.使用-v選項&#xff0c;可以參看遠程主機的網址 git remote -v origin https://ccc.ddd.com/1-java/a-admin-api.git (fetch) origin https://ccc.…

Webpack構建工具

構建工具系列 Gulp構建工具Grunt構建工具Webpack構建工具Vite構建工具 Webpack構建工具 構建工具系列前言一、安裝打包配置webpack安裝樣式加載器devtoolwebpack devtool 配置詳解常見 devtool 值及適用場景選擇建議性能影響注意事項 module處理流程module.rulesmodule.usemod…

重學前端002 --響應式網頁設計 CSS

文章目錄 css 樣式特殊說明 根據在這里 Freecodecamp 實踐&#xff0c;調整順序后做的總結。 css 樣式 body {background-color: red; # 跟background-image 不同時使用background-image: url(https://cdn.freecodecamp.org/curriculum/css-cafe/beans.jpg);font-family: san…

RabbitMQ簡單消息監聽和確認

如何監聽RabbitMQ隊列 簡單代碼實現RabbitMQ消息監聽 需要的依賴 <!--rabbitmq--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId><version>x.x.x</version>&l…

Docker學習筆記:Docker網絡

本文是自己的學習筆記 1、Linux中的namespace1.1、創建namespace1.2、兩個namespace互相通信2、Docker中的namespace2.1 容器中的默認Bridge3、容器的三種網絡模式1、Linux中的namespace Docker中使用了虛擬網絡技術&#xff0c;讓各個容器的網絡隔離。好像每個容器從網卡到端…

用自定義注解解決excel動態表頭導出的問題

導入的excel有固定表頭動態表頭如何解決 自定義注解&#xff1a; import java.lang.annotation.*;/*** 自定義注解&#xff0c;用于動態生成excel表頭*/ Target(ElementType.FIELD) Retention(RetentionPolicy.RUNTIME) public interface FieldLabel {// 字段中文String label(…

Android-EDLA 解決 GtsMediaRouterTestCases 存在 fail

問題描述&#xff1a;[原因]R10套件新增模塊&#xff0c;getRemoteDevice獲取遠程藍牙設備時&#xff0c;藍牙MAC為空 [對策]實際藍牙MAC非空;測試時繞過處理 1.release/ebsw_skg/skg/frameworks/base/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManage…

雙渦輪增壓器結構設計cad【5張】+設計說明書

摘要 隨著汽車制造商和消費者對動力性能的要求不斷增加&#xff0c;發動機需要在更寬的轉速范圍內提供更大的功率和扭矩。雙渦輪增壓器可以幫助實現這一目標&#xff0c;通過在不同轉速下調整渦輪的工作狀態來提供更平順的動力輸出。單一渦輪增壓器可能存在渦輪滯后和增壓延遲…

大數據輕量化流批一體架構探索實踐(一)

最近學習了解到一種輕量化&#xff0c;維護門檻較低的流批一體化的架構方式&#xff0c;雖然目前還是不太成熟&#xff0c;自己也在探索學習中。 dolphinschedulerdinkystarrocksflinkzookeper 后面我會逐步發一下這個整體架構的特點&#xff0c;以及各個組件作用&#xff0c;和…

【2025/07/04】GitHub 今日熱門項目

GitHub 今日熱門項目 &#x1f680; 每日精選優質開源項目 | 發現優質開源項目&#xff0c;跟上技術發展趨勢 &#x1f4cb; 報告概覽 &#x1f4ca; 統計項&#x1f4c8; 數值&#x1f4dd; 說明&#x1f4c5; 報告日期2025-07-04 (周五)GitHub Trending 每日快照&#x1f55…

HarmonyOS學習記錄3

HarmonyOS學習記錄3 本文為個人學習記錄&#xff0c;僅供參考&#xff0c;如有錯誤請指出。本文主要記錄ArkTS基礎語法&#xff0c;僅記錄了部分我覺得與其他語言不太類似的地方&#xff0c;具體規范請參考官方文檔。 參考官方文檔&#xff1a;https://developer.huawei.com/co…

HKS201-M24 大師版 8K60Hz USB 3.0 適用于 2 臺 PC 1臺顯示器 無縫切換 KVM 切換器

HKS201-M24 8K60Hz HDMI 2.1 2x1 KVM 切換器&#xff0c;適用于 2 臺 PC&#xff0c;帶 EDID 仿真、千兆 LAN、雙充電和 USB 3.2 Gen 1 HKS201-M24 產品概述 TESmart 重新定義智能工作空間&#xff0c;無縫雙PC控制。 真正的 8K60Hz 亮度&#xff0c;具有 EDID 穩定性和超快速…

stm32f103vct6的DAC口的輸出電壓達不到3.3V

問題&#xff1a;調試時發現自己設置的DAC在最大時達不到3.3V&#xff0c;總結了原因&#xff0c;記錄下。 原因&#xff1a;使用時&#xff0c;注意有沒有其他負載&#xff0c;有的話最好給負載獨立供電&#xff0c;不要只用STM32f103的板湊活著供電&#xff0c;我的就是這個…

java8 Collectors.mapping 使用 例子 學習

java8 Collectors.mapping 使用 例子 學習 Map<String, List<String>> colorApple appleList.stream().collect(Collectors.groupingBy(Apple::getColor, Collectors.mapping(Apple::getVariety, toList()))); colorApple.forEach((k, v) -> {System.out.prin…

動態規劃-P1216 [IOI 1994] 數字三角形 Number Triangles

P1216 [IOI 1994] 數字三角形 Number Triangles 題目來源-洛谷題庫 思路 如果用貪心只是找當前的到達該點的路徑最大值&#xff0c;可能結果無法做到最優最值問題試著看能否將大問題分解成若干個小問題 走到a[i] [j ]這個點的最值來源于上一步a[i-1 ] [j]和a[i-1] [j-1]的最…

25年Java后端社招技術場景題!

一、電商領域高頻場景題1. 百萬級QPS秒殺系統設計場景需求&#xff1a;設計一個支持百萬級QPS的秒殺系統&#xff0c;要求解決超賣問題&#xff0c;保證系統高可用。技術方案&#xff1a;分層削峰&#xff1a;前端頁面靜態化按鈕防重復點擊Redis集群&#xff1a;采用Lua腳本實現…

牛客:HJ16 購物單【01背包】【華為機考】

學習要點 深入理解回溯深入理解01背包問題 題目鏈接 購物單_牛客題霸_牛客網 題目描述 解法1&#xff1a;回溯 其實此題非常符合取子集的邏輯&#xff0c;但是時間復雜度太高。通過11/14。想寫出來這個回溯過程&#xff0c;不容易。 #include <iostream> #include &l…