文章出處

用戶反饋

@消失的鍵盤 在論壇反饋了一個問題,在 AppBoxMvc 中的 Title 模型中,如果將 Name 屬性改名為小寫的 name 屬性,就會報錯:

因為這是一個 ASP.NET MVC 的項目,而這個屬性是通過 TextBoxFor 渲染到頁面上的,因此 name 會生成為 DOM 節點的 id 屬性:

F.SimpleForm()
                .ID("SimpleForm1")
                .ShowBorder(false)
                .ShowHeader(false)
                .BodyPadding(10)
                .Items(
                    F.TextBoxFor(m => m.name),
                    F.TextAreaFor(m => m.Remark)
                )

 

 

 

按道理說這也沒什么,雖然有點別扭,但是也沒有規定說name字符串不能作為id屬性的值。

并且從另一個方面講,name 也不是 JavaScript 的關鍵字,不可能沖突阿。

 

分析問題

還是從代碼入手,經過簡單的調試,發現 id=name 的這個文本輸入框對象居然找不到,而這個對象是保存在 F.ui 上面的。

首先我們看下 F.ui 的定義:

F.ui = function(item) {
    var itemType = F.getType(item.type || 'component');
    return new itemType(item);
};

 

為了方便用戶書寫代碼,FineUIMvc中 F.ui 其實有兩個用途:

1. 用作函數:創建控件,可以在JS中通過 F.ui 來創建一個控件:

F.ui({
        type: 'button', renderTo: document.body, text: '按鈕', id:'button1',
        listeners: {
                click: function (event) {
                        F.alert('你點擊了按鈕');
                }
        }
});

 

2. 用作對象:保存控件,可以在JS中通過 F.ui 來引用一個控件(比如上面創建的按鈕):

F.ui.button1

 

這樣一分析問題就來了,因為本身JS函數是有屬性的,這里由于 F.ui 是個匿名函數,所以 F.ui.name == '' (這個函數的 name 屬性為空字符串)

對于一個普通的函數,這個name屬性就是函數名稱,如下所示:

function test1() { }
console.log(test1.name)  // "test1"

 

其實JavaScript 函數不僅有 name 屬性,還是 length , caller, arguments, toString .... 等很多屬性,在Chrome的調試工具中可以方便的查看:

 

所以,當我們試圖將名為 name 的文本輸入框對象保存到 F.ui 上時,其實是不成功的,此時 F.ui.name 依然為空字符串。

 

解決問題

由于 F.ui 的兩個作用已經被網友所熟知,并且已經應用到很多項目中了,不能因為幾個特殊屬性的沖突就廢棄這種做法。那么怎么規避這個問題呢?

我們使用了一個內部變量來保存頁面上的控件實例:

F._fjs_objects = {};

 

同時為了兼容之前的代碼,F.ui 函數仍然用來保存控件實例,只不過在保存之前要先進行判斷,如果傳入的名稱是函數屬性名的話,就不要保存:

function nameIsPropertyOfFunction(name) {
    return $.inArray(name, ['arguments', 'caller', 'length', 'name']) >=0 || $.isFunction(F.ui[name]);
}

F._fjs_addToFObjects = function(objId, obj) {
    F._fjs_objects[objId] = obj;
    
    if(!nameIsPropertyOfFunction(objId)) {
        F.ui[objId] = obj;
    }
};

 

優化后,之前的所有代碼都不用改動,你仍然可以通過兩種方式獲取控件實例:

1. F('controlid')
2. F.ui.controlid

 

而對于非常特殊的情況,控件ID為 name, length, toString (當然我們極力不推薦你用這樣的名稱來命名控件ID!!)時,頁面也不會出錯,只不過你不能再通過F.ui.name 來獲取控件了,只能通過 F('name') 來獲取控件對象。

 


文章列表


不含病毒。www.avast.com
arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()