文档章节

Angular控制器之间的数据通信

梅气灶
 梅气灶
发布于 2015/12/10 15:22
字数 1590
阅读 189
收藏 3

        angular作为在SPA开发中一个很强大的框架,数据操作是一大特点,而每个数据都有他们自己相应的作用域(即在自己的控制器内),那么,如何实现控制器之间的数据交互呢?归纳总结出来有如下几种:

控制器之间是父子关系——继承方式

        这样的交互方式是由于作用域的继承是基于js的原型继承方式的,所以需要分成两种情况,当作用域上的值(即你需要操作的数据)是基本类型的时候,修改父级作用域上面的值的同时会影响到子级作用域,但是修改子级作用域的值却不会改变父级作用域。另外一种情况是:作用域上的值是对象,这样无论是修改父级作用域还是子级作用域,两个都会改变!具体demo,可以查看我的上一篇文章。

基于广播机制的方式

        其实利用父子的继承方式已经能处理angular大部分的数据交互了,不过,当我们需要在兄弟节点进行数据交互的话,父子继承方式就显得那么有心无力了,那么这个时候就需要用到了我们的广播机制进行数据交互,具体我们来看下面的一个demo:

        先来看下控制器中的代码:

var routeApp = angular.module('routeApp', []);
    routeApp.controller('parentCtrl',['$scope',function($scope){
        $scope.parentname = "This is parent init name meichao";
        $scope.$on('firstChild', function(event,data){
            $scope.parentname = "This is firstChild change name";
            $scope.$broadcast('parent_to_secondCtrl', data);
        });
        $scope.$on('secondChild', function(event,data){
            $scope.parentname = "This is secondChild change name";
            $scope.$broadcast('parent_to_firstCtrl', data);
        });
    }]);
    routeApp.controller('firstChildCtrl',['$scope',function($scope){
        $scope.firstChidname = "This is firstChildCtrl init name";
        $scope.firstClick = function(){
            $scope.$emit('firstChild', $scope.firstChidname);
        }
        $scope.$on('parent_to_firstCtrl', function(event,data){
            $scope.firstChidname = data;
        });

    }]);
    routeApp.controller('secondChildCtrl',['$scope',function($scope){
        $scope.secondChidname = "This is secondChildCtrl init name";
        $scope.secondClick = function(){
            $scope.$emit('secondChild', $scope.secondChidname);
        }
        $scope.$on('parent_to_secondCtrl', function(event,data){
            $scope.secondChidname = data;
        });
    }]);

        再来看下我们的html中的代码:

<div ng-controller="parentCtrl">
        <div>{{parentname}}</div>
        <br>
        <div ng-controller="firstChildCtrl">
            <div>这里是firstChildCtrl中的可能会被改变的值:{{firstChidname}}</div>
            <br>
            <input type="text" ng-model="firstChidname">
            <div class="btn" ng-click="firstClick()">点我first</div>
        </div>
        <div ng-controller="secondChildCtrl">
            <div>这里是secondChildCtrl中的可能会被改变的值:{{secondChidname}}</div>
            <br>
            <input type="text" ng-model="secondChidname">
            <div class="btn" ng-click="secondClick()">点我second</div>
        </div>
    </div>

        我们一共写了有3个控制器,一个父级,两个子级(子级控制器互为兄弟),利用广播机制来实现firstChildCtrl控制器和secondChildCtrl控制器之间的数据交互,各控制器内都有一个函数用来触发$emit事件(像父级传送数据),然后在parentCtrl控制器中用$on来接收数据,进而像另外一个子控制器进行$broadcast广播,从而改变另外一个自控制器中的数据,以达到兄弟控制器之间的数据交互。

        具体效果可以自己写测试用例。

指令中的控制器与父级控制器之间的交互

        当我们自写指令的时候,也会有与父级控制器之间进行数据交互,来看一个demo:

<div ng-controller="parentCtrl">
        <div>{{parentname}}</div>
        <test/>
    </div>
    <script src="//cdn.bootcss.com/angular.js/1.3.9/angular.min.js"></script>
    <script>
        var routeApp = angular.module('routeApp', []);
        routeApp.controller('parentCtrl',['$scope',function($scope){
            $scope.parentname = "这里是父级控制器里面的内容";
        }]);
        routeApp.directive('test', function(){
            return {
                scope:true,
                template: '<div><div>{{parentname}}</div><input type="text" ng-model="parentname" /></div>',
                link: function($scope, iElm, iAttrs, controller) {
                    
                }
            };
        });
    </script>

        指令中的scope默认为false,那么我们创建的指令就会继承父作用域的一切属性和方法且不隔离,当我们在输入框中输入新的内容的时候,指令中的parentname和父作用域的parentname都会被改变,当我们把scope设置成true时,继承父作用域并且进行隔离:即在控制器中进行数据修改只会影响控制器中的parentname而不会影响到父作用域中的parentname,我们也可以将scope设置成独立作用域进行隔离且不继承,,来看设置成独立作用域后的demo:

<div ng-controller="parentCtrl">
        <div>{{parentname}}</div>
        <div test parentname="parentname"></div>
    </div>
    <script src="//cdn.bootcss.com/angular.js/1.3.9/angular.min.js"></script>
    <script>
        var routeApp = angular.module('routeApp', []);
        routeApp.controller('parentCtrl',['$scope',function($scope){
            $scope.parentname = "这里是父级控制器里面的内容";
        }]);
        routeApp.directive('test', function(){
            return {
                scope:{
                    parentname:'='
                },
                template: '<div><div>{{parentname}}</div><input type="text" ng-model="parentname" /></div>',
                link: function($scope, iElm, iAttrs, controller) {
                    
                }
            };
        });
    </script>

        可以看到,写法有些变化,scope:{parentname:'='}使用=实现数据的双向绑定,即在指令中的输入框中输入内容不仅会改变指令中的parentname也会改变父作用域中的parentname。当然,有数据的双向绑定,肯定也会有数据的单项绑定,请看demo:

<div ng-controller="parentCtrl">
        <div>{{parentname}}</div>
        <div test parentname="{{parentname}}"></div>
    </div>
    <script src="//cdn.bootcss.com/angular.js/1.3.9/angular.min.js"></script>
    <script>
        var routeApp = angular.module('routeApp', []);
        routeApp.controller('parentCtrl',['$scope',function($scope){
            $scope.parentname = "这里是父级控制器里面的内容";
        }]);
        routeApp.directive('test', function(){
            return {
                scope:{
                    parentname:'@'
                },
                template: '<div><div>{{parentname}}</div><input type="text" ng-model="parentname" /></div>',
                link: function($scope, iElm, iAttrs, controller) {
                    
                }
            };
        });
    </script>

        这样的话在输入框中输入内容,只会改变控制器中的parentname而不会改变父作用域中的parentname。

angular服务实现控制器之间数据交互

        在ng中,服务是一个单例,所以需要在服务中生成一个对象,该对象就可以利用依赖注入的方式将数据在所有的控制器中进行共享,下面请来看demo:

<div ng-controller="brotherCtrl_first">
        <input type="text" ng-model="test"/>
        <div class="btn" ng-click="change()">click me</div>
    </div>
    <div ng-controller="brotherCtrl_second">
        <div class="btn" ng-click="add()">my name {{name}}</div>
    </div>
    <script src="//cdn.bootcss.com/angular.js/1.3.9/angular.min.js"></script>
    <script>
    var routeApp = angular.module('routeApp', []);
    routeApp.factory('instance',function(){
        return {
            name:''
        }
    });
    routeApp.controller('brotherCtrl_first',['$scope','instance',function($scope, instance) {
        $scope.change = function(){
           instance.name = $scope.test;
       };
    }]);
    routeApp.controller('brotherCtrl_second', ['$scope','instance',function($scope, instance) {
        $scope.add = function() {
            $scope.name = instance.name;
        };
    }]);
    </script>

        在brotherCtrl_first控制器中的输入框中输入内容点击click me 按钮,这个时候会把输入框中的内容存放到服务中,然后我们在brotherCtrl_second控制器中点击按钮,则会从服务中把数据取出来传给name,从而实现数据的交互。

        在angular中的数据交互方式大自是这么几种,如果有说的不好的地方,还请指教。

© 著作权归作者所有

共有 人打赏支持
梅气灶
粉丝 30
博文 15
码字总数 20372
作品 0
杭州
前端工程师
加载中

评论(2)

梅气灶
梅气灶

引用来自“喝豆浆不用吸管”的评论

现在2就快出来了,学习1感觉都虚了
但是2的普及程度目前来说还是比较受限的,而且目前也还在学,至少先把1搞懂了,2再继续,哈哈
boogoogle
boogoogle
现在2就快出来了,学习1感觉都虚了
第214天:Angular 基础概念

一、Angular 简介 1、 什么是 AngularJS - 一款非常优秀的前端高级 JS 框架 - 最早由 Misko Hevery 等人创建 - 2009 年被 Google 公式收购,用于其多款产品 - 目前有一个全职的开发团队继续开...

半指温柔乐
04/04
0
0
读书笔记“使用AngularJs开发下一代web应用”

国内一个挺好的读书笔记 http://www.sunzhongwei.com/angularjs.html 源码下载地址https://github.com/shyamseshadri/angularjs-book Angular SEO http://www.yearofmoo.com/2012/11/angula......

lilugirl
2014/01/06
0
0
Angular 中得 scope 作用域梳理

$scope 的使用贯穿整个 Angular App 应用,它与数据模型相关联,同时也是表达式执行的上下文.有了 $scope 就在视图和控制器之间建立了一个通道,基于作用域视图在修改数据时会立刻更新 $scope,同...

顽Shi
2014/09/21
0
2
5-XHRs(XmlHttpRequest)与依赖注入

足以给应用绑定了硬编码数据集中的三条手机数据,让我们从我们的服务中适配更大的数据集,他使用Angular内建的服务中$htttp。我们将使用Angular的依赖注入给提供服务。 现在有20条手机,从服...

奋斗到天明
2015/08/27
0
0
使用Angular CLI生成的项目结构解说

项目结构 组件,是整个应用的基础。下图是组件的必备元素。 @Component:组件元数据装饰器,简称装饰器。装饰器告诉Angular框架如何处理一个TypeScript类。装饰器包含多个属性,属性的值叫做...

灯下草虫鸣_
2017/10/29
0
0

没有更多内容

加载失败,请刷新页面

加载更多

smart-doc特殊功能使用介绍

smart-doc从8月份底开始开源发布到目前为止已经迭代了几个版本。在这里非常感谢那些敢于用smart-doc去做尝试并积极提出建议的社区用户。因此决定在本博客中重要说明下smart-doc的功能,包括使...

上官胡闹
昨天
0
0
JavaEE——Junit

声明:本栏目所使用的素材都是凯哥学堂VIP学员所写,学员有权匿名,对文章有最终解释权;凯哥学堂旨在促进VIP学员互相学习的基础上公开笔记。 Junit Junit又名单元测试,Junit是用来测试Jav...

凯哥学堂
昨天
0
0
读《美丽新世界》

一、背景 十一国庆节从重庆回深圳的时候,做得绿皮车,路上看了两本书:李笑来的《韭菜的自我修养》和禁书《美丽新世界》。 上篇文章已经分享了 读《韭菜的自我修养》,这篇文章来记录一下《...

tiankonguse
昨天
0
0
archlinux下基于Jenkins,docker实现自动化部署(持续交互)

本文永久更新地址:https://my.oschina.net/bysu/blog/2250954 【若要到岸,请摇船:开源中国 不最醉不龟归】 -----------------------------------第一部分Jenkins的安装与使用-----------...

不最醉不龟归
昨天
0
0
Spark Parquet file split

在实际使用 spark + parquet 的时候, 遇到了两个不解的地方: 我们只有一个 parquet 文件(小于 hdfs block size), 但是 spark 在某个 stage 生成了4个 tasks 来处理. 4个 tasks 中只有一个 ta...

Aaaaaaaron
昨天
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部