需求說明:css
一個表單頁面,點擊提交以後,進入後臺進行一系列數據交互,而後將交互信息返回至頁面中,並以彈框形式展現html
應用場景:jquery
添加、修改、刪除數據後,返回數據操做是否成功,以及一些其餘信息ajax
前期準備:瀏覽器
實現過程:dom
首先,來一段最原始簡單的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):post
緊接着,是一段簡單的後臺代碼:動畫
1 public ActionResult Default() { 2 3 return View(); 4 } 5 6 [HttpPost] 7 public ActionResult Default(string title) { 8 9 return View(); 10 }
代碼的執行過程是這樣的,ui
首先進入第一個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提交,驗證插件就徹底失效了,這還只是最初步的實驗,估計那些看得見的看不見的問題會更多,
哪位大佬有更好的解決思路,,歡迎指點