angular 11 返回上一页保留页面数据的思考

Fork Me On Github

起因

有这个需要的页面基本是从列表页点击详情或新建编辑页面。在返回需要回到上一次的列表页面,同时保持页面内容不变

例如:在列表已经翻到了第100页,需要修改某一项值(当然可以做一个弹窗修改,这里讨论的是有必要新增页面去修改的情况),

这是点进去修改之后返回,发现到了第一页,这就麻烦了,再放到第100页就需要浪费时间了。

解决方案

  1. 接受分页参数

这时可能想到在网址上加一个可接受的分页属性。

但是这也要手动去输入。

如果还有其他查询参数呢?难道还一个个去输入,这也麻烦。

第一版

/list?page=1
private route: ActivatedRoute

this.route.queryParams.subscribe(params => {
    this.goPage(params.page || 1);
});

第二版

/list?page=1&keywords=
private route: ActivatedRoute

this.route.queryParams.subscribe(params => {
    this.goPage(params);
});

缺点

不灵活

  1. 直接使用 localStorage 保存页面数据

如果所有的列表页面都使用一个值。这样就会发现页面之间会混乱。

例如:

/list

访问到了第10页,在访问其他页面

/list2

发现一进去也到了第10页。

那就分开保存,但是 localStorage 是由存储限制的,页面一多。就会发现localStorage存满了,

缺点

不优雅,会受限制

  1. 使用浏览器的网址历史功能

每访问一页就进行保存历史。


/**
 * 遍历对象属性或数组
 */
export function eachObject(obj: any, cb: (val: any, key?: string|number) => any): any {
    if (typeof obj !== 'object') {
        return cb(obj, undefined);
    }
    if (obj instanceof Array) {
        for (let i = 0; i < obj.length; i++) {
            if (cb(obj[i], i) === false) {
                return false;
            }
        }
        return;
    }
    for (const key in obj) {
        if (Object.prototype.hasOwnProperty.call(obj, key)) {
            if (cb(obj[key], key) === false) {
                return false;
            }
        }
    }
}

export function uriEncode(path: string, obj: any = {}, unEncodeURI?: boolean) {
    const result = [];
    for (const name in obj) {
        if (Object.prototype.hasOwnProperty.call(obj, name)) {
            const value = obj[name];
            result.push(name + '=' + (unEncodeURI ? value : encodeURIComponent(value)));
        }
    }
    if (result.length < 1) {
        return path;
    }
    return path + (path.indexOf('?') > 0 ? '&' : '?') + result.join('&');
}

/**
 * 从当前页面链接获取查询参数
 * @param routeQueries 
 * @param def 
 * @returns 
 */
export const getQueries = <T>(routeQueries: any, def: T, ): T => {
    const queries: any = {};
    const parseNumber = (val: any): number => {
        if (!val) {
            return 0;
        }
        if (typeof val === 'string' && val.indexOf('.') > 0) {
            return parseFloat(val);
        }
        return parseInt(val, 10);
    };
    eachObject(def, (val, key) => {
        if (!routeQueries || !Object.prototype.hasOwnProperty.call(routeQueries, key)) {
            queries[key] = val;
            return;
        }
        if (typeof val === 'number') {
            queries[key] = parseNumber(routeQueries[key]);
            return;
        }
        if (typeof val === 'boolean') {
            queries[key] = routeQueries[key] === true || routeQueries[key] === '1' || routeQueries[key] === 'true';
            return;
        }
        queries[key] = typeof routeQueries[key] === 'undefined' || routeQueries[key] === null ? '' : routeQueries[key];
    });
    return queries;
};

/**
 * 记录查询历史
 * @param queries 
 * @param title 
 */
export const applyHistory = (queries: any, title = '查询列表') => {
    const url = window.location.href;
    const path = url.split('?', 2)[0];
    history.pushState(null, title, uriEncode(path, queries));
    document.documentElement.scrollTop = 0;
};

使用

private route: ActivatedRoute

this.route.queryParams.subscribe(params => {
    this.queries = getQueries(res, {
        keywords: '',
        term: 0,
        page: 1,
        per_page: 20,
    });
    this.goPage(this.queries.page);
});

public goPage(page: number) {
    const queries = {...this.queries, page};
    this.service.logList(queries).subscribe(res => {
        this.items = res.data;
        this.queries = queries;
        applyHistory(queries);
    });
}
点击查看全文
标签: angular
0 470 0
在 angular 项目中实现对页面的访问控制
按下回车键,焦点移动到下一个表单或提交表单
使用ng-template 显示tree结构数据
使用 ViewContainerRef.createComponent 替代 ComponentFactoryResolver
angular 12使用 KaTex 显示 AsciiMath 格式的公式