1. 程式人生 > >利用layer實現MVC頁面數據互交提示彈框

利用layer實現MVC頁面數據互交提示彈框

++ 拼接 script isnull you -i 控制 tro ati

需求說明:

  一個表單頁面,點擊提交之後,進入後臺進行一系列數據交互,然後將交互信息返回至頁面中,並以彈框形式展示

應用場景:

  添加、修改、刪除數據後,返回數據操作是否成功,以及一些其他信息

前期準備:

  • 一個MVC項目
  • jquery-3.2.1.js,下載地址:右鍵另存為
  • layui-v2.1.5.zip,官網:http://www.layui.com/,使用方法請查看文檔,非常詳實

實現過程:

  首先,來一段最原始簡單的HTML和後臺代碼,請忽略CSS

 1 <html>
 2 <head>
 3     <title>
Default</title> 4 <!-- CSS文件引用 --> 5 <link href="/Content/Script/Plug/layui/css/layui.css" rel="stylesheet"> 6 </head> 7 <body> 8 9 <form action="/Home/Default" method="post" class="layui-form" style="width:80%;margin:0px auto;"> 10 <fieldset
> 11 <legend>表單</legend> 12 <!-- 輸入框 --> 13 <div class="layui-form-item"> 14 <label class="layui-form-label">輸入框</label> 15 <div class="layui-input-block"> 16 <
input type="text" name="title" placeholder="請輸入文字" class="layui-input"> 17 </div> 18 </div> 19 <!-- 提交按扭 --> 20 <div class="layui-form-item"> 21 <div class="layui-input-block"> 22 <input type="submit" class="layui-btn layui-btn-block"> 23 </div> 24 </div> 25 26 </fieldset> 27 </form> 28 <!-- JS文件引用 --> 29 <script src="/Content/Script/jquery-3.2.1.min.js"></script> 30 <script src="/Content/Script/Plug/layui/layui.all.js"></script> 31 32 </body> 33 </html>

效果如下(圖1):

技術分享

緊接著,是一段簡單的後臺代碼:

 1         public ActionResult Default() {
 2 
 3             return View();
 4         }
 5 
 6         [HttpPost]
 7         public ActionResult Default(string title) {
 8 
 9             return View();
10         }

代碼的執行過程是這樣的,

首先進入第一個Defult()方法,簡稱Get方法,展示頁面

在頁面中,點擊表單的提交按鈕,會進入第二個Gefult()方法,簡稱Post方法,進行數據處理,然後返回頁面

Get方法可以暫時忽略,它和返回彈框信息並沒有什麽關系,我們主要是對Post方法進行改造

要實現彈框效果,其實很簡單,略微改造就OK:

1         [HttpPost]
2         public ActionResult Default(string title) {
3 
4             return Content("<script>alert(" + title + ")</script >");
5         }

但這樣的效果非常不友好,非常難看不說,每個瀏覽器alert出來的彈框樣式都不一致,而且,還有這樣那樣的bug,效果如圖(圖2):

技術分享

根據layui的文檔,layer.msg("msg");執行的彈框還是非常不錯的,那我們就將alert修改為layer.msg();:

1         [HttpPost]
2         public ActionResult Default(string title) {
3 
4             return Content("<script>layer.msg(" + title + ")</script >");
5         }

然後,執行就炸毛了,彈框沒有出現,頁面也是一片空白:

技術分享

可以看到,拼接出來的script代碼並沒有問題,然而控制臺卻報錯:Default:1 Uncaught ReferenceError: layer is not defined,沒找到layer對象

技術分享

這是什麽原因呢??再看當前頁面的HTML:

技術分享

只有一些最基本的標簽,以及head裏面一個孤零零的script代碼,這樣錯誤就很明顯了,

layer.msg();這個方法是要依賴於layui.js的,現在還沒有引用文件,自然會報錯,

那麽,問題又來了,為什麽返回的視圖只有一段script代碼呢??

仔細觀察,不難發現,比較原始代碼和當前代碼,最大的不同是return 的內容不一樣了,

原始代碼:return View();// 返回當前視圖對應的html代碼

當前代碼:return Content("");// 返回傳入的字符串

現在問題就很明了了,

如果我要返回頁面的話,肯定是要返回View()的,那裏面有需要的各種文件的引用,

  然後在返回View();的情況下,返回字符串,如果不考慮使用ViewBag,因為總感覺用那個的非常不方便,那麽我們只能使用View("Msg");來返回信息

  這樣的話,如果我要對頁面返回一個實例對象,就又呵呵了,所以,使用View();返回的方法不作考慮

那麽就只能使用Content();方法返回信息了,

  其實頁面信息不顯示的問題還是很好解決的,可以這樣返回:return Content("<script>location.htrf=‘/Home/Default‘;</script>");

  利用js進行頁面跳轉,就會跳轉至Get方法,而Get方法是return View();所以頁面信息顯示的問題解決了,

  但是,如何彈框呢?

  如果將彈框代碼layer.msg("Msg");寫在跳轉之前,那個時候還沒有引用文件,所以肯定是報錯,無法彈框的,說不定還會因為報錯導致跳轉代碼無法執行,所以pass,

  若寫在跳轉之後,嗯,頁面已經跳轉了,你這個彈框先不說能不能彈出來,哪怕彈出來也看不到了,畢竟已經跳轉到另外一個頁面了,

  很好,現在局面又陷入了僵局,,,

  想想,現在我們應該怎麽處理???

  能不能讓跳轉和彈框分開,既然它們相看兩厭,那就讓它們互不相關,互不影響怎麽樣,你跳你的頁面,我彈我的框,咱們畫好三八線

  那麽,這根三八線怎麽畫,用什麽畫??答案是iframe

  新建一個頁面Index,該引用的引用好,然後將頁面Default嵌入到iframe中,

  這樣跳轉的話,只是iframe跳轉,而我的彈框,完全可以跳出Default文件引用的約束,利用父窗Index的引用實現

具體實現過程如下:

新建一個父窗的後臺和HTML:

1         public ActionResult Index() {
2 
3             return View();
4         }
 1 @{
 2     Layout = null;
 3 }
 4 
 5 <!DOCTYPE html>
 6 
 7 <html>
 8 <head>
 9     <meta name="viewport" content="width=device-width" />
10     <title>@ViewBag.Title</title>
11     <!-- CSS文件引用 -->
12     <link href="~/Content/Script/Plug/layui/css/layui.css" rel="stylesheet" />
13     <!-- JS文件引用 -->
14     <script src="~/Content/Script/jquery-3.2.1.min.js"></script>
15     <script src="~/Content/Script/Plug/layui/layui.all.js"></script>
16 </head>
17 <body>
18     <script>
19 
20         $(function () {
21             // 創建iframe
22             layer.open({
23             type: 2,// 2為iframe
24             title: false,// 去掉標題
25             closeBtn: 0,// 去掉關閉按鈕
26             shade: false,// 關閉遮罩層
27             maxmin: false, // 關閉最大化最小化按鈕
28             area: [100%, 100%],// 直接最大化,充當Index內容
29             anim:5,// 漸變出現
30             content: @Url.Action("Default", "Home")// iframe鏈接地址
31             });
32         });
33         
34     </script>
35 </body>
36 </html>

這樣運行出來的效果和圖1是一毛一樣的,但是仔細觀察,會發現它們的路徑是不一樣的,

圖1的路徑是http://localhost:50082/Home/Default,現在運行出來的路徑是http://localhost:50082/Home/Index

技術分享

這時候,就已經將Default頁面用iframe嵌入Index頁面了,而且毫無違和感,修改anim屬性,還能有一些意外的進入動畫效果,相當不錯來著,,

接下來就是返回消息彈框了,我已經封裝好了,直接貼代碼:

 1         [HttpPost]
 2         public ActionResult Default(string title) {
 3             return Content(LayerMsg(title));
 4         }
 5 
 6         /// <summary>
 7         /// 返回頁面消息彈框
 8         /// </summary>
 9         /// <param name="msg">消息內容</param>
10         /// <param name="url">跳轉鏈接</param>
11         /// <param name="icon">消息類型,[-1,6]</param>
12         /// <param name="anim">消息動畫,[-1,6]</param>
13         /// <param name="time">出現時間,(單位:ms)</param>
14         /// <returns></returns>
15         public string LayerMsg(string msg, string url = "", int? icon=null, int anim = -1, int time = 2000) {
16 
17             // 鏈接,若為空,返回當前頁面
18             if (string.IsNullOrEmpty(url))
19                 url = HttpContext.Current.Request.RawUrl;
20             // 動畫
21             anim = anim % 7;
22             if (anim < 0)
23                 anim = new Random().Next(0, 7);
24 
25             StringBuilder str = new StringBuilder();
26 
27             object[] key = { "anim", "time", "icon" };
28             object[] val = {  anim, time, icon };
29 
30             str.Append("<script>");
31             str.Append("location.href=‘" + url + "‘; ");
32             // 由於要返回的是父窗的方法,所以加上‘parent.‘
33             str.Append("parent.layer.msg(‘" + msg + "‘,{");
34             str.Append(MosaicKeyVal(key, val) + "});");
35             str.Append("</script>");
36 
37             return str.ToString();
38         }
39 
40         /// <summary>
41         /// 拼接鍵值對
42         /// </summary>
43         /// <param name="key"></param>
44         /// <param name="val"></param>
45         /// <returns></returns>
46         public string MosaicKeyVal(object[] key, object[] val) {
47             if (key.Length != val.Length)
48                 return "";
49 
50             StringBuilder str = new StringBuilder();
51             for (int i = 0; i < key.Length; i++) {
52                 if (string.IsNullOrEmpty(key[i] + ""))
53                     continue;
54                 if (string.IsNullOrEmpty(val[i] + ""))
55                     continue;
56                 // 添加逗號
57                 if (str.Length > 0)
58                     str.Append(",");
59                 // 添加鍵值對
60                 str.Append(string.Format(" ‘{0}‘:‘{1}‘  ", key[i].ToString(), val[i].ToString()));
61             }
62             return str.ToString(); ;
63         }

效果以及返回的script代碼如圖:

技術分享

至此就大功告成了,那幾個參數大家可以看著傳過去玩玩,有驚喜的,

尚待思考:

  有人對這個方法提出了一個需求,就是點擊提交之後,不僅可以彈框,還要保證文本框裏面的信息不會丟失,

  對於這個需求我表示相當無奈,除非使用ViewBag,還沒有比較好的解決方法,或許是我的思路還不夠開闊吧,

  那貨說可以監聽所有的onsubmit事件,將submit提交更改為ajax異步,這樣數據就能保留下來了,而且,彈框也更簡單了,直接使用success事件就好,

  但是這樣總感覺哪裏不對勁,也嘗試這樣寫過,確實能夠實現最開始的需求,不過會順帶出一大堆的問題,

  比如說,我加入表單驗證插件Validform之後,用ajax提交,驗證插件就完全失效了,這還只是最初步的實驗,估計那些看得見的看不見的問題會更多,

  哪位大佬有更好的解決思路,,歡迎指點

利用layer實現MVC頁面數據互交提示彈框