如何在UI Router中通过$state.go修改state的data属性(不使用params)?
$state.go的参数修改state的data,但有替代方案实现需求 首先明确:AngularJS ui-router中,state的data属性是静态定义的全局配置,不能直接通过$state.go的第二个参数(params对象)来修改——这个参数只能传递state配置中params字段定义的参数,和data是完全独立的两个部分。所以你写的$state.go('baseInformation', {data1: 'data1 changed'})是不会生效的。
不过我们可以通过以下几种方式实现“动态传递类似data的自定义数据”的需求,同时避开显式使用params(或使用隐藏式params):
方法1:临时修改state的全局data配置(不推荐,有副作用)
如果你确定不需要考虑全局state配置被修改的影响,可以直接获取目标state的定义,修改其data属性后再跳转:
// 在跳转前修改state的data const targetState = $state.get('baseInformation'); targetState.data.data1 = 'data1 changed'; // 跳转 $state.go('baseInformation');
⚠️ 注意:这种方式会全局修改该state的data配置,后续所有跳转到baseInformation的请求都会使用修改后的data1值,除非你再改回去。如果只是单次跳转需要临时数据,不建议用这种方法。
方法2:用resolve传递动态数据(推荐,无全局副作用)
resolve是ui-router中用于在进入state前预加载数据的机制,每次跳转都会执行,非常适合传递单次跳转的动态数据,且不会污染全局state配置。
第一步:修改state配置,添加resolve
(function() { 'use strict'; angular.module('app').config(stateConfig); function stateConfig($stateProvider) { $stateProvider .state('baseInformation', { parent: 'panel', params: { param1: null }, data: { data1: 'sample data' }, // 添加resolve resolve: { dynamicData1: function($stateParams) { // 如果跳转时传了dynamicData1就用它,否则用data里的默认值 return $stateParams.dynamicData1 || this.data.data1; } }, url: 'baseInformation', views: { 'panel': { templateUrl: 'app/baseInformation.html', controller: 'BaseInformationController', controllerAs: 'vm' } } }); } })();
第二步:跳转时传递动态数据
$state.go('baseInformation', {dynamicData1: 'data1 changed'});
第三步:在控制器中注入resolve的数据
angular.module('app').controller('BaseInformationController', BaseInformationController); function BaseInformationController(dynamicData1) { var vm = this; // 使用动态传递的数据 vm.data1 = dynamicData1; }
这种方法的优势是:每次跳转的动态数据都是独立的,不会影响其他跳转,也不会修改全局state的原始配置。
方法3:使用隐藏式params(满足“不想用显式params”的需求)
如果你不想让参数出现在URL中,可以定义一个隐藏的params(设置squash: true和dynamic: true),这样参数不会显示在地址栏里,但能正常传递数据。
第一步:修改state的params配置
(function() { 'use strict'; angular.module('app').config(stateConfig); function stateConfig($stateProvider) { $stateProvider .state('baseInformation', { parent: 'panel', params: { param1: null, // 添加隐藏参数data1 data1: { value: null, // 默认值 squash: true, // 值为null时不显示在URL dynamic: true // 允许动态修改该参数 } }, data: { data1: 'sample data' }, url: 'baseInformation', views: { 'panel': { templateUrl: 'app/baseInformation.html', controller: 'BaseInformationController', controllerAs: 'vm' } } }); } })();
第二步:跳转时传递参数
$state.go('baseInformation', {data1: 'data1 changed'});
第三步:在控制器中获取参数
angular.module('app').controller('BaseInformationController', BaseInformationController); function BaseInformationController($stateParams, $state) { var vm = this; // 优先用传递的params值,没有则用data里的默认值 vm.data1 = $stateParams.data1 || $state.current.data.data1; }
这种方法既满足了你“不想用显式params”(参数不会出现在URL)的需求,又实现了动态传递数据的效果,同时不会修改全局state的data配置。
内容的提问来源于stack exchange,提问作者Rasool Ghafari

