首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計疑難解答

JavaScript 跨 Frame 操作 DOM:父頁面動態向 iframe 子頁面插入 Table 行的完整實現

     編輯:程式設計疑難解答

在傳統 `frameset`/`iframe` 架構中,父頁面按鈕點擊觸發子頁面 `table` 動態增刪行是常見需求。本文提供基於原生 JS 的跨文檔 DOM 操作完整方案,涵蓋跨域限制、生命週期同步、性能優化關鍵點。

核心原理:`contentWindow` 橋接跨文檔上下文

`iframe` 元素的 `contentWindow` 屬性返回**子頁面的 `window` 物件**,透過它可訪問子頁面的 `document`、全域變數、函式。**前提:同源策略 (協議/域名/端口一致) 或配置 `document.domain` 放寬子域限制。**

完整代碼實現 (同源場景)

父頁面 `parent.html`

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>父頁面</title>
</head>
<body>
    <iframe id="childFrame" src="child.html" width="100%" height="400"></iframe>
    <br>
    <button onclick="addRowToChild()">向子頁面添加行</button>
    <button onclick="clearChildTable()">清空子頁面表格</button>

    <script>
    function getChildDoc() {
        const iframe = document.getElementById('childFrame');
        // 關鍵:等待 iframe 加載完成
        if (!iframe.contentWindow || !iframe.contentWindow.document) {
            alert('子頁面尚未加載完成');
            return null;
        }
        return iframe.contentWindow.document;
    }

    function addRowToChild() {
        const doc = getChildDoc();
        if (!doc) return;
        
        const table = doc.getElementById('dataTable');
        if (!table) { alert('子頁面未找到 dataTable'); return; }
        
        const row = table.insertRow(-1); // -1 追加到末尾
        const now = Date.now();
        // 插入單元格並設置內容
        row.insertCell(0).textContent = 'ID-' + now;
        row.insertCell(1).textContent = '動態數據-' + now;
        row.insertCell(2).textContent = new Date().toLocaleTimeString();
    }

    function clearChildTable() {
        const doc = getChildDoc();
        if (!doc) return;
        const table = doc.getElementById('dataTable');
        if (table) {
            // 保留表頭 (rows[0]),刪除數據行
            while (table.rows.length > 1) table.deleteRow(1);
        }
    }
    </script>
</body>
</html>

子頁面 `child.html`

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>子頁面</title>
</head>
<body>
    <h3>子頁面數據表格</h3>
    <table id="dataTable" border="1" style="border-collapse:collapse; width:100%;">
        <thead>
            <tr style="background:#f0f0f0;">
                <th>ID</th><th>內容</th><th>時間</th>
            </tr>
        </thead>
        <tbody></tbody>
    </table>
</body>
</html>

關鍵技術點詳解

點說明最佳實踐
獲取子文檔`iframe.contentWindow.document`封裝 `getChildDoc()` 統一做空檢查、加載狀態判斷
插入行`table.insertRow(index)`索引 `-1` 追加末尾;`0` 插入表頭後;返回 `HTMLTableRowElement`
插入儲存格`row.insertCell(index)`返回 `HTMLTableCellElement`,用 `textContent` 設置文本 (防 XSS)
刪除行`table.deleteRow(index)`反向循環刪除避免索引偏移:`for(let i=rows.length-1; i>0; i--) table.deleteRow(i)`
性能優化大量行操作構建 `DocumentFragment` 或字串 `innerHTML` 批量寫入,避免頻繁重排
跨域處理不同域/端口**不可直接操作 DOM**。需用 `postMessage` 通信,子頁面監聽 `message` 事件自行操作 DOM

跨域場景:`postMessage` 解耦方案

父頁面發送指令

const iframe = document.getElementById('childFrame');
iframe.contentWindow.postMessage({ 
    type: 'ADD_ROW', 
    payload: { id: 'ID-' + Date.now(), content: '跨域數據' } 
}, 'https://child-domain.com'); // 指定目標源,安全

子頁面監聽執行

window.addEventListener('message', (event) => {
    // 安全驗證來源
    if (event.origin !== 'https://parent-domain.com') return;
    if (event.data.type === 'ADD_ROW') {
        const { id, content } = event.data.payload;
        const row = document.getElementById('dataTable').insertRow(-1);
        row.insertCell(0).textContent = id;
        row.insertCell(1).textContent = content;
        row.insertCell(2).textContent = new Date().toLocaleTimeString();
    }
});

總結

**同源用 `contentWindow.document` 直操作,跨域用 `postMessage` 解耦通信。** 封裝獲取子文檔邏輯、統一異常處理、注意大量操作性能優化,即可構建穩健的跨 Frame 交互系統。現代項目建議優先考慮 **單頁應用 (SPA) + 組件化** 替代 Frame 架構,從根本上消除跨文檔協作複雜度。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved