Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Performance 如何避免每次在KnockoutJS中重新绘制整个选项卡?_Performance_Knockout.js_Twitter Bootstrap 3_Redraw - Fatal编程技术网

Performance 如何避免每次在KnockoutJS中重新绘制整个选项卡?

Performance 如何避免每次在KnockoutJS中重新绘制整个选项卡?,performance,knockout.js,twitter-bootstrap-3,redraw,Performance,Knockout.js,Twitter Bootstrap 3,Redraw,在这个使用引导标签的非常基本的例子中,每次我点击一个标签,KnockoutJS都会重新绘制整个标签,有没有办法“保存”标签的状态,这样下次我点击消息时,KO就不必重新绘制整个内容了 绘制大约需要100毫秒。(根据Chromium profiler),fps降至1fps。这让整个事情变得毫无反应 <div> <ul class="nav nav-tabs" role="tablist"> <li role="presentation"><a h

在这个使用引导标签的非常基本的例子中,每次我点击一个标签,KnockoutJS都会重新绘制整个标签,有没有办法“保存”标签的状态,这样下次我点击消息时,KO就不必重新绘制整个内容了

绘制大约需要100毫秒。(根据Chromium profiler),fps降至1fps。这让整个事情变得毫无反应

<div>
  <ul class="nav nav-tabs" role="tablist">
    <li role="presentation"><a href="#profile" aria-controls="profile" role="tab" data-toggle="tab">Profile</a></li>
    <li role="presentation"><a href="#messages" aria-controls="messages" role="tab" data-toggle="tab">Messages</a></li>
  </ul>

  <div class="tab-content">
    <div role="tabpanel" class="tab-pane active" id="tab_storage" data-bind="with: BuildingsVM">

    <h2 data-bind="i18next: 'AllOurStorage'"></h2>
    <div class="row" data-bind="foreach: buildingsByType['RawStorage']">
      <div data-bind="template: { name: 'tpl_building' }"></div>
    </div>
    <div class="row" data-bind="foreach: buildingsByType['RefinedStorage']">
      <div data-bind="template: { name: 'tpl_building' }"></div>
    </div>

  </div>
    <div role="tabpanel" class="tab-pane" id="messages" data-bind="messages">
      <div data-bind="foreach: message">
        <span data-bind="text: title"></span>
      </div>
    </div>
  </div>
</div>
编辑: 使用引导JS库切换选项卡

 $("#MenuTab").on('click','a', function(e) {
   e.preventDefault();
   var id = $(this).attr('href');
   $(this).tab("show");
 });
建筑“卡”的模板:

<script type="text/html" id="tpl_building">
  <div class="col-xs-10 col-sm-6 col-md-3">
    <div class="card card-raised">
      <div class="card-header"><h3 data-bind="text: buildingName"></h3> </div>
      <div class="card-content">

        <div class="row" data-bind="if: (buildingType == 'RawStorage' || buildingType == 'RefinedStorage')">
          <div class="col-xs-4">
            Usage: <span data-bind="text: getOccupyingSpace"></span> / <span data-bind="text: TotalCapacity"></span>
          </div>
          <div class="col-xs-8">
            <span data-bind="meter: {value: getOccupyingSpace, max: TotalCapacity}"></span>
          </div>
        </div>



        <div class="row">
        <!-- ko foreach: Ressources -->
        <div class="col-md-6" data-bind="if: $parent.TotalCapacity">
          <span data-bind="text: Name"></span> <span data-bind="text: Qte"></span> (<span class="small" data-bind="text: getOccupyingSpace"></span>)
          <!-- ko if: ProductionRate() -->
          <span data-bind="text: ProductionRate()"></span>/s
          <!-- /ko -->
        </div>
        <div class="col-md-6" data-bind="if: ProductionRate">
          <span data-bind="text: Name"></span> <span data-bind="text: getProductionRatePerSecond()"></span>/s (1 every <span data-bind="text: ProductionRate()/1000"></span> sec)
        </div>
        <!-- /ko -->
        </div>


      </div>
      <div class="card-footer">
        <!-- ko if: initialConstructionGoing -->
        <i class="fa fa-exclamation-triangle icon-gradient-warning" class="ko-popover"
  data-bind="popover: initialConstructionGoing, popoverOptions: { title: i18nextko.t('UnderConstruction_potitle') }" ></i>
  <span data-bind="i18next: 'UnderConstruction'"></span> <span data-bind="text: getBuildProgress"></span>
  <span data-bind="meter: {p: getBuildProgress, onComplete: 'remove'}"></span>
  <span data-bind="WorkersAssigned().length"></span>/<span data-bind="WorkersBuild"></span>
        <!-- /ko -->

      </div>
    </div>
  </div>
</script>
还修改了原始选项卡内容代码以反映真实代码(使用模板)

我本来会制作一个JSFIDLE,但由于一些模糊的原因,它似乎不能正常工作(新的路由器固件可能是问题所在,阻塞CDN)

为了更好地理解上下文,您可以看看我的另一个问题:


查看控制台中的DOM树,即使选项卡未处于活动状态,所有元素仍然存在-可能是其他原因造成了延迟。

是否使用自定义绑定?如何切换哪个选项卡处于活动状态?哦,哈哈,是的,这可能会有所帮助,更新了问题。哇,在调查了探查器中的所有调用之后,似乎边框图像花了太多时间才光栅化。删除该类属性后,chromium的渲染速度似乎更快,并且没有200毫秒的显示时间(平均只有40毫秒)-不知道CSS会对性能产生如此大的影响!
<script type="text/html" id="tpl_building">
  <div class="col-xs-10 col-sm-6 col-md-3">
    <div class="card card-raised">
      <div class="card-header"><h3 data-bind="text: buildingName"></h3> </div>
      <div class="card-content">

        <div class="row" data-bind="if: (buildingType == 'RawStorage' || buildingType == 'RefinedStorage')">
          <div class="col-xs-4">
            Usage: <span data-bind="text: getOccupyingSpace"></span> / <span data-bind="text: TotalCapacity"></span>
          </div>
          <div class="col-xs-8">
            <span data-bind="meter: {value: getOccupyingSpace, max: TotalCapacity}"></span>
          </div>
        </div>



        <div class="row">
        <!-- ko foreach: Ressources -->
        <div class="col-md-6" data-bind="if: $parent.TotalCapacity">
          <span data-bind="text: Name"></span> <span data-bind="text: Qte"></span> (<span class="small" data-bind="text: getOccupyingSpace"></span>)
          <!-- ko if: ProductionRate() -->
          <span data-bind="text: ProductionRate()"></span>/s
          <!-- /ko -->
        </div>
        <div class="col-md-6" data-bind="if: ProductionRate">
          <span data-bind="text: Name"></span> <span data-bind="text: getProductionRatePerSecond()"></span>/s (1 every <span data-bind="text: ProductionRate()/1000"></span> sec)
        </div>
        <!-- /ko -->
        </div>


      </div>
      <div class="card-footer">
        <!-- ko if: initialConstructionGoing -->
        <i class="fa fa-exclamation-triangle icon-gradient-warning" class="ko-popover"
  data-bind="popover: initialConstructionGoing, popoverOptions: { title: i18nextko.t('UnderConstruction_potitle') }" ></i>
  <span data-bind="i18next: 'UnderConstruction'"></span> <span data-bind="text: getBuildProgress"></span>
  <span data-bind="meter: {p: getBuildProgress, onComplete: 'remove'}"></span>
  <span data-bind="WorkersAssigned().length"></span>/<span data-bind="WorkersBuild"></span>
        <!-- /ko -->

      </div>
    </div>
  </div>
</script>
  ko.bindingHandlers.meter = {
      init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
          // This will be called when the binding is first applied to an element
          // Set up any initial state, event handlers, etc. here
          var progress = ko.unwrap(valueAccessor());

          if(progress.value) {
            var value = ko.unwrap(progress.value);
            var max = ko.unwrap(progress.max);

            if(value === 0 && max === 0) {
              var percentage = 0;
            } else {
              var percentage = (value/max)*100;
            }
          } else {
            var percentage = ko.unwrap(progress.p);
          }




          $progress_tpl = $('<div class="meter"><span style="width: '+percentage+'%"></span></div>');
          if(progress.onComplete) {
            $progress_tpl.attr('data-oncomplete', progress.onComplete);
          }
          $(element).append($progress_tpl);


      },
      update: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
          // This will be called once when the binding is first applied to an element,
          // and again whenever any observables/computeds that are accessed change
          // Update the DOM element based on the supplied values here.
          var progress = ko.unwrap(valueAccessor());
          if(progress.value) {
            var value = ko.unwrap(progress.value);
            var max = ko.unwrap(progress.max);
            var percentage = (value/max)*100;

          } else {
            var percentage = ko.unwrap(progress.p);

          }

          $(element).find('.meter span').stop().animate({'width': percentage+'%'}, (bindingContext.$root.cf.refreshEvery), 'swing', function() {
            if(percentage >= 100) {
              if($(element).find(".meter").attr('data-oncomplete') == 'remove') {
                $(element).hide(300, function() {
                  $(element).remove();
                  ko.cleanNode(element);

                });
              } else if($(element).find(".meter").attr('data-oncomplete') == 'reset') {
                $(element).hide(300, function() {
                  $(element).remove();
                });
              } else {

              }

            }
          });


      }
  };
var mainVM = {
    Ressources: new RessourcesVM(),
    Buildings: new BuildingsVM(),
    cf: {
      ...
    }
}