Mitigating a flickering UI when refreshing content in Ember

百般思念 提交于 2019-12-24 08:13:34

问题


The problem

I have a view which displays a list of workers. This view has a button which calls a controller method named refresh. Originally I was setting the content to this list, but noticed that the UI would flicker, which would be especially annoying once this is run on a timer.

I managed to make everything work without flickering using the following:

App.WorkersIndexController = Ember.ArrayController.extend
    refresh: ->
        console.log 'refreshing workers'
        # set a property to a new collection
        @set 'refreshing', App.Worker.find()

    # observer that watches the new collection load
    update: (->
        refreshing = @get 'refreshing'
        return unless refreshing.get('isLoaded')
        # what this question is about...
        Ember.run =>
            @set 'content', refreshing
    ).observes('refreshing.isLoaded')

As you can see I'm setting the refreshed content to a temporary variable, and observing the loading of the content and then updating the content. The content flickered less until I added a call to Ember.run which removed the flicker entirely.

I understand why the flicker is occurring, and I understand why Ember.run makes it go away but my question is what is the best way to solve this without resorting to Ember.run? I feel like calling Ember.run is kind of a last resort... Any help would be greatly appreciated!

Edit: Also I'm not using ember data. The find method looks like this:

App.Worker.reopenClass
    find: ->
        console.log 'loading workers'
        workers = Em.A []
        request = $.getJSON '/api/admin/workers', (data) =>
            console.log ' -> loaded workers'
            data.forEach (d) =>
                worker = App.Worker.create(d)
                worker.set 'isLoaded', true
                workers.pushObject(worker)
        request.error =>
            console.log ' -> failed to load workers'
            workers.set 'isFailed', true
        request.complete =>
            workers.set 'isLoaded', true
        workers

回答1:


I have avoided flicker in similar situations by having a fixed list who's objects I just change.

In the simplest case, lets' say you were displaying names, and knew that you knew you'd never have more than 3 elements you could make

App.names = [ 
    Ember.Object.create({name:"", active:false}),
    Ember.Object.create({name:"", active:false}),
    Ember.Object.create({name:"", active:false})
]

and have your template be

{{#each App.names}}
    {{#if active}}
        <li> {{name}} </li>
    {{/if}}
{{/each}}

you could then add names by running

  App.names[0].set("name", "Frank");
  App.names[0].set("active", true);

and update the list without any flicker. Only a single element in the list is changed at a time, so you don't have the flicker from the whole list being redrawn.

In practical terms you might need App.names to be an ArrayController so that you can handle expanding the list gracefully, but the gist of that will work.



来源:https://stackoverflow.com/questions/14883553/mitigating-a-flickering-ui-when-refreshing-content-in-ember

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!