個人前端架構彙總css
初學者推薦文章:JavaScript祕密花園html
如今頁面的內容大都是分塊的,常見的以下結構:前端
<html> <head></head> <body> <header> </header> <main> <left> </left> <content> </content> <right> </right> <footer> </footer> </main> </body> </html>
其中 left ,right,content,footer 是使用(或部分使用)異步加載的方式來加載遠程頁面的。jquery
若是left是菜單, content是一個帶有選項卡的多頁面結構,不少狀況下,content下的每一個頁面須要一個 iframe 來隔離每一個頁面,避免 A 頁面 和 B 頁面控件ID和 Js 方法名重複。git
加載iframe 1會形成一些性能的浪費,2會增長客戶端瀏覽器的壓力,由於Dom結構很龐大,3給各個選項卡頁面通訊、頁面間帶來麻煩。github
我須要解決的就是不使用 iframe 而加載不少頁面,又不會產生衝突。ajax
給Dom元素添加做用域,做用域能夠看做是頁面的Dom大容器,它也是一棵樹,根節點是 html。做用域結構是下面的結構:瀏覽器
html
left
content
right
footer
jv.page(dom) 方法返回 dom元素所在的做用域。爲了簡化操做,能夠在 click 等帶有event,能夠找到事件觸發源的方法裏,使用 jv.page() 獲得當前做用域。服務器
$(selector, jv.page(dom)) 方法對DOM元素進行選擇。架構
普通方法定義是不行的,像這樣:
function test(){}
這種定義方法是公開到 window 下的。相似於:
window.test = function(){}
若是A頁面和B頁面都使用同一個 test 方法,則 B頁面的 test 方法會覆蓋 A頁面的 test方法。
咱們要改造的效果是:把方法定義到各個做用域上去。核心是做用域!
新的定義方法:
this.test = function(){}
this 不是常量,它不必定是 window,它表示該Dom容器作爲做用域的 MyPageObject 對象,它和做用域DOM容器是一一對應的,但不是做用域DOM容器。它一樣是一棵樹。這棵樹的根是 window ,子數據在 window.SubPages 中存儲
咱們在加載遠程異步加載頁面的時候,須要手動指定 this 對象 。核心代碼:
$.extend.LoadView = function (p) { //清空當前節點的內容。 //Ajax獲取遠程內容。在回調中處理HTML //1. 使用過濾器過濾出要顯示的部分。 //2. 把 Js 分爲兩部分: 最早執行的JS,和 最後執行的JS ,中間填充 DOM對象(包含Css) //3. 運行最早執行的JS,(若是 script 標籤有 init 屬性,則認爲它是須要最早加載執行的JS ) 使用 call 或 apply 改變 Js 的 this當前上下文。 //4. 填充DOM //5. 運行最後執行的JS,使用 call 或 apply 改變 Js 的 this 當前上下文。 }
這樣定義的頁面,這個頁面能夠獨立運行,也能夠被LoadView屢次加載運行。
this 是當前加載頁面部分的做用域對象。因爲this易變,咱們引入了 me 對象。me是在後臺自動加入的。上面定義方法的方式也能夠這樣:
me.test=function(){}
若是在頁面上使用 this.test = function(){} 定義了方法,如何使用呢。以下:
<script> this.test = function(){ var doer = jv.getDoer(); alert(doer.innerHTML); //顯示肯定 } </script> <body> <button onclick="jv.me(event).test(event)">肯定</button> </body>
其中 jv.me(event) 方法找出 做用域的 MyPageObject 對象,即方法中定義的 this 對象。 傳入 event 對於瀏覽器兼容性來講,是有必要的。
jv.getDoer(event) 方法會遞歸查找方法參數中的 event 對象,找出觸發事件的源。因此在調用方法時,參數最後要傳遞 event
jv.getDoer按如下優先級進行確認:
var ret = null; if (evt.srcElement) { ret = evt.srcElement; } else if (evt.target) { ret = evt.target; } else if (evt.originalEvent === true) { ret = evt.target; } else if (evt.originalEvent == "me") { ret = evt.target; } else if (evt.originalEvent == "func") { ret = evt.target(); } else if (evt.originalEvent == "jquery") { ret = $(evt.target)[0]; } else if (evt.fromElement) { ret = evt.fromElement; } else if (evt.currentTarget) { ret = evt.currentTarget; }
若是對父元素綁定了事件,使用子元素觸發了click,則:
currentTarget 表示父元素; target表示子元素。
做用域的 MyPageObject 對象 簡稱 me 對象,由於它是經過 jv.me() 獲得的。
每一個頁面的最後,都會調用一個Js方法:jv.myOnInit(); 來實現頁面的自動化和執行頁面生命週期的各個方法。
jv.myOnInit 會依次執行如下方法
1. 執行 me.Page_PreInit
2. 執行 jv.MyInitOn_PreFith ,系統腳本給最初的容器計算高度
3. 執行 jv.MyInitOn 字典裏的 value 部分。這是系統腳本註冊的自動化部分。
4. 執行 me.Page_Init
5. 執行 me.Page_Render 字典裏的 value 部分,這是頁面腳本本身的自動化部分。
6. 執行 jv.MyInitOn_Fithed,系統腳本在腳本最後,計算容器高度。
7. 執行 me.Page_Inited
其中2,3,6 是系統自動執行的腳本。除去2,3,6,其他的部分,就是頁面能控制的生命週期。
1. Page_PreInit
2. Page_Init, 最經常使用
3. Page_Render 這是字典結構。
4. Page_Inited
1. 自動化初始化時間選擇控件。
引用的第三方時間選擇控件的Api,通常是顯式進行定義,像這樣: $("#id").時間控件方法(格式);如 My97:
$("#date").click(function () { WdatePicker({ $dpPath: jv.Root + "R/My97/", dateFmt: "yyyy-MM-dd" }); });
利用頁面最後會執行 jv.myOnInit 中的 jv.MyInitOn 字典的數據,進行自動化初始化。
jv.MyInitOn["MyDate"] = function (container) { jv.loadJsCss("js", jv.Root + "R/My97/wdatepicker.js"); container = container || jv.page(); $(".MyDate", container).each(function () { var $self = $(this); var format = $self.attr("dtFormat") || 'yyyy-MM-dd'; $self.click(function () { WdatePicker({ $dpPath: jv.Root + "R/My97/", dateFmt: format }); }); if (!$self.val()) return; $self.val($self.val().getDate().toString(format)); }) });
這樣,全部包含 MyDate 的類元素,都會自動註冊 click 事件,顯示時間控件。只須要這樣:
<input class="MyDate"/>
2. 改造默認的Ajax,在請求出錯時,自動彈出信息框。
jv.MyInitOn["InitJQueryAjax"] = function () { $.ajaxSetup({ //請求成功後觸發 success: function (data) { }, //請求失敗遇到異常觸發 error: function (xhr, status, e) { //彈框報錯。 }, //完成請求後觸發。即在success或error觸發後觸發 complete: function (xhr, status) { $(document.body).css("cursor", "default"); }, //發送請求前觸發 beforeSend: function (xhr, opt) { $(document.body).css("cursor", "wait"); } }); };
僅當是GET請求頁面HTML時,爲方便頁面實現以上機制,服務器會對頁面輸出進行如下干涉:
1. script標籤移到最後。
2. 去除重複引用
3. 解析 ~/ 符號
4. 把Mvc服務器定義的變量輸出到前端: me.變量=值;
5. 在最前面生成: jv.Root=""~/"";var me=new MyPageObject();jv.addRequest(me);me.SYSTEMPOWERBUTTON=[];
其中:
jv.addRequest用於分隔頁面做用域
me.SYSTEMPOWERBUTTON 用於定義該頁面的按鈕權限。
6. 給 script 標籤的最前頭,添加: var me=this;
項目部署教程: