1

我在单个页面上构建了 RIA。我正在使用 Dojo 1.7.2。该页面包含大约 200 个 dijit/NumberSpinner 和一些 TabContainers 和 TitlePanes。当然,这在所有浏览器中都能完美运行,客户公司使用的 Internet Explorer 8 除外。

在所有浏览器中,整个页面的解析需要几秒钟,在 IE8 中是 2 分钟,我通过使用以下提示将其缩短到 40 秒:

  • 使用自定义构建
  • 以编程方式而不是声明方式创建小部件
  • 仅在显示小部件时对其进行解析。(这不会加快解析速度,只会让用户在使用应用程序时等待更多时间,而不是之前。)
  • 用 NumberSpinners 代替 NumberTextBox(这将解析时间减少了一半!)

还有其他提示吗?我可以尝试重用 NumberSpinner 并在 div 可见时将它们扔掉,但这需要我的应用程序进行相当大的重写。

4

1 回答 1

2

您面临的情况是,在 DOM 中以编程方式创建了非常多的节点。IE 在这方面表现不佳,受到 javascript 引擎的阻碍。咳咳?!

您的目标是尽可能多地预先定义,而不是在运行时覆盖它。我的意思是在 data-dojo-props / 构造参数中设置参数。这尤其适用于 onClick 处理程序等。你可以通过这样做来实现这一点:

var MyConstruct = dojo.define("foo.MyConstruct", [ /* inheritance */ dijit.form.ValidationTextBox ], function() {
      // instead of setting properties during construct, preset those which are possible
      constraints: { min: 0, max: 100 },
      postMixInArguments: function() {
          this.inherited(arguments);    // call widget first
          if(this.constructParameter) ; // act on it
      },
      // implement any overrides you otherwise would need
      // and for minimal runtime overhead, redefine the private version, like _onBlur
      // copy the source and change what you need
      onBlur: function () {
          // an event override example
      }
});

但; 为什么 NumberSpinners > NumberTextBoxes 减少了 50%?这就是为什么:

模板文本框

<div class="dijit dijitReset dijitInline dijitLeft" id="widget_${id}" role="presentation"
    ><div class="dijitReset dijitInputField dijitInputContainer"
        ><input class="dijitReset dijitInputInner" data-dojo-attach-point='textbox,focusNode' autocomplete="off"
            ${!nameAttrSetting} type='${type}'
    /></div
></div>

模板微调器

<div class="dijit dijitReset dijitInline dijitLeft"
    id="widget_${id}" role="presentation"
    ><div class="dijitReset dijitButtonNode dijitSpinnerButtonContainer"
        ><input class="dijitReset dijitInputField dijitSpinnerButtonInner" type="text" tabIndex="-1" readonly="readonly" role="presentation"
        /><div class="dijitReset dijitLeft dijitButtonNode dijitArrowButton dijitUpArrowButton"
            data-dojo-attach-point="upArrowNode"
            ><div class="dijitArrowButtonInner"
                ><input class="dijitReset dijitInputField" value="&#9650;" type="text" tabIndex="-1" readonly="readonly" role="presentation"
                    ${_buttonInputDisabled}
            /></div
        ></div
        ><div class="dijitReset dijitLeft dijitButtonNode dijitArrowButton dijitDownArrowButton"
            data-dojo-attach-point="downArrowNode"
            ><div class="dijitArrowButtonInner"
                ><input class="dijitReset dijitInputField" value="&#9660;" type="text" tabIndex="-1" readonly="readonly" role="presentation"
                    ${_buttonInputDisabled}
            /></div
        ></div
    ></div
    ><div class='dijitReset dijitValidationContainer'
        ><input class="dijitReset dijitInputField dijitValidationIcon dijitValidationInner" value="&#935;" type="text" tabIndex="-1" readonly="readonly" role="presentation"
    /></div
    ><div class="dijitReset dijitInputField dijitInputContainer"
        ><input class='dijitReset dijitInputInner' data-dojo-attach-point="textbox,focusNode" type="${type}" data-dojo-attach-event="onkeypress:_onKeyPress"
            role="spinbutton" autocomplete="off" ${!nameAttrSetting}
    /></div
></div>

TextBox 模板没有太多可以优化它的地方,只有入口点是 ${type} 参数,该参数是通过 _getTypeAttr 使用常规 exp 替换设置的。在 postMixInProps 中(在 _TemplatedMixin 运行并生成 DOM 之前),即使指定了其他任何内容,该值也会被覆盖为“文本”。尽管——不知道这会如何暗示——人们可能想要拿走focusNode + FocusMixin,但我不会去讨论这个。

在 dijit/form/MappedTextBox 中有一些奇怪的处理(它创建了一个隐藏的<input>,包含 'true' 值,请参阅http://bugs.dojotoolkit.org/ticket/8660。这已经在 'this.name 上放置了一个正则表达式替换' 来解决问题 - 在您的输入字段中省略 name 属性会解决这个问题(如果可能,请使用 Id 代替)。

模板验证文本框

使用 NumberTextBox 的主要原因是范围限制,对吧?为了加载该特定模块,完成了许多混合 - 但基本上它们基于 ValidationTextBox。这提供了一种.validate功能并在需要时显示消息。上面关于删除 focusmixin 的注释将使消息传递停止工作,因为它们作用于 onBlur 事件。

如果您要使用 ValidationTextBox 而不是 NumberTextBox 并通过自定义功能实现范围检查,我相信它会产生奇迹。大量的 eval 代码在验证文本框之上运行以使其成为数字文本框 - 其中一些可能在您的情况下是开销。

<div class="dijit dijitReset dijitInline dijitLeft"
    id="widget_${id}" role="presentation"
    ><div class='dijitReset dijitValidationContainer'
        ><input class="dijitReset dijitInputField dijitValidationIcon dijitValidationInner" value="&#935; " type="text" tabIndex="-1" readonly="readonly" role="presentation"
    /></div
    ><div class="dijitReset dijitInputField dijitInputContainer"
        ><input class="dijitReset dijitInputInner" data-dojo-attach-point='textbox,focusNode' autocomplete="off"
            ${!nameAttrSetting} type='${type}'
    /></div
></div>

验证的示例覆盖:

dijit.byId("validationTextBoxNodeId").validator = function(value, constraints){

    // Check that email has not been used yet.
    if(some-checks){
        return true;
    }else{
        return false;
    }
}
于 2012-06-04T11:48:06.457 回答