TTS-Web-Vue系列:Vue3實現內嵌iframe文檔顯示功能

🖼? 本文是TTS-Web-Vue系列的新篇章,重點介紹如何在Vue3項目中優雅地實現內嵌iframe功能,用于加載外部文檔內容。通過Vue3的響應式系統和組件化設計,我們實現了一個功能完善、用戶體驗友好的文檔嵌入方案,包括加載狀態管理、錯誤處理和自適應布局等關鍵功能。

📖 系列文章導航

歡迎查看主頁

🌟 內嵌iframe的應用場景與價值

在現代Web應用中,內嵌iframe是集成外部內容的有效方式,特別適用于以下場景:

  1. 展示項目文檔:直接嵌入項目文檔網站,避免用戶在多個標簽頁切換
  2. 整合第三方內容:無需重新開發,直接復用已有的Web資源
  3. 隔離運行環境:為外部內容提供獨立的執行環境,避免與主應用沖突
  4. 保持UI一致性:讓外部內容看起來像是應用的一部分,提升用戶體驗
  5. 降低開發成本:避免重復開發相似功能,專注于核心業務邏輯

在TTS-Web-Vue項目中,我們使用內嵌iframe來加載項目文檔,使用戶能夠在不離開應用的情況下查閱使用指南、API文檔和其他參考資料。

💡 實現思路與技術選型

整體設計方案

我們的iframe嵌入方案采用了以下設計思路:

  1. 響應式狀態管理:使用Vue3的響應式系統管理iframe的加載狀態
  2. 異常處理機制:完善的錯誤處理和恢復策略,提供友好的錯誤界面
  3. 動態樣式調整:根據內容和容器大小動態調整iframe尺寸
  4. 跨域安全處理:合理設置sandbox屬性和referrer策略,確保安全性
  5. 加載狀態反饋:提供視覺反饋,優化用戶等待體驗
  6. 備用方案支持:支持多個文檔源,在主源不可用時提供備選鏈接

這種方案既保證了功能的完整性,又提供了良好的用戶體驗和可維護性。

技術實現要點

  • 使用Vue3的refwatch實現響應式狀態管理
  • 通過DOM API動態調整iframe樣式和容器布局
  • 利用Element Plus組件庫提供加載和錯誤界面
  • 使用PostMessage API實現iframe與主應用的通信
  • 結合CSS動畫提升加載體驗

🧩 核心代碼實現

主組件模板代碼

在Main.vue中,我們實現了文檔頁面容器和iframe的基本結構:

<div v-if="page.asideIndex === '4'" class="doc-page-container" :key="'doc-page'"><!-- 加載狀態顯示 --><div v-if="!iframeLoaded && !iframeError" class="iframe-loading"><div class="loading-spinner"></div><p>正在加載文檔<span class="loading-dots"></span></p></div><!-- iframe組件 --><iframe ref="docIframe"class="doc-frame" :src="iframeCurrentSrc" @load="handleIframeLoad"@error="handleIframeError"allow="fullscreen"referrerpolicy="no-referrer":class="{'iframe-visible': iframeLoaded}"sandbox="allow-scripts allow-same-origin allow-popups allow-forms"></iframe><!-- 錯誤狀態顯示 --><div v-if="iframeError" class="iframe-error"><el-icon class="error-icon"><WarningFilled /></el-icon><p>加載文檔失敗,請檢查網絡連接或嘗試備用鏈接。</p><div class="error-actions"><el-button type="primary" @click="reloadIframe"><el-icon><RefreshRight /></el-icon> 重新加載</el-button><el-button @click="tryAlternativeUrl"><el-icon><SwitchButton /></el-icon> 嘗試備用鏈接</el-button></div></div>
</div>

狀態管理與初始化

在組合式API中管理iframe相關的狀態:

// 聲明狀態變量
const docIframe = ref(null);
const iframeLoaded = ref(false);
const iframeError = ref(false);
const docUrl = ref('https://docs.tts88.top/');
const urlIndex = ref(0);
const iframeCurrentSrc = ref('');
const docUrls = ['https://docs.tts88.top/',// 可以添加備用鏈接
];// iframe初始化函數
const initIframe = () => {iframeCurrentSrc.value = '';// 在清除src后,立即設置容器和iframe樣式以確保正確顯示nextTick(() => {// 修改頁面主容器樣式,保留基本結構但減少內邊距const mainContainer = document.querySelector('.modern-main');if (mainContainer instanceof HTMLElement && page?.value?.asideIndex === '4') {mainContainer.style.padding = '0';mainContainer.style.gap = '0';}const container = document.querySelector('.doc-page-container');if (container instanceof HTMLElement) {// 設置文檔容器填充可用空間,但不使用fixed定位container.style.display = 'flex';container.style.flexDirection = 'column';container.style.height = 'calc(100vh - 40px)'; // 只預留頂部導航欄的空間container.style.margin = '0';container.style.padding = '0';container.style.borderRadius = '0';container.style.boxShadow = 'none';container.style.position = 'relative';}if (docIframe.value) {docIframe.value.style.display = 'block';docIframe.value.style.flex = '1';docIframe.value.style.width = '100%';docIframe.value.style.height = '100%';docIframe.value.style.minHeight = '700px';docIframe.value.style.maxHeight = 'none';docIframe.value.style.margin = '0';docIframe.value.style.padding = '0';docIframe.value.style.border = 'none';docIframe.value.style.borderRadius = '0';}// 設置iframe源iframeCurrentSrc.value = docUrl.value;console.log('iframe 初始化源設置為:', docUrl.value);});
};

事件處理函數

處理iframe的加載和錯誤事件:

// 處理 iframe 加載成功
const handleIframeLoad = (event) => {console.log('iframe 加載事件觸發');// 檢查iframe是否完全加載且可訪問try {const iframe = event.target;// 不是所有iframe都會觸發跨域報錯,但我們需要檢查是否實際加載成功if (iframe.contentWindow && iframe.src.includes(docUrl.value)) {iframeLoaded.value = true;iframeError.value = false;console.log('iframe 加載成功:', {width: iframe.offsetWidth,height: iframe.offsetHeight});// 嘗試調整iframe高度nextTick(() => {adjustIframeHeight();// 發送初始化消息到iframesendInitMessageToIframe();});// 顯示加載成功提示ElMessage({message: "文檔加載成功",type: "success",duration: 2000,});} else {console.warn('iframe可能加載不完整或存在跨域問題');}} catch (error) {// 處理跨域安全限制導致的錯誤console.error('檢查iframe出錯 (可能是跨域問題):', error);// 我們不將這種情況標記為錯誤,因為iframe可能仍然正常加載iframeLoaded.value = true;}
};// 處理 iframe 加載失敗
const handleIframeError = (event) => {console.error('iframe 加載失敗:', event);iframeLoaded.value = false;iframeError.value = true;ElMessage({message: "文檔加載失敗,請檢查網絡連接",type: "error",duration: 3000,});
};// 重新加載 iframe
const reloadIframe = () => {console.log('重新加載 iframe');iframeLoaded.value = false;iframeError.value = false;// 強制 iframe 重新加載initIframe();ElMessage({message: "正在重新加載文檔",type: "info",duration: 2000,});
};// 嘗試使用備用鏈接
const tryAlternativeUrl = () => {urlIndex.value = (urlIndex.value + 1) % docUrls.length;docUrl.value = docUrls[urlIndex.value];console.log(`嘗試備用文檔鏈接: ${docUrl.value}`);iframeLoaded.value = false;iframeError.value = false;// 清空并重新設置src以確保重新加載initIframe();ElMessage({message: `正在嘗試備用鏈接: ${docUrl.value}`,type: "info",duration: 3000,});
};

樣式和動畫設計

為iframe相關組件添加樣式:

.iframe-loading, .iframe-error {position: absolute;top: 0;left: 0;right: 0;bottom: 0;display: flex;flex-direction: column;justify-content: center;align-items: center;background-color: var(--card-background);z-index: 1000;text-align: center;
}.iframe-loading {font-size: 18px;font-weight: 600;color: var(--text-primary);
}.loading-spinner {width: 40px;height: 40px;border: 4px solid rgba(74, 108, 247, 0.2);border-radius: 50%;border-top-color: var(--primary-color);animation: spin 1s linear infinite;margin-bottom: 16px;
}@keyframes spin {to {transform: rotate(360deg);}
}.iframe-error {padding: 30px;background-color: var(--card-background);
}.iframe-error p {margin: 16px 0;font-size: 16px;color: var(--text-secondary);
}.error-icon {font-size: 48px;color: #ff4757;margin-bottom: 16px;
}.error-actions {display: flex;gap: 16px;margin-top: 16px;
}.loading-dots {display: inline-block;width: 30px;text-align: left;
}.loading-dots:after {content: '.';animation: dots 1.5s steps(5, end) infinite;
}@keyframes dots {0%, 20% {content: '.';}40% {content: '..';}60% {content: '...';}80%, 100% {content: '';}
}

🔄 跨域通信實現

發送消息到iframe

通過postMessage API實現與iframe內容的通信:

// 向iframe發送消息
const sendMessageToIframe = (message) => {if (docIframe.value && docIframe.value.contentWindow) {try {docIframe.value.contentWindow.postMessage(message, '*');console.log('向iframe發送消息:', message);} catch (error) {console.error('向iframe發送消息失敗:', error);}}
};// 在iframe加載完成后發送初始化消息
const sendInitMessageToIframe = () => {// 等待iframe完全加載setTimeout(() => {sendMessageToIframe({type: 'init',appInfo: {name: 'TTS Web Vue',version: '1.0',theme: document.body.classList.contains('dark-theme') ? 'dark' : 'light'}});}, 1000);
};

接收來自iframe的消息

監聽并處理iframe發送的消息:

// 處理來自iframe的消息
const handleIframeMessage = (event) => {console.log('收到消息:', event);// 確保消息來源安全,驗證來源域名const isValidOrigin = docUrls.some(url => {try {const urlHost = new URL(url).hostname;return event.origin.includes(urlHost);} catch (e) {return false;}});// 如果消息來源不安全,忽略此消息if (!isValidOrigin) {console.warn('收到來自未知來源的消息,已忽略:', event.origin);return;}console.log('來自文檔頁面的消息:', event.data);// 處理不同類型的消息if (typeof event.data === 'object' && event.data !== null) {// 文檔加載完成消息if (event.data.type === 'docLoaded') {iframeLoaded.value = true;iframeError.value = false;ElMessage({message: "文檔頁面已準備就緒",type: "success",duration: 2000,});// 對iframe內容回送確認消息sendMessageToIframe({type: 'docLoadedConfirm',status: 'success'});}// 調整高度消息if (event.data.type === 'resizeHeight' && typeof event.data.height === 'number') {const height = event.data.height;if (height > 0 && docIframe.value) {// 確保高度合理const safeHeight = Math.max(Math.min(height, 5000), 300);docIframe.value.style.height = `${safeHeight}px`;console.log(`根據iframe請求調整高度: ${safeHeight}px`);}}}
};// 在組件掛載時添加消息監聽器
onMounted(() => {window.addEventListener('message', handleIframeMessage);
});// 在組件卸載時移除監聽器
onUnmounted(() => {window.removeEventListener('message', handleIframeMessage);
});

📱 自適應布局實現

響應式高度調整

動態調整iframe高度以適應不同屏幕尺寸:

// 添加新函數用于調整iframe高度
const adjustIframeHeight = () => {if (!docIframe.value) return;// 獲取容器高度const container = document.querySelector('.doc-page-container');if (!container) return;// 修改頁面主容器樣式,減少內邊距但保留基本布局const mainContainer = document.querySelector('.modern-main');if (mainContainer instanceof HTMLElement && page?.value?.asideIndex === '4') {mainContainer.style.padding = '0';mainContainer.style.gap = '0';}// 獲取可用高度(視口高度減去頂部導航欄高度)const availableHeight = window.innerHeight - 40;// 設置container樣式以充分利用可用空間if (container instanceof HTMLElement) {container.style.height = `${availableHeight}px`;container.style.maxHeight = `${availableHeight}px`;container.style.margin = '0';container.style.padding = '0';container.style.borderRadius = '0';container.style.boxShadow = 'none';container.style.position = 'relative';}// 設置iframe樣式以充滿容器docIframe.value.style.width = '100%';docIframe.value.style.height = '100%';docIframe.value.style.minHeight = '700px';docIframe.value.style.maxHeight = 'none';docIframe.value.style.display = 'block';docIframe.value.style.flex = '1';docIframe.value.style.margin = '0';docIframe.value.style.padding = '0';docIframe.value.style.border = 'none';docIframe.value.style.borderRadius = '0';
};// 監聽窗口大小變化事件
const handleResize = () => {if (page?.value?.asideIndex === '4' && iframeLoaded.value) {adjustIframeHeight();}
};// 在組件掛載和窗口大小變化時調整高度
onMounted(() => {window.addEventListener('resize', handleResize);
});onUnmounted(() => {window.removeEventListener('resize', handleResize);
});

移動端顯示優化

為移動設備添加特定的樣式調整:

@media (max-width: 768px) {.doc-page-container {height: calc(100vh - 50px) !important; /* 為移動端頂部導航欄留出更多空間 */}.iframe-loading p, .iframe-error p {font-size: 14px;padding: 0 20px;}.error-actions {flex-direction: column;width: 80%;}.loading-spinner {width: 30px;height: 30px;}
}

🔒 安全性考慮

iframe安全屬性設置

為確保iframe的安全性,我們設置了以下關鍵屬性:

<iframe ref="docIframe"class="doc-frame" :src="iframeCurrentSrc" @load="handleIframeLoad"@error="handleIframeError"allow="fullscreen"referrerpolicy="no-referrer":class="{'iframe-visible': iframeLoaded}"sandbox="allow-scripts allow-same-origin allow-popups allow-forms"
>
</iframe>

主要安全措施包括:

  1. sandbox屬性:限制iframe內容的權限,僅允許必要的功能

    • allow-scripts: 允許運行腳本
    • allow-same-origin: 允許訪問同源資源
    • allow-popups: 允許打開新窗口
    • allow-forms: 允許表單提交
  2. referrerpolicy:設置為no-referrer防止泄露引用信息

  3. 消息驗證:驗證接收消息的來源,防止惡意站點發送的消息

跨域消息驗證

在處理iframe消息時進行來源驗證:

// 確保消息來源安全,驗證來源域名
const isValidOrigin = docUrls.some(url => {try {const urlHost = new URL(url).hostname;return event.origin.includes(urlHost);} catch (e) {return false;}
});// 如果消息來源不安全,忽略此消息
if (!isValidOrigin) {console.warn('收到來自未知來源的消息,已忽略:', event.origin);return;
}

🎭 用戶體驗增強

加載狀態優化

為提供更好的視覺反饋,我們添加了加載動畫和進度指示:

<div v-if="!iframeLoaded && !iframeError" class="iframe-loading"><div class="loading-spinner"></div><p>正在加載文檔<span class="loading-dots"></span></p>
</div>

動畫效果通過CSS實現:

.loading-spinner {width: 40px;height: 40px;border: 4px solid rgba(74, 108, 247, 0.2);border-radius: 50%;border-top-color: var(--primary-color);animation: spin 1s linear infinite;margin-bottom: 16px;
}@keyframes spin {to {transform: rotate(360deg);}
}.loading-dots:after {content: '.';animation: dots 1.5s steps(5, end) infinite;
}@keyframes dots {0%, 20% {content: '.';}40% {content: '..';}60% {content: '...';}80%, 100% {content: '';}
}

錯誤處理與恢復

提供直觀的錯誤界面和恢復選項:

<div v-if="iframeError" class="iframe-error"><el-icon class="error-icon"><WarningFilled /></el-icon><p>加載文檔失敗,請檢查網絡連接或嘗試備用鏈接。</p><div class="error-actions"><el-button type="primary" @click="reloadIframe"><el-icon><RefreshRight /></el-icon> 重新加載</el-button><el-button @click="tryAlternativeUrl"><el-icon><SwitchButton /></el-icon> 嘗試備用鏈接</el-button></div>
</div>

📊 性能優化

減少重繪和回流

為提高iframe加載性能,我們采取了以下優化措施:

// 先將iframe的src設為空,然后再設置目標URL,減少重復加載
iframeCurrentSrc.value = '';// 使用nextTick等待DOM更新后再進行樣式調整
nextTick(() => {// 樣式調整代碼...// 最后再設置srciframeCurrentSrc.value = docUrl.value;
});

延遲加載與可見性優化

只有在iframe加載完成后才顯示內容,避免閃爍:

<iframe :class="{'iframe-visible': iframeLoaded}"<!-- 其他屬性... -->
>
</iframe>
.doc-frame {opacity: 0;transition: opacity 0.3s ease;
}.iframe-visible {opacity: 1;
}

📝 總結與拓展

主要成果

通過Vue3實現內嵌iframe,我們為TTS-Web-Vue項目帶來了以下價值:

  1. 一體化用戶體驗:用戶無需離開應用即可訪問文檔
  2. 響應式布局:自適應不同屏幕尺寸,優化移動端體驗
  3. 完善的狀態管理:處理加載、錯誤等各種狀態,提升用戶體驗
  4. 安全可控:通過sandbox和消息驗證確保安全性
  5. 高性能:優化加載過程,減少性能開銷

未來可能的拓展方向

  1. 內容預加載:實現文檔預加載,進一步提升加載速度
  2. 深度鏈接:支持直接鏈接到文檔的特定部分
  3. 離線支持:加入文檔緩存功能,支持離線訪問
  4. 內容同步:實現iframe內容與應用狀態的雙向同步
  5. 多文檔管理:支持多個文檔源和文檔切換功能

🔗 相關鏈接

  • TTS-Web-Vue項目主頁
  • 在線演示
  • Vue3官方文檔
  • Element Plus UI庫
  • MDN iframe文檔

注意:本文介紹的功能僅供學習和個人使用,請勿用于商業用途。如有問題或建議,歡迎在評論區討論!

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

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

相關文章

Elasticsearch索引設計與調優

一、分片策略設計 1.?分片容量規劃 單分片容量建議30GB(日志場景可放寬至100GB),避免超大分片引發查詢延遲。分片總數計算公式:總數據量 / 30GB 1.2(20%余量應對未來增長)。主分片數創建后不可修改,副本分片數支持動態調整。2.?分片分布優化 PUT logs-2025 { &qu…

Spring AI 集成 Mistral AI:構建高效多語言對話助手的實戰指南

Spring AI 集成 Mistral AI&#xff1a;構建高效多語言對話助手的實戰指南 前言 在人工智能應用開發領域&#xff0c;選擇合適的大語言模型&#xff08;LLM&#xff09;與開發框架至關重要。Mistral AI 憑借其高效的多語言模型&#xff08;如 Mistral-7B、Mixtral-8x7B 等&am…

從新手到高手:全面解析 AI 時代的「魔法咒語」——Prompt

引言&#xff1a;AI 時代的「語言煉金術」 在人工智能技術突飛猛進的今天&#xff0c;我們正在經歷一場堪比工業革命的生產力變革。從聊天機器人到圖像生成&#xff0c;從數據分析到自動化寫作&#xff0c;AI 模型正在重塑人類與信息交互的方式。而在這一切背后&#xff0c;隱…

MySQL 8.0安裝(壓縮包方式)

MySQL 8.0安裝(壓縮包方式) 下載安裝包并解壓 下載 https://dev.mysql.com/downloads/mysql/可關注“后端碼匠”回復“MySQL8”關鍵字獲取 解壓&#xff08;我解壓到D:\dev\mysql-8.4.5-winx64目錄下&#xff09; 創建mysql服務 注意&#xff0c;這步之前一定要保證自己電…

免費Ollama大模型集成系統——Golang

Ollama Free V2 Web 功能實現&#xff1a;界面交互與后端邏輯 一、Web 界面概述 Ollama Free V2 的 Web 界面提供了豐富的交互功能&#xff0c;包括模型選擇、圖片上傳、歷史記錄查看等。界面使用 Bootstrap 進行布局&#xff0c;結合 JavaScript 實現動態交互。 二、前端界…

【AI】人工智能數據標注細分和商業機會

一、數據標注的常見方法 數據標注是為人工智能模型訓練提供高質量標簽的過程&#xff0c;根據數據類型&#xff08;圖像、文本、音頻、視頻等&#xff09;的不同&#xff0c;標注方法也有所差異&#xff1a; 1. 圖像標注 分類標注&#xff1a;為圖像分配類別標簽&#xff08…

lanqiaoOJ 652:一步之遙 ← 擴展歐幾里得定理

【題目來源】 https://www.lanqiao.cn/problems/652/learning/ 【題目背景】 本題為填空題&#xff0c;只需要算出結果后&#xff0c;在代碼中使用輸出語句將所填結果輸出即可。 【題目描述】 從昏迷中醒來&#xff0c;小明發現自己被關在X星球的廢礦車里。礦車停在平直的廢棄…

HTTP / HTTPS 協議

目錄 一、前言&#xff1a; 二、Fiddler 抓包工具&#xff1a; 三、http 協議&#xff1a; 1、http 請求&#xff1a; 1.&#xff08;1&#xff09;請求行&#xff1a; 1、(2) 請求頭&#xff1a; 1、(3) 請求正文: 2、http 響應&#xff1a; 2、(1) 狀態碼&#x…

使用泛型加載保存數據

文章速覽 泛型泛型概述定義優點 實例加載數據保存數據 一個贊&#xff0c;專屬于你的足跡&#xff01; 泛型 泛型概述 泛型&#xff08;Generics&#xff09;是 C# 中一種重要的編程特性&#xff0c;它允許程序員編寫靈活且類型安全的代碼。通過使用泛型&#xff0c;可以創建…

Redis內存淘汰策略和過期鍵刪除策略有哪些?

Redis 提供 8 種內存淘汰策略&#xff0c;以下是詳細解析及場景建議&#xff1a; 一、核心策略解析 noeviction (默認策略) 機制&#xff1a;內存滿時拒絕新寫入操作&#xff0c;返回錯誤優勢&#xff1a;絕對數據安全場景&#xff1a;金融交易系統、醫療數據存儲 allkeys-lr…

【C/C++】自定義類型:結構體

文章目錄 前言自定義類型&#xff1a;結構體1.結構體類型的聲明1.1 結構體回顧1.1.1 結構的聲明 1.1.2 結構體變量的創建和初始化1.2 結構的特殊聲明1.3 結構的自引用 2.結構體內存對齊2.1 對?規則2.2 為什么存在內存對齊&#xff1f;2.3 修改默認對?數 3. 結構體傳參4.結構體…

PPO算法:一種先進的強化學習策略

什么是PPO算法&#xff1f; PPO&#xff08;Proximal Policy Optimization&#xff09;是一種增強學習算法&#xff0c;主要應用于解決連續控制任務。PPO算法在2017年由OpenAI提出&#xff0c;旨在解決傳統策略梯度方法在連續控制任務中面臨的挑戰。PPO算法通過引入一個近似目…

OpenCV實現數字水印的相關函數和示例代碼

OpenCV計算機視覺開發實踐&#xff1a;基于Qt C - 商品搜索 - 京東 實現數字水印的相關函數 用OpenCV來實現數字水印功能&#xff0c;需要使用一些位操作函數&#xff0c;我們需要先了解一下這些函數。 1. bitwise_and函數 bitwise_and函數是OpenCV中的位運算函數之一&…

基于Python的計算機科學研究話題管理系統的設計與實現 - 爬蟲

標題:基于Python的計算機科學研究話題管理系統的設計與實現 - 爬蟲 內容:1.摘要 本文聚焦于基于Python的計算機科學研究話題管理系統的爬蟲部分。背景是隨著計算機科學研究的快速發展&#xff0c;相關話題數據海量且分散&#xff0c;人工管理效率低。目的是設計并實現一個能高…

告別手動解析!借助 CodeBuddy 快速開發網頁源碼提取工具

作為一名長期從事 Web 開發的程序員&#xff0c;我們在日常工作中&#xff0c;時不時會需要查看網頁的源代碼。這么做的目的通常是為了排查前端渲染的問題、分析接口返回的數據結構&#xff0c;或者就是單純地想快速提取頁面中的某些信息&#xff0c;比如文章鏈接、圖片地址&am…

為什么要在 input() 后加 .strip()?

strip() 是 Python 字符串的一個方法&#xff0c;用于去除字符串開頭和結尾的空白字符&#xff08;包括空格、制表符 \t、換行符 \n 等&#xff09;。 為什么要在 input() 后加 .strip()&#xff1f; 用戶在輸入時&#xff0c;可能會不小心在開頭或結尾輸入空格&#xff0c;例…

【日擼 Java 300行】Day 14(棧)

目錄 Day 14&#xff1a;棧 一、棧的基本知識 二、棧的方法 1. 順序表實現棧 2. 入棧 3. 出棧 三、代碼及測試 拓展&#xff1a; 小結 Day 14&#xff1a;棧 Task&#xff1a; push 和 pop 均只能在棧頂操作.沒有循環, 時間復雜度為 O(1). 一、棧的基本知識 詳細的介…

dotnet core c#調用Linux c++導出函數

1.聲明C++導出函數 platform_export.h // // Created by dev on 5/6/25. //#ifndef PLATFORM_EXPORT_H #define PLATFORM_EXPORT_H #if defined(_WIN32)#ifdef LIB_EXPORTS#define LIB_API __declspec(dllimport)#else#define LIB_API __declspec(dllimport)#endif #else#ifde…

SparkSQL操作Mysql

前面的課程我們學習了如何從csv文件中讀入數據&#xff0c;這相當于是對csv這種類型的數據的操作。那么接下來&#xff0c;我們一起看看&#xff0c;如何寫Spark程序來操作mysql數據庫。先來給大家介紹一下我們這節課的主要學習內容&#xff1a; &#xff08;1&#xff09;安裝…

語言學中的對象語言與元語言 | 概念 / 區別 / 實例分析

注&#xff1a;英文引文&#xff0c;機翻未校。 語言學中的“對象語言”和“元語言” 劉福長 現代外語 1989年第3期&#xff08;總第45期&#xff09; 在閱讀語言學著作時&#xff0c;我們有時會遇到這樣兩個術語&#xff1a;對象語言&#xff08;object language&#xff0…