使用计算机进行aurelia搜索过滤会导致渲染时出现问题

时间:2017-05-16 14:34:58

标签: javascript typescript search aurelia computed-properties

我有一个检索对象的搜索功能

this.searchForObjectByName = () => {
            this.server.get('objects/?searchTerm=' + self.searchTerm)
                .then(groupObjects=> 
                {
                    this.searchResults = groupObjects;
                });
        }

然后我将其结果设置为名为searchResults的属性,该属性是一组对象。 我现在想根据结果执行一些过滤。假设我有一些看似如下的对象组:

{
    id: 1, 
    name: 'group 1',
    objects: [
        {
          id: 1,
          name: 'object name 1',
          categories: ['Cat A', 'Cat B']
        },
        {
          id: 2,
          name: 'object name 2',
          categories: ['Cat A', 'Cat D']
        },
        {
          id: 3,
          name: 'object name 3',
          categories: ['Cat C', 'Cat D']
        }
    ]
},
{
    id: 2, 
    name: 'group 2',
    objects: [
        {
          id: 4,
          name: 'object name 4',
          categories: ['Cat A', 'Cat F']
        },
        {
          id: 5,
          name: 'object name 5',
          categories: ['Cat C', 'Cat D']
        }
    ]
}

我想过滤以仅显示Cat A对象。 我有一个计算器,根据选定的类别过滤搜索结果:

get filteredSearchResults(): any[] {
    var filteredGroups = this.searchResults.map(res => {
        let filteredGroup = new Group;
        filteredGroup = res.id,
        filteredGroup = res.name;
        filteredGroup = res.objects.filter(o => this.filteredCategories.some(fc => o.categories.some(oc => oc == fc)));
        return filteredGroup;
    });

    filteredGroups = filteredGroups.filter(fg => fg.objects.length > 0);
    return filteredGroups;
}

这会很好地过滤结果,我可以选择不同的类别并正确过滤。然而,它在UI中遍布各处,由于使用计算器来过滤结果,结果会不断更新。我不能使用computedfrom属性,因为它基于我选择的过滤类别(即数组)和从服务器返回的结果(也是数组)。还有其他人以前遇到过这个问题吗?我尝试的所有内容都会导致抖动,我不确定如何以不同的方式做到这一点。

我可以在选定的类别更改时触发事件,或者从服务器返回数据时,我可以重新计算过滤后的结果。这可以工作,但很hacky,并希望能够在计算

中执行此操作

1 个答案:

答案 0 :(得分:1)

如果没有computedFrom,您的属性获取器将被轮询,这就是您的界面跳转的原因。我不熟悉.some,但我猜不到订单。虽然你可以简单地命令你的搜索结果解决这个问题,但是每隔5秒对数组进行过滤和排序是非常低效的。

使用集合观察器,只有在界面过滤器实际更改时才会执行过滤器代码。 我还没有真正测试过此代码

import { BindingEngine, Disposable, bindable } from 'aurelia-framework';

export class MyPage
{
    @bindable searchTerm: string;
    filteredSearchResults: any[];
    subscription: Disposable;

    constructor(private bindingEngine: BindingEngine)
    {
    }

    attached()
    {
        this.subscription = this.bindingEngine.collectionObserver(this.filteredCategories).subscribe(this.filtersChanged);
    }

    detached()
    {
        this.subscription.dispose();
    }

    searchTermChanged(newValue: string, oldValue: string)
    {
        this.find();
    }

    find()
    {
         this.server.get('objects/?searchTerm=' + this.searchTerm)
                .then(groupObjects=> 
                {
                    this.searchResults = groupObjects;
                    this.update();
                });
    }

    update()
    {
        // your original filtering logic unchanged
        var filteredGroups = this.searchResults.map(res =>
        {
            let filteredGroup = new Group;
            filteredGroup = res.id,
            filteredGroup = res.name;
            filteredGroup = res.objects.filter(o => this.filteredCategories.some(fc => o.categories.some(oc => oc == fc)));
            return filteredGroup;
        });

        filteredGroups = filteredGroups.filter(fg => fg.objects.length > 0);

        // set value instead of using a computed property
        this.filteredSearchResults = filteredGroups;
    }

    filtersChanged(splices)
    {
        this.update(); // you could remove this method and bind the array observable directly to update()
    }
}