如何在 url 中记录页面搜索条件

问题描述

在一个页面,有很多搜索选项,比如十几个。假设全部都有选中,那么查询参数就会有十几个。我想把这些参数都放到 url 上,这样即使页面刷新也能还原之前的搜索条件

我用的是 angular(1.2.5) + ui-router(0.2.18) 来做的,目前的代码是这样的

贴代码

    // config
    angular.module('app').config(configRouter);
    
    function configRouter($locationProvider, $urlRouterProvider, $stateProvider) {
        $locationProvider.html5Mode(false);
    
        $urlRouterProvider
            .when('/', '/enter/paper/1/1/')
            .when('/enter', '/enter/paper/1/1/')
            .otherwise('/enter/paper/1/1/');
    
        $stateProvider
            .state('main', {
                url: '/',
                templateUrl: 'main.html',
                controller: 'MainCtrl',
                controllerAs: 'mn'
            })
            .state('main.enter', {
                url: '^/enter',
                template: '<div ui-view class="enter"></div>'
            })
            .state('main.enter.paper', {
                url: '^/enter/paper/:page/:sort/:audit_status/:audit_time_start/:audit_time_end/:id/:name/:publisher_id/:school_stage_id/:subject_id/:grade_id/:volume_id/:chapter_id',
                templateUrl: 'enter_paper.html',
                controller: 'EnterPaperCtrl',
                controllerAs: 'ep'
            });
    }

    // EnterPaperCtrl
    var params = {
        page: 1,
        sort: 1,
        audit_status: 8,
        // ... 省略其他参数
    };
    function search() {
        return EnterService.search(params).then(function(data) {
            // 省略其他代码
            // 使用 $state.go 可以实现修改 query 而不用刷新页面
            $state.go('.', params, {notify: false});
        });
    }

结果是

无法进入 main.enter.paper ,原因就是设置了很多 stateParams ,但是没有给默认值, 因为那些都是可选参数。

我的期望是

最好设置路由的时候只需要这样设置

    // config
    $urlRouterProvider
            .when('/', '/enter/paper/1/1')
            .when('/enter', '/enter/paper/1/1')
            .otherwise('/enter/paper/1/1');
            
    $stateProvider
        .state('main.enter.paper', {
            url: '^/enter/paper/:page/:sort', // 最好是其他可选参数不用预先写在这里
            templateUrl: 'enter_paper.html',
            controller: 'EnterPaperCtrl',
            controllerAs: 'ep'
         });
         
    // EnterPaperCtrl
    var params = {
        page: 1,
        sort: 1,
        audit_status: 8,
        // ... 省略其他参数
    };
    function search() {
        return EnterService.search(params).then(function(data) {
            // 省略其他代码
            // 使用 $state.go 可以实现修改 query 而不用刷新页面
            $state.go('.', params, {notify: false});
        });
    }

还有之所以不用 location.href 是因为这个会刷新页面,不知各位有什么好办法?

阅读 3.4k
2 个回答

ok, 我找到一个可以实现的方法,贴代码如下:

$stateProvider
        .state('main', {
            url: '/',
            templateUrl: 'main.html',
            controller: 'MainCtrl',
            controllerAs: 'mn'
        })
        .state('main.enter', {
            url: '^/enter',
            template: '<div ui-view class="enter"></div>'
        })
        .state('main.enter.paper', {
            url: '^/enter/paper/:page?sort=1&per_page&publisher_id&school_stage_id&subject_id&volume_id&grade_id&type_id&level&year&province_id&area_id&city_id&time_start&time_end',
            templateUrl: 'enter_paper.html',
            controller: 'EnterPaperCtrl',
            controllerAs: 'ep'
        });

就是在定义 url 的时候,后面先定义可选参数,'^/enter/paper/:page?sort=1&per_page&publisher_id
这样,在进入 'main.enter.paper' 后,地址栏可以看到 url 是 /enter/paper/1?sort=1&per_page=10
因为我进入 EnterPaperCtrl 就更新了一次 url,更新参数就是 {page: 1, sort: 1, per_page: 10},然后如果选中出版社,查询后更新 url,

var params = {
    page: 1,
    sort: 1,
    per_page: 10,
    publish_id: '38dfjdfkj889'
};
$state.go('.', params, {notify: false});

可以看到 url 将更新为 /enter/paper/1?sort=1&per_page=10&publish_id=38dfjdfkj889

ui-router的话,参数的配置不一定非要以内联在url的方式。可以对每个路由对象声明一个params属性

{
 name: 'foo',
 url: '/foo',
 params: {
     a: null,
     b: 'b',
     c: 1
 }
}

params属性配置的参数默认是可选的,你用的ui-router版本比较低,具体的配置参数请参考文档吧

好像你还需要使参数持久化,这种query参数一般不会写在url主体中的,一般都是写到url的query部分, 如

url: 'foo?param1&param2'
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题