AngularJs之Scope作用域(详解)

AngularJS Scope(作用域) 在AngularJS中,Scope是一个对象,它充当视图(HTML)和控制器(JavaScript)之间的胶水。Scope是表达式执行的上下文,是存储模型的地方。每当在视图中绑定一个表达式时,AngularJS会在相应的Scope中查找该表达式的值。 阅读详情

一、什么是scope

  AngularJS 中,作用域是一个指向应用模型的对象,它是表达式的执行环境。作用域有层次结构,这个层次和相应的 DOM 几乎是一样的。作用域能监控表达式和传递事件。

  在 HTML 代码中,一旦一个 ng-app 指令被定义,那么一个作用域就产生了,由 ng-app 所生成的作用域比较特殊,它是一个根作用域($rootScope),它是其他所有$Scope 的最顶层。

  除了用 ng-app 指令可以产生一个作用域之外,其他的指令如 ng-controller,ng-repeat 等都会产生一个或者多个作用域。此外,还可以通过 AngularJS 提供的创建作用域的工厂方法来创建一个作用域。这些作用域都拥有自己的继承上下文,并且根作用域都为$rootScope。

  在生成一个作用域之后,在编写 AngularJS 代码时,$scope 对象就代表了这个作用域的数据实体,我们可以在$scope 内定义各种数据类型,之后可以直接在 HTML 中以 {{变量名}} 方式来让 HTML 访问到这个变量。

二、继承作用域

 AngularJS 在创建一个作用域时,会检索上下文,如果上下文中已经存在一个作用域,那么这个新创建的作用域就会以 JavaScript 原型继承机制继承其父作用域的属性和方法。

  一些 AngularJS 指令会创建新的子作用域,并且进行原型继承: ng-repeat、ng-include、ng-switch、ng-view、ng-controller, 用 scope: true 和 transclude: true 创建的 directive。

  以下 HTML 中定义了三个作用域,分别是由 ng-app 指令所创建的$rootScope,parentCtrl 和 childCtrl 所创建的子作用域,这其中 childCtrl 生成的作用域又是 parentCtrl 的子作用域。

三、作用域的继承实例

<!doctype html>
<html>
<head>
    <meta charset=utf-8"/>
    <title>scope nick</title>
    <script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"></script>
</head>
<script type="text/javascript">
    angular.module('app', [])
            .controller('parentCtrl', ['$scope', function($scope) {
                $scope.args= 'Nick DeveloperWorks';
            }])
            .controller('childCtrl', ['$scope', function($scope) {
                $scope.args= 'Nick DeveloperWorks for test';
            }]);
</script>
<body ng-app="app">
<div ng-controller="parentCtrl">
    <input ng-model="args">
    <div ng-controller="childCtrl">
        <input ng-model="args">
    </div>
</div>
</body>
</html>

  继承作用域符合 JavaScript 的原型继承机制,这意味着如果我们在子作用域中访问一个父作用域中定义的属性,JavaScript 首先在子作用域中寻找该属性,没找到再从原型链上的父作用域中寻找,如果还没找到会再往上一级原型链的父作用域寻找。在 AngularJS 中,作用域原型链的顶端是$rootScope,AnguarJS 将会寻找到$rootScope 为止,如果还是找不到,则会返回 undefined。

  我们用实例代码说明下这个机制。首先,我们探讨下对于原型数据类型的作用域继承机制:

<!doctype html>
<html>
<head>
    <meta charset=utf-8"/>
    <title>scope nick</title>
    <script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"></script>
</head>
<script type="text/javascript">
    angular.module('app', [])
            .controller('parentCtrl', ['$scope', function($scope) {
                $scope.args = 'Nick DeveloperWorks';
            }])
            .controller('childCtrl', ['$scope', function($scope) {
            }]);
</script>
<body ng-app="app">
<div ng-controller="parentCtrl">
    <input ng-model="args">
    <div ng-controller="childCtrl">
        <input ng-model="args">
    </div>
</div>
</body>
</html>

测试运行结果:

第一个输入框:

  虽然在 childCtrl 中没有定义具体的 args 属性,但是因为 childCtrl 的作用域继承自 parentCtrl 的作用域,因此,AngularJS 会找到父作用域中的 args 属性并设置到输入框中。而且,如果我们在第一个输入框中改变内容,内容将会同步的反应到第二个输入框。

第二个输入框:

  第二个输入框的内容从此将不再和第一个输入框的内容保持同步。在改变第二个输入框的内容时,因为 HTML 代码中 model 明确绑定在 childCtrl 的作用域中,因此 AngularJS 会为 childCtrl 生成一个 args 原始类型属性。这样,根据 AngularJS 作用域继承原型机制,childCtrl 在自己的作用域找得到 args 这个属性,从而也不再会去寻找 parentCtrl 的 args 属性。从此,两个输入框的内容所绑定的属性已经是两份不同的实例,因此不会再保持同步。

现将代码做如下修改,结合以上两个场景,会出现怎样的结果?

<!doctype html>
<html>
<head>
    <meta charset=utf-8"/>
    <title>scope nick</title>
    <script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"></script>
</head>
<script type="text/javascript">
    angular.module('app', [])
            .controller('parentCtrl', ['$scope', function($scope) {
                $scope.args = {};
                $scope.args.content = 'Nick DeveloperWorks';
            }])
            .controller('childCtrl', ['$scope', function($scope) {
            }]);
</script>
<body ng-app="app">
<div ng-controller="parentCtrl">
    <input ng-model="args.content">
    <div ng-controller="childCtrl">
        <input ng-model="args.content">
    </div>
</div>
</body>
</html>

测试结果是无论改变任何一个输入框的内容,两者的内容始终同步。

  根据 AngularJS 的原型继承机制,如果 ng-model 绑定的是一个对象数据,那么 AngularJS 将不会为 childCtrl 创建一个 args 的对象,自然也不会有 args.content 属性。这样,childCtrl 作用域中将始终不会存在 args.content 属性,只能从父作用域中寻找,也即是两个输入框的的变化其实只是在改变 parentCtrl 作用域中的 args.content 属性。因此,两者的内容始终保持同步。

  我们再看一个例子,分析结果如何。


<!doctype html>
<html>
<head>
    <meta charset=utf-8"/>
    <title>scope nick</title>
    <script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"></script>
</head>
<script type="text/javascript">
    angular.module('app', [])
            .controller('parentCtrl', ['$scope', function($scope) {
                $scope.args = {};
                $scope.args.content = 'Nick DeveloperWorks';
            }])
            .controller('childCtrl', ['$scope', function($scope) {
                $scope.args = {};
                $scope.args.content = 'Nick DeveloperWorks for test';
            }]);
</script>
<body ng-app="app">
<div ng-controller="parentCtrl">
    <input ng-model="args.content">
    <div ng-controller="childCtrl">
        <input ng-model="args.content">
    </div>
</div>
</body>
</html>

 测试结果是两个输入框的内容永远不会同步。子作用域有实例数据对象,则不访问父作用域。

四、独立作用域

angular.module('isolate', []).directive("isolate", function () {
 return {
 scope : {},
 };
})
  独立作用域最大的特点是不会原型继承其父作用域,对外界的父作用域保持相对的独立。因此,如果在定义了孤立作用域的 AngularJS directive 中想要访问其父作用域的属性,则得到的值为 undefined。代码如下:
<!doctype html>
<html>
<head>
    <meta charset=utf-8"/>
    <title>scope nick</title>
    <script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"></script>
</head>
<script type="text/javascript">
    angular.module('app', [])
            .controller('ctrl', ['$scope', function($scope) {
                $scope.args = {};
            }])
            .directive("isolateDirective", function () {
                return {
                    scope : {},
                    link : function($scope, $element, $attr) {
                        console.log($scope.$args); //输出 undefined
                    }
                };
            });
</script>
<body ng-app="app">
<div ng-controller="ctrl">
    <div isolate-directive></div>
</div>
</body>
</html>
上面的代码中通过在 directive 中声明了 scope 属性从而创建了一个作用域,其父作用域为 ctrl 所属的作用域。但是,这个作用域是孤立的,因此,它访问不到父作用域的中的任何属性。存在这样设计机制的好处是:能够创建出一些列可复用的 directive,这些 directive 不会相互在拥有的属性值上产生串扰,也不会产生任何副作用。

五、AngularJS 独立作用域的数据绑定

 在继承作用域中,我们可以选择子作用域直接操作父作用域数据来实现父子作用域的通信,而在独立作用域中,子作用域不能直接访问和修改父作用域的属性和值。为了能够使孤立作用域也能和外界通信,AngularJS 提供了三种方式用来打破独立作用域“孤立”这一限制。单向绑定(@ 或者 @attr)

  这是 AngularJS 独立作用域与外界父作用域进行数据通信中最简单的一种,绑定的对象只能是父作用域中的字符串值,并且为单向只读引用,无法对父作用域中的字符串值进行修改,此外,这个字符串还必须在父作用域的 HTML 节点中以 attr(属性)的方式声明。

  使用这种绑定方式时,需要在 directive 的 scope 属性中明确指定引用父作用域中的 HTML 字符串属性,否则会抛异常。示例代码如下:

<!doctype html>
<html>
<head>
    <meta charset=utf-8"/>
    <title>scope nick</title>
    <script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"></script>
</head>
<script>
    angular.module('isolateScope', [])
            .directive("isolateDirective", function () {
                return {
                    replace : true,
                    template: '<button>{{isolates}}</button>',
                    scope : {
                        isolates : '@',
                    },
                    link : function($scope, $element, $attr) {
                        $scope.isolates = "DeveloperWorks";//无效
                    }
                };
            })
            .controller("ctrl", function ($scope) {
                $scope.btns = 'NICK';
            });
</script>
<body ng-app="isolateScope" >
<div ng-controller="ctrl">
    <button>{{btns}}</button>
    <div isolate-directive isolates="{{btns}}"></div>
</div>
</body>
</html>

上面的代码,通过在 directive 中声明了 scope:{isolates:'@'} 使得 directive 拥有了父作用域中 data-isolates (isolates为自定义属性,不加data也可以,但建议加上data)这个 HTML 属性所拥有的值,这个值在控制器 ctrl 中被赋值为'nick'。所以,代码的运行结果是页面上有两个名为 nick的按钮。

  我们还注意到 link 函数中对 isolates 进行了修改,但是最终不会在运行结果中体现。这是因为 isolates 始终绑定为父作用域中的 btns 字符串,如果父作用域中的 btns 不改变,那么在孤立作用域中无论怎么修改 isolates 都不会起作用。引用绑定(&或者&attr)

  通过这种形式的绑定,孤立作用域将有能力访问到父作用域中的函数对象,从而能够执行父作用域中的函数来获取某些结果。这种方式的绑定跟单向绑定一样,只能以只读的方式访问父作用函数,并且这个函数的定义必须写在父作用域 HTML 中的 attr(属性)节点上。

  这种方式的绑定虽然无法修改父作用域的 attr 所设定的函数对象,但是却可以通过执行函数来改变父作用域中某些属性的值,来达到一些预期的效果。示例代码如下:

<!doctype html>
<html>
<head>
    <meta charset=utf-8"/>
    <title>scope nick</title>
    <script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"></script>
</head>
<script>
    angular.module('isolateScope', [])
            .directive("isolateDirective", function () {
                return {
                    replace : true,
                    scope : {
                        isolates : '&',
                    },
                    link : function($scope, $element, $attr) {
                        var func = $scope.isolates();
                        func();
                    }
                };
            })
            .controller("ctrl", function ($scope) {
                $scope.func = function () {
                    console.log("Nick DeveloperWorks");
                }
            });
</script>
<body ng-app="isolateScope" >
<div ng-controller="ctrl">
    <div isolate-directive data-isolates="func"></div>
</div>
</body>
</html>

这个例子中,浏览器的控制台将会打印“Nick DeveloperWorks”文字。

  上面的代码中我们在父作用域中指定了一个函数对象$scope.func,在孤立作用域中通过对 HTML 属性的绑定从而引用了 func。需要注意的是 link 函数中对 func 对象的使用方法,$scope.isolates 获得的仅仅是函数对象,而不是调用这个对象,因此我们需要在调用完$scope.isolates 之后再调用这个函数,才能得到真正的执行结果。双向绑定(=或者=attr)双向绑定赋予 AngularJS 孤立作用域与外界最为自由的双向数据通信功能。在双向绑定模式下,孤立作用域能够直接读写父作用域中的属性和数据。和以上两种孤立作用域定义数据绑定一样,双向绑定也必须在父作用域的 HTML 中设定属性节点来绑定。

双向绑定非常适用于一些子 directive 需要频繁和父作用域进行数据交互,并且数据比较复杂的场景。不过,由于可以自由的读写父作用域中的属性和对象,所以在一些多个 directive 共享父作用域数据的场景下需要小心使用,很容易引起数据上的混乱。

示例代码如下:

<!doctype html>
<html>
<head>
    <meta charset=utf-8"/>
    <title>scope nick</title>
    <script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"></script>
</head>
<script>
    angular.module('isolateScope', [])
            .directive("isolateDirective", function () {
                return {
                    replace : true,
                    template: '<button>{{isolates}}</button>',
                    scope : {
                        isolates : '=',
                    },
                    link : function($scope, $element, $attr) {
                        $scope.isolates.name = "NICK";
                    }
                };
            })
            .controller("ctrl", function ($scope) {
                $scope.btns = {
                    name : 'nick',
                    dw : 'DeveloperWorks'
                };
            });
</script>
<body ng-app="isolateScope" >
<div ng-controller="ctrl">
    <button>{{btns.dw}}</button>
    <button>{{btns.name}}</button>
    <div isolate-directive data-isolates="btns"></div>
</div>
</body>
</html>

上面的代码运行的结果是浏览器页面上出现三个按钮,其中第一个按钮标题为“DeveloperWorks”,第二和第三个按钮的标题为“NICK”。

初始时父作用域中的$scope.btns.name为小写的“nick”,通过双向绑定,孤立作用域中将父作用域的 name改写成为大写的“NICK”并且直接生效,父作用域的值被更改。








AngularJS Scope(作用域) 在AngularJS中,Scope是一个具有属性和函数的对象,它代表了应用中的模型。每个AngularJS指令都有自己的作用域,而每个控制器也都有自己的作用域。作用域的主要目的是隔离数据,确保它们不会在全局作用域中互相干扰。AngularJS的作用域是理解其工作原理的关键部分。通过理解作用域的定义、作用、生命周期以及如何使用它,我们可以更好地构建和维护AngularJS应用。本文深入探讨了AngularJS的作用域,并提供了示例来帮助读者更好地理解这一概念。 阅读详情

相关推荐

AngularJS 中的作用域(scope)概述

作用域(scope)是AngularJS中一个重要的概念,它定义了在AngularJS应用程序中的变量和函数的可访问范围。本文将详细介绍AngularJS中的作用域(scope)概念,并提供相应的源代码示例。以上是关于AngularJS中作用域(scope)的概述和示例代码。作用域是AngularJS中非常重要的概念,它决定了变量和函数的可见性和生命周期。在子控制器中,我们修改了父作用域中的。在上面的代码中,我们给作用域(scope)对象添加了一个名为。在上面的代码中,我们创建了一个名为。

PixelLoom的博客 281

AngularJs之Scope作用域

前言: 上篇博文AngularJs之directive中说了Scope作用域是个大坑,所以拿出来作为重点总结! 什么是scope   AngularJS 中,作用域是一个指向应用模型的对象,它是表达式的执行环境。作用域有层次结构,这个层次和相应的 DOM 几乎是一样的。作用域能监控表达式和传递事件。   在 HTML 代码中,一旦一个 ng-app 指令被定义,那么一个作用域就产生了,由 ...

weixin_30781433的博客 248

深信服桌面云实战:从零部署到高效运维的配置全景指南

本文详细介绍了深信服桌面云从零部署到高效运维的全流程配置指南,涵盖硬件规划、平台部署、虚拟桌面发布、终端管理及性能优化等关键环节。特别强调了双万兆网络架构、分布式存储配置和智能调度功能的应用,帮助用户实现高性能、高可用的虚拟桌面环境。

weixin_28568819的博客 395

AngularJS Scope 的概念、特性和用法

Scope(作用域)是 AngularJS 框架中的一个重要概念,用于描述应用中的数据模型。它是一个 JavaScript 对象,包含了应用中的数据和方法。Scope 建立了控制器和视图之间的连接,通过双向数据绑定实现数据的自动更新。

网络技术联盟站 531

当LightGBM推理遇上GPU:3种替代方案性能对比(含ONNX实战代码)

本文针对LightGBM官方不支持GPU推理的性能瓶颈,深度评测了RAPIDS cuML、ONNX Runtime GPU和Triton Inference Server三种GPU加速推理替代方案。通过详尽的性能对比和实战代码,为高并发、低延迟的在线预测场景提供了清晰的选型指南,帮助工程师打破推理性能枷锁,实现显著的吞吐量提升。

salt9的博客 812

使用pytorch构建LSTM_AE模型的两种方式

2.基本LSTM_Unit计算——基本LSTM_AE结构 3.自定义LSTM_Unit计算——自定义LSTM_AE结构 1.LSTM-Encoder-Decoder模型结构及简要解析 图基本lstm计算单元

qq_37840762的博客 7273

angularJS 通过scopeId 获取scope

angularJs 中每一个scope都会有一个自身的iD,可通过本地浏览器console.log打印查看. //通过ID获取Scope function getScopeById(id) { var element; $('.ng-scope').each(function(){ var scope = angular.element(this).scope

qq_33460562的博客 1725

python 常见算法(1-50题)

常见的算法题

weixin_58470558的博客 1755

JavaScript:AngularJS Scope(作用域)

Scope(作用域) 是应用在 HTML (视图) 和 JavaScript (控制器)之间的纽带。 Scope 是一个对象,有可用的方法和属性。 Scope 可应用在视图和控制器上。

君逍遥o 517

从拆箱到跑通:Intel RealSense D435i开箱实测+ROS驱动配置全流程

本文详细记录了Intel RealSense D435i深度相机的开箱体验,并提供了在Ubuntu 22.04与ROS2 Humble环境下,从安装librealsense2 SDK到配置ROS2驱动的完整流程。重点解决了驱动安装、数据流发布、点云对齐以及IMU数据融合等关键步骤,帮助研究者和开发者快速实现D435i与机器人系统的集成。

weixin_29168393的博客 304

《SOC架构-ARM架构-文档导读》-目录

小白请看“Armv8/Armv9架构从入门到精通”专栏。以翻译为主的,深度深度深度深度/深入深入深入 学习ARM架构的文章。

baron-周贺贺-代码改变世界ctw 2083

AngularJS 指令的 Scope 作用域的详解

在理解scope作用域过程中,网上查找资料,找到一篇写的很详细,容易理解的文字,下面是链接,分享一下~一招制敌 - 玩转 AngularJS 指令的 Scope (作用域)

泠泠似水 320

UG\NX二次开发 一个创建小平面体的例子

介绍。

王牌飞行员_里海的博客 443

理解AngularJS的作用域Scope

2013年8月2日, 严清 译 译文:理解AngularJS的作用域Scope 原文:Understanding Scopes 概叙: AngularJS中,子作用域一般都会通过JavaScript原型继承机制继承其父作用域的属性和方法。但有一个例外:在directive中使用scope: { ... },这种方式创建的作用域是一个独立的"Isolate"作用域,它也有父作用域,但

大爱无疆的博客 2240

AI Agent Harness Engineering 开发效率工具:Prompt工程、调试与监控平台

随着AI Agent技术从原型探索走向企业级落地,开发者普遍面临Prompt迭代无版本管控、Agent执行黑盒无法定位错误、上线后无监控导致故障频发、多团队协作效率低下四大核心痛点,据2024年LLMOps行业报告显示,没有配套工具链的Agent开发团队平均迭代周期是有工具链团队的6倍,线上故障率高达23%,平均资源浪费超过60%。

小白菜的博客 423

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

angularJs 之 Scope(作用域)

<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Scope(作用域)</title> <script src="js/Angular.js"></script> </head> <body> <div ng-app="scopeApp" i

海阔天空 314

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

深入理解AngularJS--Scope(作用域)

Scope(作用域)是应用在HTML(视图)和JavaScript(控制器)之间的纽带。 Scope是一个对象,有可用的方法和属性。 Scope可应用在视图和控制器上。 一、如何使用Scope 当你在AngularJS创建控制器时,你可以将$scope对象当作一个参数传递: 控制器中的属性对应了视图上的属性: <div ng-app="myApp" ng-controller="myCtrl"> <h1>{{carname}}</h1> </d

qq_26780317的博客 600

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

AngularJS Scope(作用域)+控制器+过滤器

AngularJSScope(作用域) Scope(作用域) 是应用在 HTML (视图) 和 JavaScript (控制器)之间的纽带。 Scope 是一个对象,有可用的方法和属性。 Scope 可应用在视图和控制器上。 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <...

zyl042的博客 194
上一篇: HTML5对手机页面长按会粘贴复制禁用的解决方法(常用)
下一篇: Angularjs中ng-select和ng-options的用法详解
拼搏的小叔
博客等级 码龄10年 56粉丝 61原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值