Angular 1 ui-路由器 1.0.24:以编程方式更改 url,无需重新加载控制器,保留历史记录和手动 url 更改

Angular 1 ui-router 1.0.24: change url programmatically without controller reload, keeping history and manual url change

我想使页面 url 与使用 ui-router 1.0.24 的 angular 1 页面的内部状态保持同步。

当页面过滤器改变时,页面数据被重新加载,然后调用 $state.transitionTo() 来同步 url新过滤器:

$state.transitionTo($state.current.name, self.getPageParams(), { /*location: 'replace',*/ reload: false, inherit: false, notify: false, custom: {urlChangedAfterReload: true} });

页面状态定义为:

  $stateProvider
    .state('page', {
      url: '/Page/:dateParam/:modeParam',
      params: {
        dateParam: {value: null, dynamic: false},
        modeParam: {value: 'READ', dynamic: false}
      },
      ...
    })

我尝试将参数标记为动态(使用 dynamic: true):该选项避免了控制器重新加载,但同时不允许更改 url 手动并且不允许使用历史记录(参数是动态的,所以 ui-router 忽略它们的变化)。

仅当我以编程方式更改 url 时才可以启用动态选项,而当用户手动更改 url、通过历史记录或 link?

我找到了解决方案。

在更改url之前,我将当前页面的所有参数设置为动态(因此不会重新加载控制器)。

this.reload = function() {
  ...
  $log.info('Updating url');
  const pageParams = $stateRegistry.states[$state.current.name].params;
  Object.keys(pageParams).forEach(paramName => pageParams[paramName].dynamic = true);
  $state.transitionTo($state.current.name, this.getPageParams());
};

然后,当转换完成时,我将动态参数设置为 false(因此如果用户将更改 url 或将使用浏览器历史记录,将重新加载页面)。 onSuccess 参数改变时调用,onError 否则。

this.$onInit = function () {
  ...
  const uiRouterOnSuccess = $transitions.onSuccess({}, () => {
    $log.info('onSuccess');
    const pageParams = $stateRegistry.states[$state.current.name].params;
    Object.keys(pageParams).forEach(paramName => pageParams[paramName].dynamic = false);
    return true;
  });
  const uiRouterOnError = $transitions.onError({}, () => {
    $log.info('onError');
    const pageParams = $stateRegistry.states[$state.current.name].params;
    Object.keys(pageParams).forEach(paramName => pageParams[paramName].dynamic = false);
    return true;
  });
  $log.info('$onInit');
  $scope.$on('$destroy', () => {
    $log.info('$destroy');
    uiRouterOnSuccess();
    uiRouterOnError();
  });
};

getPageParams 使用过滤器值更新参数。

this.getPageParams = function() {
  const params = $state.current.params;
  params.dateParam = xxx;
  params.modeParam = yyy;
  return params;
};