回前頁

框架組的階層結構

window 物件釋疑
網頁物件模組中最令人容易搞混的就是 window 物件,表面上它好像指的是 瀏覽器的操作視窗,但實際上不是。加上 frame、iframe、 layer、opener 和 subwindow 等等,不同名稱,不同方式產生,但卻擁有相同內容 和操作方式的網頁物件,真是讓人一團混亂。要指出 window 到底在網頁上代表什麼 ,真是費力而不討好,但如果以操作實用的觀點出發,我們可以為 window 物件下個 定義,那就是 window 是指包住那個網頁的顯示框框,或者說是在瀏覽器中可以獨立 顯示網頁的區域。所以:
frame 的階層關係
就如前段所言,frame 是一個 window ,這個 window 是透過 FRAMESET 標籤把 上層的 window 切割而成的,所以切割出來的 window 和被切割的 window 就形成 一個階層關係。在這階層中彼此的關係是: 當我們明瞭階層中的 window 彼此如何互相呼叫時,就可以在一個 window 中去操作 另一個 window 的動作(視窗如何互相操作及傳遞訊息請參考 子視窗的開啟與關閉)
top 在 frame 階層中的意義
parent、self、frames 的三層,的確就完整的說明了 frame 階層的上下 window 關係,但這三個物件都是相對物件,也就是在一個瀏覽器操作視窗中,因為目前視窗 的不同,而使三個物件是代表那個 window 的參照也就有所不同,但網頁 window 有沒 絕對的 window 物件呢?也就是不管目前 window 是那一個,但這個物件總指著一個 固定的 window ,不會改變的?那就是 top 物件。top 也是一個 window ,它是指 當我們開啟一個瀏覽器操作視窗時,第一個伴隨開啟的那個網頁顯示框(或者稱為網頁 顯示區你比較能理解),它在瀏覽器開啟時產生,瀏覽器關閉時消失,一個瀏覽器中只有 一個,並且在瀏覽器執行中,沒有任何辦法消滅或脫離它。這麼說或許太玄,其實 top 是你平常最常用的一個 window ,當你打開瀏覽器,瀏覽沒有任何 FRAMESET 設定的 網頁時,你就是在使用 top 這個 window,當你第一次載入 FRAMESET 網頁, 首先分割的也是 top 這個 window。所以我們瀏覽一個單一沒有 frame 階層的網頁時 ,self 指的是 top ,parent 指的也是 top ,因為瀏覽器總共只有一個 top window。 但當 frame 階層有兩層時,那麼就下層子網頁來說,self 指的是自己目前使用的 這個 window ,而 parent 等於 top 。但當 frame 有三層時,第三層 window 的 self、parent 和 top 可就個別指向不同的 window 了。最後用最通俗的話來解釋, top 是老祖宗,parent 則是上一代,但如果你的上一代,甚至你自己本身就是開山祖, 那當然就一人兼好幾個身份了。
frame 階層的計算
用一個 FRAMESET 網頁把 window 切成好幾個下層的 window ,就在 frame 階層中多 加了一個階層,這是很簡單的道理,但在實作上卻容易引起一些混淆,譬如:
<!-- 一個 FRAMESET 網頁組成的 frame 階層 // -->
<FRAMESET NAME="all_frame" COLS="30%,*">
    <FRAME NAME="left" SRC="左網頁 URL">
    <FRAMESET NAME="right_frame" ROWS="50%,*">
        <FRAME NAME="right_up" SRC="右上網頁 URL">
        <FRAME NAME="right_dn" SRC="右下網頁 URL">
    </FRAMESET>
</FRAMESET>
這是把一個 window 分成 left、right_up、right_dn 三個 window,你或許看到網頁 上的巢狀結構,而以為這是三層結構(原 window 一層、left,right 兩層、right_up, right_dn 三層),錯了,這只有兩層(原 window 一層、left,right_up,right_dn 二層) 。再看下面個例子:
<!-- 兩個 FRAMESET 網頁組成的 frame 階層 // -->
<!-- 先分左右的 FRAMESET 網頁 // -->
<FRAMESET NAME="all_frame" COLS="30%,*">
    <FRAME NAME="left" SRC="左網頁 URL">
    <FRAME NAME="right" SRC="右邊 Frameset 網頁 URL">
</FRAMESET>

<!-- 被上面一個 FRAMESET 載入的右側 FRAMESET 獨立網頁 // -->
<FRAMESET NAME="right_frame" ROWS="50%,*">
    <FRAME NAME="right_up" SRC="右上網頁 URL">
    <FRAME NAME="right_dn" SRC="右下網頁 URL">
</FRAMESET>
這個例子顯示出的外貌和上一例完全一樣,你或許懷疑舉例目的何在?很簡單, 這個例和上一例貌似而實不同,這例的 frame 階層是三層,也就是原 window 一層、 left,right 兩層、right_up,right_dn 三層。如此差別是有道理的,那就是一個 window 再怎麼分,都只能產生下一層 window ,不可能有下兩層 window,而不管 一個 FRAMESET 中做了幾次的 FRAMESET 巢狀包覆;同樣的一個 FRAMESET 網頁只能 把一個 window 分成幾個 window ,而無法先分一個 window 後,再去分另一個 window;這道理就和老爹老娘再會生,生再多,也只能生出兒子女兒,不可能生出孫兒 孫女是一樣的。而後一例道理就更簡單了,從兒女生出的下一代,當然是孫兒孫女, 決不能生小弟小妹吧(別跟我提亂倫可能,軟體中這種 Bug 是不被允許的。)所以我們 也可以這麼看,一個 FRAMESET 網頁只能為 frame 階層加一個下層,每加一層要多用 一個 FRAMESET 網頁,當然這不是指網頁的外觀顯示,而是指網頁物件的內部組成。
frame 階層對物件參照的影響
前面費那麼多言辭解釋 frame 階層的觀念,目的就是為了這一段的重點。 基本上我們在設計 DHTML 時,如果所有的 Script 只會操作本身 window 的物件, 那麼 frame 階層的結構我們大可不予理會,但如果我們在 frame 階層中做跨 window 的物件操作,那麼搞錯了 frame 階層,可是會引起程式錯誤的。以上面的 兩個不同階層的 FRAMESET 網頁為例,譬如你要在 left frame 中讓 right_dn frame 更改載入的網頁,在兩層 frame 例中你可以這麼做:
/* left frame 網頁的 Code */
/* 更改 right_dn frame 的載入網頁函式 */
function ChangeRightDNURL(url)
{parent.frames.right_dn.location.href=url;}

<!-- 更改 right_dn frame 載入網頁的標籤設定 // -->
<A HREF="#" onclick="ChangeRightDNURL('NewURLString');return false;">
但在三層 frame 例中你則必須把函式改成:
function ChangeRightDNURL(url)
{parent.frames.right.frames.right_dn.location.href=url;}
又如果你要在 right_dn frame 中顯示一個 left frame 的 leftcommon 的變數值, 那麼它們的不同如下:
/* 這是兩層 frame 範例 */
alert(parent.frames.left.leftcommon);

/* 這是三層 frame 範例 */
alert(parent.parent.frames.left.leftcommon);
範例測試
如果你看了半天還是有些糊塗,請按 這裡。測試一下一個 FRAMESET 網頁 構成的 frame 階層,和兩個 FRAMESET 網頁構成的 frame 階層到底有何不同。

回前頁
1