Ionic1如何让菜单模板共享当前控制器的$scope变量
我太懂你这个困扰了——侧菜单挂在抽象父状态app的模板里,和子视图(比如app.view1)的控制器$scope根本不是同一个上下文,直接写{{title}}肯定拿不到值;硬加ng-controller又会让控制器被实例化两次,控制台输出重复,简直头疼。
下面给你几个实用的解决方案,按推荐程度排序:
方案1:用Angular服务共享数据(最推荐)
搞个专门的共享服务来存跨组件的数据,不管是菜单还是视图控制器,都通过这个服务读写,彻底绕开$scope上下文的问题,还符合Angular的最佳实践。
- 先创建共享服务:
tinApp.factory('SharedData', function() { var shared = { title: '' }; return { getTitle: () => shared.title, setTitle: (newTitle) => { shared.title = newTitle; } }; });
- 修改你的子控制器,注入服务并设置标题:
tinApp.controller('myControllerController', function($scope, SharedData) { const pageTitle = "hello"; // 存到共享服务里 SharedData.setTitle(pageTitle); // 视图本身要用的话同步到$scope $scope.title = pageTitle; });
- 给抽象父状态
app加个菜单控制器,用来绑定共享数据到菜单的$scope:
// 修改app状态的配置 .state('app', { url: '/app', abstract: true, templateUrl: 'templates/menu.html', controller: 'MenuController' // 新增菜单专属控制器 })
然后写这个MenuController:
tinApp.controller('MenuController', function($scope, SharedData) { // 监听共享数据的变化,确保菜单实时更新 $scope.$watch( () => SharedData.getTitle(), (newTitle) => { $scope.title = newTitle; } ); });
这样菜单里的{{title}}就能实时显示当前视图设置的标题了,完全不会有控制器重复加载的问题,后续要加其他共享数据也方便扩展。
方案2:直接更新父状态的$scope
如果不想新增服务,也可以利用Angular的$scope继承特性——子状态的$scope会继承父状态的$scope,所以直接在子控制器里更新$scope.$parent的属性就行。
修改你的子控制器:
tinApp.controller('myControllerController', function($scope) { $scope.title = "hello"; // 把值同步到父状态(app)的$scope $scope.$parent.title = $scope.title; });
这个方法简单直接,但缺点也明显:如果有多个子页面,每个都要手动写同步代码;要是父状态的$scope结构变了,很容易出问题,适合简单场景临时用用。
方案3:用$rootScope(不推荐,尽量别用)
直接把数据丢到全局的$rootScope里,所有模板都能直接访问,但这种方式容易造成全局变量污染,后期代码维护起来会很乱,除非是全APP通用的核心数据,否则不建议这么干。
示例代码:
tinApp.controller('myControllerController', function($rootScope) { $rootScope.title = "hello"; });
菜单里的{{title}}就能直接拿到值,但要小心别在其他地方不小心覆盖了这个变量。
为啥加ng-controller会重复加载?
因为你的子状态app.view1已经指定了controller: 'myControllerController',当你在菜单模板里再加ng-controller="myControllerController"时,Angular会额外再实例化一次这个控制器,所以控制台的console.log会输出两次,这就是重复加载的根源。
还是方案1最稳妥,既规范又好维护,推荐你用这个~
内容的提问来源于stack exchange,提问作者yavg

