使用计算的 aurelia 搜索过滤在呈现视图时会导致问题

aurelia search filtering using a computed is causing issues when rendering to view

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

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 对象。 我有一个计算器,可以根据 selected 类别过滤搜索结果:

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;
}

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

我可以在 selected 类别更改或从服务器返回数据时触发事件,然后我可以重新计算过滤结果。这会起作用但是很麻烦,并且更愿意能够在计算

中做到这一点

如果没有 computedFrom,您的 属性 getter 将被轮询,这就是您的界面跳来跳去的原因。我不熟悉 .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()
    }
}