使用计算的 aurelia 搜索过滤在渲染到视图时会导致问题

Posted

技术标签:

【中文标题】使用计算的 aurelia 搜索过滤在渲染到视图时会导致问题【英文标题】:aurelia search filtering using a computed is causing issues when rendering to view 【发布时间】:2017-10-15 17:03:57 【问题描述】:

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

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】:

如果没有 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()
    

【讨论】:

这有点像我当前的工作实现,但这里的问题是如果我执行另一个搜索说我搜索“对象 3”,那么过滤的结果不会更新,因为没有观察到搜索结果属性。我使用 eventAggregator 发布了一个名为“filterSearchResults”的事件,并有一个订阅可以执行您对 filtersChanged 回调的建议。每次我想更新结果时,我只需要发布事件。我觉得这两种方法都不理想,因为它的可扩展性不太好(更多过滤器等),顺便说一句,感谢您的回复! 在这种情况下,您希望将客户端过滤逻辑移动到另一个方法,并且您的 filtersChanged 回调以及服务器 get 可以执行相同的功能。事件聚合器是创建松散耦合组件的一个很好的解决方案,但是在单个组件内部使用它并没有多大意义。我会更新我的答案以反映这一点。 我会接受答案,即使我希望它可以以某种方式使用计算属性。我要做的是扩展 collectionObserver 以获取一组要观察的项目,因此我只需将其设置在一个地方。

以上是关于使用计算的 aurelia 搜索过滤在渲染到视图时会导致问题的主要内容,如果未能解决你的问题,请参考以下文章

typescript Bulma.io形式为aurelia和aurelia形式的渲染器。

在 Drupal 7 中,如何使用“搜索视图”模块将搜索词过滤器添加到我的视图中?

搜索视图和可过滤:显示带有搜索文本的栏

如何在视图外评估 Aurelia 插值表达式?

在 VueJS 中使用计算属性搜索过滤器

Aurelia 中组件和视图之间的区别(及其生命周期)