網站製作學習誌

記錄學習製作網站的一切

JavaScript 小陷阱 (4) - location.reload()

以前的同事問了我一個問題:

在 A 視窗 (list.asp) 中會用 window.open 開啟子視窗 B (edit.asp) ,然後 B 視窗上的表單資料會 submit 到一支 C 程式 (save.asp) 。

而 當 C 程式做完存檔動作後,在最後面程式碼裡加上了:

1
2
3
4
5
6
7
<script type="text/javascript">
<!--
alert('存檔成功!');
window.opener.location.reload();
window.close();
//-->
</script>

理論上 A 視窗會重新整理,然後子視窗 B 會關掉;但是現在 A 視窗會出現以下訊息 (IE) :

或是在 Firefox 中出現:

這個問題只看字面的話,說實在的有點難懂,我想我用以下程式來說明好了:

註:這裡舉的例子比較簡單,沒有考慮到實用上的完整性,大家在實作時請自行小心。

list.asp

1
2
3
4
5
6
7
8
9
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=big5" />
<title>列表頁</title>
</head>
<body>
<a href="edit.asp" onclick="window.open('edit.asp', 'b', 'width=100,height=100'); return false;">測試</a>
</body>
</html>

edit.asp

1
2
3
4
5
6
7
8
9
10
11
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=big5" />
<title>表單</title>
</head>
<body>
<form id="form1" name="form1" method="post" action="save.asp">
<input type="submit" name="Submit" value="送出" />
</form>
</body>
</html>

save.asp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=big5" />
<title>處理頁</title>
</head>
<body>
<script type="text/javascript">
<!--
alert('存檔成功.');
<strong>window.opener.location.reload();</strong>
window.close();
//-->
</script>
</body>
</html>

如果大家直接執行 list.asp 並按下「測試」連結,在出現表單視窗後按下「送出」,可能會發現沒有我朋友所說的問題。

那為什麼我朋友會遇到呢?

其實在 Firefox 的訊息視窗裡可以看出一些端倪,原因就在 POSTDATA !怎麼說呢?如果我把 list.asp 改成以下這樣:

1
2
3
4
5
6
7
8
9
10
11
12
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=big5" />
<title>列表頁</title>
</head>
<body>
<a href="edit.asp" onclick="window.open('edit.asp', 'b', 'width=100,height=100'); return false;">測試</a>
<strong><form id="form1" name="form1" method="post" action="list.asp">
<input type="submit" name="Submit" value="送出" />
</form></strong>
</body>
</html>

這時我們先按下 list.asp 的「送出」,也就是說 list.asp 會把資料 POST 給自己 (當然如果是從別的頁面 POST 過來的也是一樣) ,然後再執行一次剛剛的表單測試:

這時畫面就會跳出:

也就是說 list.asp 必須重新把 POST 的資料再次載入。

那麼如何解決呢?兩個方法可用:

  1. list.asp 的表單改用 GET 來傳遞參數。
  2. 非得用 POST 的話,那 save.asp 就不要用 location.reload() ,而改用 location.replace() 。

location.replace() 怎麼用呢?範例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=big5" />
<title>處理頁</title>
</head>
<body>
<script type="text/javascript">
<!--
alert('存檔成功.');
<strong>window.opener.location.replace('list.asp');</strong>
window.close();
//-->
</script>
</body>
</html>

這樣 list.asp 就會被重新讀取了。

Comments