Search code examples
javascripttemplatesoptimizationjsrenderjsviews

observable vs render methods jsviews


Exist: 2500 array object-items. Render method took 1347.783ms

I`ve tried to optimize timing using $.observable(array).refresh() method and it takes: 3382.213ms

What`s the best way to update view? I thought refresh() method affects only changable items which is not much.

Template:

<script id="betTMPL" type="text/x-jsrender">
<div class="bet_group">
    <div class="bet-title {{if hideGroup}}min{{/if}}" id="group_{{:groupID}}" data-gid="{{:groupID}}" data-gameid="{{:gameID}}">
        <div class="groupName">{^{:groupName}}
            <span id="kolG_{{:groupID}}" {{if !hideGroup}}style="display: none;"{{/if}}> ({{:betsLen}})</span>
            {^{if allowMyMarkets}}
                {^{if actionMyMarket}}
                    <span class="addToMarket" title="<?=__('Add')?>"></span>
                {{else}}
                    <span class="addToMarket active" title="<?=__('Del')?>"></span>
                {{/if}}
            {{/if}}
        </div>
    </div>
    <div class="bets" {{if hideGroup}}style="display: none"{{/if}}>
        {^{for bets ~cols=cols ~mainGame=mainGame ~idd=idd ~gameID=gameID ~groupID=groupID}}

            {{if !(#getIndex() % (~cols))}}
                {{if #getIndex() != 0}}
                    </div>
                {{/if}}
                <div>
            {{/if}}

            {^{if #data}}
                <div id="z_{{:T}}">
                    <span class="bet_type {{:spanBetClass}}">{^{:betName}}
                        <span class="koeff {{:classLight}}"
                                {{if ~mainGame}}mainGame="{{:~mainGame}}"{{/if}}
                                {{if DopName}}dopName="{{:DopName}}"{{/if}}
                                bl="{{:B}}"
                                u="{{:~idd}}"
                                idgamecfg="{{:~gameID}}"
                                v="{{:sobID}}"
                                g="{{:~groupID}}"
                                d="{{:P}}"
                                dn="upcoming_events"
                                pl="{{:Pl.Id}}"
                                data-type="{{:T}}"
                                data-coef="{{:C}}"
                                id="b_{{:newID}}"><i>{^{:CV}}</i></span>
                    </span>
                </div>
            {{else}}
                <div>&nbsp</div>
            {{/if}}

            {{if #getIndex() == #get("array").data.length - 1}}
                </div>
            {{/if}}
        {{/for}}
    </div>
</div>
</script>


Solution

  • If you have {^{for bets ...}}...{{/for}} and you call $.observable(bets).refresh(newBets) then you are replacing the whole bets array with a new newBets array, so the whole content of that {{for}} block will be completely re-rendered and re-linked - which will be as slow as the original rendering.

    If the change to the array is incremental, and can be expressed in terms of one or more insert or remove operations, then that will allow JsViews to know that only the added/removed/moved items should be re-rendered, and it will be much faster. Move operations have been optimized in a recent update.

    See http://www.jsviews.com/#arrchange

    For more complex changes to arrays, you can use compiled View Models, and use the merge() feature. Since a recent update (78) the merge() operation has been optimized, and is usually much faster (including for arrays) provided you define identity, by a primary key field or similar. See http://www.jsviews.com/#jsvviewmodelsapi@mergeadvsample.