@消失的键盘 在论坛反馈了一个问题,在 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') 来获取控件对象。
来源: http://www.cnblogs.com/sanshi/p/7159885.html