一招制敌 - 玩转 AngularJS 指令的 Scope (作用域)【转】

学习了AngularJS好长时间,最近再次回首看看指令这部分的时候,觉得比自己刚开始学习的时候理解的更加深入了,尤其是指令的作用域这部分。

当初看的是《AngularJS权威指南》这本书,但是感觉这本书关于这方面讲的不是很细致,
另外吐槽一下,这本书中文版印刷的质量不是很好,很多地方都有错误;不过讲的还是可以的,是一本学习AngularJS的好书。

下面我们就来详细分析一下指令的作用域。
在这之前希望你对AngularJS的Directive有一定的了解,不然你对下面部分的理解可能会有一点难度。

步入正题:

每当一个指令被创建的时候,都会有这样一个选择,是继承自己的父作用域(一般是外部的Controller提供的作用域或者根作用域($rootScope)),还是创建一个新的自己的作用域,当然AngularJS为我们指令的scope参数提供了三种选择,分别是:false,true,{};默认情况下是false

scope = false

首先我们来看一下,当scope参数被设置为false时有什么情况发生

在这种情况下,在指令模板中可以直接使用父作用域中的变量,函数
首先我们来创建一个指令,代码如下所示:
JS代码:

angular.module("MyApp", [])
    .controller("MyController", function ($scope) {
        //J1 这里我们在作用域里初始化两个变量
    $scope.name = "dreamapple";
    $scope.age = 20;
        //J2 创建一个方法,修改我们创建的对象的年龄
    $scope.changeAge = function () {
        $scope.age = 22;
    }
})
        //J3 创建我们的指令,指令名字为"myDirective"

    .directive("myDirective", function () {
    var obj = {
        //J4   指令的声明模式为 "AE" 属性和元素
        restrict: "AE",
        //J5   指令继承父作用域的属性和方法
        scope: false,
        replace: true,
        template: "<div class=‘my-directive‘>" +
            "<h3>下面部分是我们创建的指令生成的</h3>" +
            "我的名字是:<span ng-bind=‘name‘></span><br/>" +
            "我的年龄是:<span ng-bind=‘age‘></span>" +
            "<input type=‘text‘ ng-model=‘name‘>"+
            " </div>"
    }
    return obj;
});

HTML代码:

<div ng-app="MyApp">
    <div class="container" ng-controller="MyController">
        <div class="my-info">我的名字是:<span ng-bind="name"></span>
        <!-- 使用"ng-bind"防止网络状态不佳时出现没有被赋值表达式   -->
            <br/>我的年龄是:<span ng-bind="age"></span>

        </div>
        <!-- 使用属性声明指令 -->
        <div class="my-directive" my-directive></div>
    </div>
</div>

CSS代码:

div{
    padding: 6px;
}
div.container {
    border: 1px solid black;
}
div.my-info {
    border: 1px solid blue;
}
div.my-directive{
    border: 1px solid green;
}

Online Code Part1点击预览

下面我们来详细解释一下上面的代码:

因为我们将scope的属性设置为false所以,我们创建的指令继承了父作用域的一切属性和方法,这也使得在指令的模板中我们可以使用这些属性和方法。

注意:此时我们在输入框里改变名字,会发现上面的两个名字都发生了变化,你肯定会说,这肯定是这样啊,数据绑定嘛,好,我们接着往下走。

scope = true

当把scope属性设置为true时,这表明我们创建的指令要创建一个新的作用域,这个作用域继承自我们的父作用域。
等等,刚才我们不是说了,当把scope属性值设置为false时,不也是继承我们的父作用域吗?表急,我们接着往下看。

修改上面的JS代码,将指令中的:

scope:false修改为scope:true

然后我们再试着在我们的input输入框中写一些字符串,会发现,指令中的那个name发生了变化,但是指令外的那个name却没有发生变化,这说明了一个问题。

  1. 当我们将scope设置为true的时候,我们就新创建了一个作用域,只不过这个作用域是继承了我们的父作用域;我觉得可以这样理解,我们新创建的作用域是一个新的作用域,只不过在初始化的时候,用了父作用域的属性和方法去填充我们这个新的作用域。它和父作用域不是同一个作用域。
  2. 当我们将scope设置为false的时候,我们创建的指令和父作用域(其实是同一个作用域)共享同一个model模型,所以在指令中修改模型数据,它会反映到父作用域的模型中。
    Online Code Part2点击预览

scope = {}

下面我们要进入一个好玩的部分,当我们将scope的属性设置为{}时,我们可以做更多的事情。

AngularJS最强的大的地方之一就是它可以构建组建,无论放在哪里都是可以使用的;
这所以可以做到这些,不得不归功于指令的这个属性;当我们将scope设置为{}时,意味着我们创建的一个新的与父作用域隔离的新的作用域,这使我们在不知道外部环境的情况下,就可以正常工作,不依赖外部环境。

当然首先我们还是要给出我们的例子,先看代码,我们修改了上述的JS代码和HTML代码
JS代码:

angular.module("MyApp", [])
    .controller("MyController", function ($scope) {
    $scope.name = "dreamapple";
    $scope.age = 20;
    $scope.changeAge = function(){
        $scope.age = 0;
    }
})
    .directive("myDirective", function () {
    var obj = {
        restrict: "AE",
        scope: {
            name: ‘@myName‘,
            age: ‘=‘,
            changeAge: ‘&changeMyAge‘
        },
        replace: true,
        template: "<div class=‘my-directive‘>" +
            "<h3>下面部分是我们创建的指令生成的</h3>" +
            "我的名字是:<span ng-bind=‘name‘></span><br/>" +
            "我的年龄是:<span ng-bind=‘age‘></span><br/>" +
            "在这里修改名字:<input type=‘text‘ ng-model=‘name‘><br/>" +
            "<button ng-click=‘changeAge()‘>修改年龄</button>" +
            " </div>"
    }
    return obj;
});

HTML代码:

<div ng-app="MyApp">
    <div class="container" ng-controller="MyController">
        <div class="my-info">我的名字是:<span ng-bind="name"></span>

            <br/>我的年龄是:<span ng-bind="age"></span>
            <br />
        </div>
        <div class="my-directive" my-directive my-name="{{name}}" age="age"  change-my-age="changeAge()"></div>
    </div>
</div>

Online Code Part3点击预览

我们使用了隔离的作用域,不代表我们不可以使用父作用域的属性和方法。

  1. 我们可以通过向scope{}中传入特殊的前缀标识符(即prefix),来进行数据的绑定。
  2. 在创建了隔离的作用域,我们可以通过@,&,=引用应用指令的元素的属性,如上面的代码那样,我们可以在<div class="my-directive" my-directive my-name="{{name}}" age="age" change-my-age="changeAge()"></div>这个元素中,利用前缀标识符通过使用属性my-name,age,change-my-age来引用这些属性的值。

下面我们来看看如何使用这些前缀标识符:

@

这是一个单项绑定的前缀标识符
使用方法:在元素中使用属性,好比这样<div my-directive my-name="{{name}}"></div>,注意,属性的名字要用-将两个单词连接,因为是数据的单项绑定所以要通过使用{{}}来绑定数据。

=

这是一个双向数据绑定前缀标识符
使用方法:在元素中使用属性,好比这样<div my-directive age="age"></div>,注意,数据的双向绑定要通过=前缀标识符实现,所以不可以使用{{}}

&

这是一个绑定函数方法的前缀标识符
使用方法:在元素中使用属性,好比这样<div my-directive change-my-age="changeAge()"></div>,注意,属性的名字要用-将多个个单词连接。

注意:在新创建指令的作用域对象中,使用属性的名字进行绑定时,要使用驼峰命名标准,比如下面的代码。

scope: {
            // `myName` 就是原来元素中的`my-name`属性
            name: ‘@myName‘,
            age: ‘=‘,
            // `changeMyAge`就是原来元素中的`change-my-age`属性
            changeAge: ‘&changeMyAge‘
        }

进一步说明,我们的指令是如何利用这些前缀标识符来寻找我们想要的属性或者函数的?

  • @ 当指令编译到模板的name时,就会到scope中寻找是否含有name的键值对,如果存在,就像上面那样,看到@就知道这是一个单向的数据绑定,然后寻找原来的那个使用指令的元素上(或者是指令元素本身)含有这个值的属性即my-name={{name}},然后在父作用域查找{{name}}的值,得到之后传递给模板中的name
  • =&@差不多,只不过=进行的是双向的数据绑定,不论模板还是父作用域上的属性的值发生改变都会使另一个值发生改变,而&是绑定函数而已。

转自: http://segmentfault.com/a/1190000002773689

时间: 2024-12-28 10:31:02

一招制敌 - 玩转 AngularJS 指令的 Scope (作用域)【转】的相关文章

一招制敌 - 玩转 AngularJS 指令的 Scope (作用域),讲得特别好

学习了AngularJS挺长时间,最近再次回首看看指令这部分的时候,觉得比自己刚开始学习的时候理解的更加深入了,尤其是指令的作用域这部分. 步入正题: 每当一个指令被创建的时候,都会有这样一个选择,是继承自己的父作用域(一般是外部的Controller提供的作用域或者根作用域($rootScope)),还是创建一个新的自己的作用域,当然AngularJS为我们指令的scope参数提供了三种选择,分别是:false,true,{}:默认情况下是false. scope = false 首先我们来看

AngularJS 指令的 Scope (作用域)

指令被创建AngularJS为我们指令的scope参数提供了三种选择,分别是:false,true,{}:默认情况下是false. 1.scope = false,在这种情况下,在指令模板中可以直接使用父作用域中的变量,创建的指令和父作用域(其实是同一个作用域)共享同一个model模型,所以在指令中修改模型数据,它会反映到父作用域的模型中. 2.scope = true,当把scope属性设置为true时,这表明我们创建的指令要创建一个新的作用域,这个作用域继承自我们的父作用域,它和父作用域不是

angularJs指令的Scope(作用域)

每当一个指令被创建的时候,都会有这样一个选择,是继承自己的父作用域(一般是外部的Controller提供的作用域或者根作用域($rootScope)),还是创建一个新的自己的作用域,当然AngularJS为我们指令的scope参数提供了三种选择,分别是:false,true,{}:默认情况下是false. 1.scope = false JS 代码: html 代码: result: 修改文本框的内容,两个名字都会变,实际上修改的是同一个$scope的name属性. 2. scope=true

Angularjs MVC 以及 $scope 作用域 Angularjs 模块 的 run 方法 以及依赖注入中代码压缩问题

Angularjs MVC 以及 $scope 作用域 Angularjs 模块的 run 方法 以及依赖注入中代码压缩问题 1. Angularjs MVCModel:数据模型层View:视图层,负责展示Controller:业务逻辑和控制逻辑优点: 代码模块化 代码逻辑比较清晰.可移值性高,后期维护方便.代码复用,代码规模越来越大的时候,切分职责是大势所趋缺点:运行效率稍微低一些2. Angularjs $scope 作用域1. $scope 多控制器单独作用域<!DOCTYPE html>

Android AppUasge统计一招制敌

Tamic/文 http://blog.csdn.net/sk719887916/article/details/71105441 Google从 API 21 新增了接口 android.app.usage , 通过这个api我们可以统计到每个app的使用情况,启动次数,启动时间等,也可以判断是否前后台,比较方便,今天就来深入的学习一下 . Google从 API 21 新增了接口 android.app.usage , 通过这个api我们可以统计到每个app的使用情况,启动次数,启动时间等,

angularJS MVC及$scope作用域

原文地址:https://www.cnblogs.com/hwgok/p/10903344.html

AngularJS指令中的compile与link函数解析

AngularJS指令中的compile与link函数解析 通常大家在使用ng中的指令的时候,用的链接函数最多的是link属性,下面这篇文章将告诉大家complie,pre-link,post-link的用法与区别. 原文地址 angularjs里的指令非常神奇,允许你创建非常语义化以及高度重用的组件,可以理解为web components的先驱者. 网上已经有很多介绍怎么使用指令的文章以及相关书籍,相互比较的话,很少有介绍compile与link的区别,更别说pre-link与post-lin

angularjs指令中的compile详解

篇文章主要介绍了angularjs指令中的compile与link函数详解,本文同时诉大家complie,pre-link,post-link的用法与区别等内容,需要的朋友可以参考下 通常大家在使用ng中的指令的时候,用的链接函数最多的是link属性,下面这篇文章将告诉大家complie,pre-link,post-link的用法与区别. angularjs里的指令非常神奇,允许你创建非常语义化以及高度重用的组件,可以理解为web components的先驱者. 网上已经有很多介绍怎么使用指令的

JavaScript强化教程——AngularJS 指令

本文为 H5EDU 机构官方 HTML5培训 AngularJS 通过被称为 指令 的新属性来扩展 HTML. AngularJS 通过内置的指令来为应用添加功能. AngularJS 允许你自定义指令. AngularJS 指令 AngularJS 指令是扩展的 HTML 属性,带有前缀 ng-. ng-app 指令初始化一个 AngularJS 应用程序. ng-init 指令初始化应用程序数据. ng-model 指令把元素值(比如输入域的值)绑定到应用程序. 完整的指令内容可以参阅 An