個人前端架構之一--頁面做用域

個人前端架構彙總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;

 

 

項目部署教程:

http://www.cnblogs.com/newsea/p/4781000.html

相關文章
相關標籤/搜索