使用过滤器或管道将产品类别加载到 Ionic 2 的页面中?

Posted

技术标签:

【中文标题】使用过滤器或管道将产品类别加载到 Ionic 2 的页面中?【英文标题】:Use a filter or pipe to load product categories into pages in Ionic 2? 【发布时间】:2017-06-27 15:06:10 【问题描述】:

我希望创建一个有 6 个页面的 Ionic 2 应用程序,我不确定是否对各个类别页面使用管道或过滤器以及我需要这样做的代码。

每个分类页面都可以加载“applecat”分类定义的相关产品。以下是 API、通过 Google 表格以电子表格格式显示产品以及一个非常快速的主页模型创意:

https://sheetsu.com/apis/v1.0/04c2d2906a10 https://docs.google.com/spreadsheets/d/1RNLXsxTFymqRwq_S538qX1p1PAEDIEA6s5sV8etkfLU/edit?usp=sharing

概览

6 页

首页 - 无需加载产品 - 只需链接到页面 allproducts - 加载所有产品 ipad - 加载在 applecat 类别下列为 ipad 的所有项目 iphone - 加载在 applecat 类别下列为 iphone 的所有项目 键盘 - 加载所有在 applecat 类别下列为 iphone 的项目 laptop - 加载所有在 applecat 类别下列为 iphone 的项目

场景(潜在用户流)

用户打开应用程序,点击主页,然后点击 Ipad 类别链接(加载所有 Ipad 产品) 然后回到首页决定点击All(Loads ALL products),返回并点击另一个页面....

问题

它会将 2 个数组加载到内存/控制台中吗? 类别页面应该使用过滤器还是管道?代码应如何查找与我现有的 API 调用和产品列表数组相关的管道/过滤器?

提供者

getRemoteData(): any
        return this.http.get('https://sheetsu.com/apis/v1.0/04c2d2906a10')
                .map(res => res.json());

列表页

@Component(
selector: 'page-master',
templateUrl: 'master.html',
providers: [Sheetsu]
)
export class MasterPage 

// declare publicly accessible variable
public sheetsuData: any;

constructor(public navCtrl: NavController, public navParams: NavParams, public sheetsuService: Sheetsu) 

ionViewDidLoad() 
    this.sheetsuService.getRemoteData()
    .subscribe(response => 
    // assign variable (async)
    this.sheetsuData = response;
    );

我看到了一个带有重置的过滤器示例,但不确定这是否适用于这种情况?

 resetData()
    this.modifiedData = JSON.parse(JSON.stringify(this.originalData));
  

  filterData()
    this.modifiedData = this.modifiedData.filter((youtuber) => 
        return youtuber.subscribers > 1000000;
    
  

由于类别页面如此之少,也许 Pipe 是每个页面的最佳选择?如果用户浏览所有 6 个页面,则只是多个 API 调用的潜在问题。

首选赏金答案:管道/过滤器/服务的代码,关于最佳解决方案的建议以及原因,更好的是 Github 中的基本工作示例(上面是对 Provider 和列表 ts 代码的 API 调用)。

可以从https://github.com/jones98/4cat查看和分叉此Github repo

可以在https://drive.google.com/file/d/0B0QBawqyq1vPZ0o4WEpaa0o0azQ/view查看应用程序当前状态的视频(预分类页面工作)

【问题讨论】:

【参考方案1】:

您可以创建一个缓存数据的服务(可能是 5 分钟、30 分钟、一小时或任何在您的应用程序上下文中有意义的时间间隔),以避免发出如此多的 http 请求,并且会也只返回您需要的内容,以便您可以直接在组件/视图中使用它,而无需过滤任何内容。

这不仅会节省大量向服务器发出的无用 http 请求,而且还会使应用程序更快,因为用户打开产品页面的大部分时间都将使用本地数据。

假设您已经有一个产品类:

export class ProductModel 
    public aw_deep_link: string;
    public product_name: string;
    public apple_cat: string;
    //...

然后我们可以像这样创建我们的缓存模型:

class ProductCache 
    public products: Array<ProductModel>;
    public timestamp: number;

    public isValid(): boolean 
        if(!this.products) 
            return false;
        

        let isExpired = Date.now() - this.timestamp > 1800000; // 30 min
        return !isExpired;
    

然后我们可以在 ProductCategoryService 中使用它

// Angular imports
import  Injectable  from '@angular/core';
import  Http  from '@angular/http';

// Rxjs imports
import  Observable  from 'rxjs';
import 'rxjs/add/operator/map';

@Injectable()
export class ProductCategoryService 

    private cache: ProductCache;
    private apiUrl: string = 'https://sheetsu.com/apis/v1.0/04c2d2906a10';

    constructor(private http: Http) 
        this.cache = new ProductCache();
    

    public getAll(): Observable<Array<ProductModel>> 
        if(this.cache.isValid()) 
            // Return the products from the cache
            return Observable.of(this.cache.products);
        

        // Cache is empty/expired, so we need to make the http request
        return this.http.get(this.apiUrl).map(res => res.json()).map(data => 
            // Save the data in the cache for the next time
            this.cache.products = data;
            this.cache.timestamp = Date.now();

            // Return the list of (all) products
            return this.cache.products;
        );
    

    public getIpadProducts(): Observable<Array<ProductModel>> 
        return this.getAll().filter((product: ProductModel) => 
            return product.apple_cat.toLowerCase() === 'ipad';
        );
    

    public getIphoneProducts(): Observable<Array<ProductModel>> 
        return this.getAll().filter((product: ProductModel) => 
            return product.apple_cat.toLowerCase() === 'iphone';
        );
    

    // ...

然后只需在每个页面中调用正确的方法,由于产品的缓存,一个http请求将只发出一次(或在本例中为每30分钟一次)。

可能存在语法错误或拼写错误(我直接在 SO 答案中编码),但这应该让您了解如何处理给定的场景。如果有问题,请告诉我,以便我可以帮助您修复它...

更新:Here 您可以找到一些信息(来自 Angular 2 文档),说明为什么使用管道过滤数据不是一个很好的方法,这就是为什么我建议在服务,对应用程序的其余部分隐藏(毕竟,每个类别页面只想获取它需要显示的数据,它不应该处理所有产品到那时只找到它需要在视图中显示的那些)。

【讨论】:

因此使用ionic g provider ProductCategory 创建了一个新服务。还通过视频向github.com/jones98/4cat 添加了工作应用程序。让这个 ProductCategory 部分在类别页面中工作会很棒。不确定我目前需要哪些零件。 我已经创建了 this pull request 并添加了缓存逻辑所需的更改。请看一下,我觉得代码很简单。 非常感谢您在这里所做的努力。我用这个完全撞到了一堵砖墙,就像做梦一样!杰出的贡献。非常感谢 这很好用,但如果没有互联网。微调器只是转动,您必须强制关闭应用程序。有没有办法给微调器添加超时? github.com/jones98/4cat/blob/master/src/pages/laptop/laptop.ts 和 github.com/jones98/4cat/blob/master/src/providers/…【参考方案2】:

我还应该创建一个名为 ProductCategoryService

的服务
ionic g provider ProductCategory

并创建一个我可以使用类别名称作为参数执行的方法

getProductsByCategoryName(categoryName): any
  return this.allProducts.filter(product => product.categoryName === categoryName);

作为回报,我会得到一个包含我的产品的过滤数组,将其绑定到您的模板,然后就完成了。

【讨论】:

以上是关于使用过滤器或管道将产品类别加载到 Ionic 2 的页面中?的主要内容,如果未能解决你的问题,请参考以下文章

Ionic 3,管道共享模块,用于延迟加载页面

如何使用 observable 的输出来过滤另一个

从特定类别获取 WooCommerce 产品

WooCommerce 产品类别计数

Ionic 4 Angular模板与异步管道绑定到可观察

类别页面上产品的 pre_get_posts - woocommerce