GVKun编程网logo

AngularJS:$ observe和$ watch方法之间的区别(angular watch的用法)

24

在这里,我们将给大家分享关于AngularJS:$observe和$watch方法之间的区别的知识,让您更了解angularwatch的用法的本质,同时也会涉及到如何更有效地AngularJs$par

在这里,我们将给大家分享关于AngularJS:$ observe和$ watch方法之间的区别的知识,让您更了解angular watch的用法的本质,同时也会涉及到如何更有效地AngularJs $parse、$eval和$observe、$watch详解、angularJS $scope的$watch方法监听model改变、Angularjs $watch使用方法、AngularJS 1,AngularJS 2,Vue 1 ,Vue 2, React之间的区别和优劣势比较的内容。

本文目录一览:

AngularJS:$ observe和$ watch方法之间的区别(angular watch的用法)

AngularJS:$ observe和$ watch方法之间的区别(angular watch的用法)

我知道,无论WatchersObservers就将计算在东西$scope在AngularJS变化。但是无法理解两者之间到底有什么区别。

我最初的理解是Observers为角表达式计算的,这些角表达式是HTML端在Watchers执行$scope.$watch()函数时所执行的条件。我的想法是否正确?

答案1

小编典典

$observe()
是Attributes对象上的一种方法,因此,它只能用于观察/监视DOM属性的值更改。仅用于/调用内部指令。当您需要观察/观察包含插值的DOM属性(即{{}})时,请使用$observe。例如,attr1="Name: {{name}}"然后在指令中:attrs.$observe(''attr1'', ...)。 (如果您尝试scope.$watch(attrs.attr1, ...)使用{{}},则无法undefined使用-您会得到的。)将$watch用于其他所有内容。

$ watch()
更复杂。它可以观察/观察“表达式”,其中表达式可以是函数或字符串。如果表达式是字符串,则将$parse’d(即,作为Angular表达式求值)放入函数中。(每个摘要周期都会调用此函数。)字符串表达式不能包含{{}}。$
watch是[Scope]对象上的一种方法,因此只要您可以访问Scope对象,就可以使用/调用它,因此在

  • 一个控制器-任何控制器-一个通过ng-view,ng-controller或指令控制器创建的控制器
  • 指令中的链接函数,因为它也可以访问作用域

因为字符串是作为Angular表达式求值的,所以当您要观察/观察模型/作用域属性时,通常使用$
watch。例如,attr1="myModel.some_prop"然后在控制器或链接功能中:scope.$watch(''myModel.some_prop'',...)scope.$watch(attrs.attr1, ...)(或scope.$watch(attrs[''attr1''], ...))。
(如果尝试attrs.$observe(''attr1''),将得到字符串myModel.some_prop,这可能不是您想要的。)

如对@PrimosK答案的评论中所述,每个摘要周期都会检查所有$observes和$ watches 。

具有单独作用域的指令更加复杂。如果使用“@”语法,则可以$observe或$watch包含插值(即{{}})的DOM属性。(它与$watch一起使用的原因是因为’@’语法为我们进行了插值,因此$
watch看到的字符串中没有{{}}。)为了更容易记住何时使用哪个字符串,我建议使用$在这种情况下也要观察。

为了帮助测试所有这些,我编写了一个Plunker,它定义了两个指令。一个(d1)不创建新的作用域,另一个(d2)创建隔离的作用域。每个指令具有相同的六个属性。每个属性都是$observe’d和$ watch’ed。

<div d1 attr1="{{prop1}}-test" attr2="prop2" attr3="33" attr4="''a_string''"        attr5="a_string" attr6="{{1+aNumber}}"></div>

查看控制台日志以查看链接功能中$observe和$watch之间的区别。然后单击链接,查看单击处理程序所做的属性更改触发了哪些$ observes和$watches。

请注意,在运行链接功能时,尚未评估任何包含{{}}的属性(因此,如果您尝试检查这些属性,则会得到undefined)。查看插值的唯一方法是使用$observe(如果使用带’@’的隔离范围,则使用$watch)。因此,获取这些属性的值是 异步 操作。(这就是为什么我们需要$ observe和$watch函数。)

有时您不需要$ observe或$watch。例如,如果您的属性包含数字或布尔值(不是字符串),则只需对其进行一次评估:attr1="22",然后在您的链接函数:中进行评估varcount=scope.$eval(attrs.attr1)。如果它只是一个常量字符串– attr1="mystring"–则只需attrs.attr1在您的指令中使用(不需要$ eval())。

AngularJs $parse、$eval和$observe、$watch详解

AngularJs $parse、$eval和$observe、$watch详解

$parse和$eval

$parse和$eval这两个函数都可以解析表达式的值.

它们的区别在于$parse是一个服务, 可以注入使用. $eval是scope对象上的一个方法, 我们只能在能访问scope的场景下使用它.

var getter = $parse(''user.name'');
var setter = getter.assign;
var context = {user: {name: ''John Doe''};
var locals = {user: {name: ''Doe John''};

getter(context); //John Doe
setter(context, ''new name'');
getter(context); //new name
getter(context, locals); //Doe John

$parse服务接收一个表达式作为参数并返回一个函数. 这个函数可以被调用, 其中的参数是一个context对象, 通常来说是作用域.
另外, 这个函数有一个assign属性. 它也是一个函数, 可以用来在给定的上下文中改变这个表达式的值. 最后一行代码演示了如何使用locals来覆盖context对象.

$eval用起来要简单很多, 因为它的上下文已经被指定为scope对象.

var scope = $rootscope.$new(true);
scope.a = 1;
scope.b = 2;
scope.$eval(''a + b'')//3
scope.$eval(function(scope){
 return scope.a + scope.b;
});//3

关于$parse和$eval之间的关系, 我们能从Angular源码中看出来, 可以说$eval是为了让$parse在scope中使用更方便的语法糖.

$eval: function(expr, locals){
 return $parse(expr)(this, locals);
}

$eval还有个同胞兄弟, $evalAsync, 它并不会立刻计算表达式的值, 而是将表达式缓存起来, 等到下一次$digest ( 脏检查 ) 的时候执行. 以获取更好的性能.

$observe和$watch

$observe和$watch都可以监听表达式值的变化. 但有显著的不同.
$observe是angular指令中link函数第三个参数 ( attrs ) 的一个方法. 只能在指令的link函数中使用它. 它是通过$evalAsync函数实现监控的.

$watch是scope对象上的一个方法, watch表达式很灵活, 可以是一个函数, 可以是scope上的属性, 也可以是一个字符串形式的表达式. 监听scope上的属性名或表达式的时候, 会利用$parse服务将表达式转换成一个函数, 这个函数会在$digest中被调用. $watch的第三个参数"objectEquality", 指定比较对象的方式, 如果为true,则用angular.equals, 否则直接比较引用. 默认为false.

//html
<div book="{{book.name}}"></div>
//js
attrs.$observe(''book'', function(newValue){
 //just have one parameter, can''t get old value
});
scope.$watch(attrs.book, function(newValue, oldValue){
 //get undefined
});

当你需要监听一个包含"{{}}"的DOM属性时, 使用$observe, 如果用$watch, 只能得到undefined. 反之, 就用$watch. 如果用$observe, 只能得到一个固定的字符串.

//html
<div book="book.name"></div>
//js
attrs.$observe(''book'', function(newValue){
 //always get ''book.name''
});
scope.$watch(attrs.book, function(newValue, oldValue){
});

有一个特殊的情况, 当你的指令使用了独立的作用域 ( scope:{} ) , 那些应用了"@"语法的DOM属性, 即使包含"{{ }}", 也可以被$watch.

因为@前缀标识符, 它的实现是通过$observe去监听DOM属性的变化, 这就是为什么@attr的值只能是字符串或是"{{}}", 而不能是scope上的属性, 所以最终$watch看到的表达式是没有"{{ }}"的. 而"="和"&"则是基于$watch实现. 所以=attr, &attr的值不能包含"{{ }}", 但可以直接使用scope上的属性.

$watchGroup和$watchCollection

$watchGroup是用来监听一组表达式. 数组中任意表达式的变化都会触发监听函数.

$scope.teamScore = 0;
$scope.time = 0;
$scope.$watchGroup([''teamScore'', ''time''], function(newVal, oldVal) {
 //newVal and oldVal are both array
});

$watchCollection用来监听一个对象(包括数组), 当这个对象的任意属性发生变化时, 触发监听函数. 和$watch一样,第一次参数可以是一个返回一个对象的函数.

$scope.names = [''igor'', ''matias'', ''misko'', ''james''];
$scope.dataCount = 4;

$scope.$watchCollection(''names'', function (newVal, oldVal) {
 $scope.dataCount = newVal.length;
});

$timeout(function(){
  $scope.names.pop();
},2000);

$observe, $watch, $watchGroup, $watchCollection都返回一个移除监听的函数. 当需要取消监听的时候, 直接调用.

var off = scope.$watch(''name'', function(newValue, oldValue){
});
off();

以上就是对AngularJs $parse、$eval和$observe、$watch的知识详解,谢谢大家对本站的支持!

您可能感兴趣的文章:
  • JS中注入eval, Function等系统函数截获动态代码
  • JavaScript数组、json对象、eval()函数用法实例分析
  • angularjs中的$eval方法详解
  • js eval函数使用,js对象和字符串互转实例
  • JavaScript制作简易计算器(不用eval)
  • js中的eval()函数把含有转义字符的字符串转换成Object对象的方法
  • 关于动态执行代码(js的Eval)实例详解
  • javascript中JSON.parse()与eval()解析json的区别
  • JS eval代码快速解密实例解析

angularJS $scope的$watch方法监听model改变

angularJS $scope的$watch方法监听model改变

$scope有个$watch方法,可以监听指定的model的改变,一旦model改变则触发(执行)传入其中的方法,该方法接收三个参数,如下

$scope.$watch('要监听的model名',function(newValue,oldValue){ },bool值指示是否监听的是对象),

其中newValue指向所监听的model,即两者是一回事,而oldValue则是所监听model此次改变前的拷贝。

示例:

<!DOCTYPE html>
<html lang="en">
<head>
    <Meta charset="UTF-8">
    <title>Title</title>
    <script src="http://cdn.static.runoob.com/libs/angular.js/1.4.6/angular.min.js"></script>
</head>
<body>
<div ng-app="myApp">
    <div ng-controller="firstController">
        <input type="text" ng-model="name">
        改变次数:{{count}}  新值:{{ name }}
        <br><br>
        <input type="text" ng-model="data.name">
        改变次数:{{data.count}}  新值:{{ data.name }}
    </div>
</div>

<script>
    var app=angular.module('myApp',[]);
    app.controller("firstController",function($scope){
        $scope.name='张三';
        $scope.count=0;

        $scope.data={
            name:'李四',count:0
        };

        //监听模型name  name每次改变时 都会执行传入的函数
        //因为name不是对象,所以不必传第三个参数
        $scope.$watch('name',oldValue){
            $scope.count ++;
            if($scope.count > 30){
                $scope.name='已经大于30次了';
            }
        });

        //监听模型data  data每次改变时  都会执行传入的函数
        //设置$watch方法的第三个参数为true 指示监听的是一个对象(该对象的每个属性变化都执行函数)
        $scope.$watch('data',oldValue){
            console.log($scope.data === newValue); //永远是true
            console.log($scope.data === oldValue); //页面初始化后是true,data改变之后永远是false
            console.log('新值: '+newValue.name+' 旧值: '+oldValue.name);
        },true);
    });
</script>
</body>
</html>

页面执行结果:

Angularjs $watch使用方法

Angularjs $watch使用方法

当angular数据模型发生变化时,我们需要如果需要根据他的变化触发其他的事件。

$watch是一个scope函数,用于监听模型变化,当你的模型部分发生变化时它会通知你。

$watch(watchExpression,listener,objectEquality);

watchExpression 需要监控的表达式,注意:表达式需要是model.attribute形式
listener 处理函数,函数参数如下
function(newValue,oldValue,scope)
objectEquality 是否深度监听,如果设置为true,它告诉Angular检查所监控的对象中每一个属性的变化. 如果你希望监控数组的个别元素或者对象的属性而不是一个普通的值,那么你应该使用它
<!DOCTYPE html>
<html ng-app="app">
<head>
<Meta charset="UTF-8">
<title>Insert title here</title>
</head>
<script src="assets/angular.min.js"></script>
<script src="assets/js/jquery.min.js"></script>
<script type="text/javascript">
var app=angular.module("app",[]);
app.controller('MainCtrl',function($scope) {
      $scope.name = "Angular";

      $scope.updated = -1;

      $scope.$watch('name',function(newValue,oldValue) {
            if (newValue === oldValue) { return; } // AKA first run
            $scope.updated++;
      });
      
      var i=0;
      
      $scope.getScope=function(){
         // console.info(this);
         var obj=$("#btnTest");
         i++;
         angular.element( obj).scope().name="hello" +i;
      }
      
    });
</script>
<body ng-controller="MainCtrl">
  <input ng-model="name" />
  Name updated: {{updated}} times.
  
  <button id="btnTest" ng-click="getScope()">获取scope</button>
</body>
</html>

此代码监控$scope的name值的变化,如果发生变化则触发监听。

监控对象:

<!DOCTYPE html>
<html ng-app="app">
<head>
<Meta charset="UTF-8">
<title>Insert title here</title>
</head>
<script src="assets/angular.min.js"></script>
<script src="assets/js/jquery.min.js"></script>
<script type="text/javascript">
var app=angular.module("app",function($scope) {
    $scope.user = { name: "Fox" };

      $scope.updated = -1;

      var watch=$scope.$watch('user',oldValue) {
        if (newValue === oldValue) { return; }
        $scope.updated++;
        
        $scope.$broadcast('userUpdate',newValue.name);
      });
      
      //watch();
      var i=0;
      
      $scope.$on('userUpdate',function(d,data){
          console.info(data);
      })
      
      $scope.getScope=function(){
         // console.info(this);
         var obj=$("#btnTest");
         i++;
         angular.element( obj).scope().user.name="hello" +i;
      }
      
    });
</script>
<body ng-controller="MainCtrl">
  <input ng-model="user.name" />
  Name updated: {{updated}} times.
  
  <button id="btnTest" ng-click="getScope()">获取scope</button>
</body>
</html>

这里我们点击按钮会发现监控并不会触发,原因是我们监控了user对象,这个user对象没哟发生变化,只不过属性值发生了变化。

如果我们希望监控user对象属性发生变化,有两个做法。

1.使用深度监控。

方法如下:

<!DOCTYPE html>
<html ng-app="app">
<head>
<Meta charset="UTF-8">
<title>Insert title here</title>
</head>
<script src="assets/angular.min.js"></script>
<script src="assets/js/jquery.min.js"></script>
<script type="text/javascript">
var app=angular.module("app",newValue.name);
      },true);
      
      //watch();
      var i=0;
      
      $scope.$on('userUpdate',data){
          console.info(data);
      })
      
      $scope.getScope=function(){
         // console.info(this);
         var obj=$("#btnTest");
         i++;
         angular.element( obj).scope().user.name="hello" +i;
      }
      
    });
</script>
<body ng-controller="MainCtrl">
  <input ng-model="user.name" />
  Name updated: {{updated}} times.
  
  <button id="btnTest" ng-click="getScope()">获取scope</button>
</body>
</html>

设置为深度监控,只要对象发生变化,那么监听就会触发。

2.直接写对象的属性值路径。

var watch=$scope.$watch('user.name',oldValue) {

具体代码就不全部写了。

消除监听

系统中太多的监听会影响系统的性能,我们可以在满足某些条件后,去掉监听。

去掉监听方法如下:

var watch=$scope.$watch('user',oldValue) {
if (newValue === oldValue) { return; }
$scope.updated++;

$scope.$broadcast('userUpdate',newValue.name);
},true);
//去掉监听。
watch();

在系统中使用事件广播。

比如在监听时,我们对外广播一个事件,

在控制其中写监听的处理方法:

实例如下:

$scope.$broadcast('userUpdate',newValue.name);

监听代码:

$scope.$on('userUpdate',data){
          console.info(data);
      })

这种做法最好使用在指令中,指令中广播事件,在控制器中实现监听。好处在于实现代码的重用。

AngularJS 1,AngularJS 2,Vue 1 ,Vue 2, React之间的区别和优劣势比较

AngularJS 1,AngularJS 2,Vue 1 ,Vue 2, React之间的区别和优劣势比较

Angluarjs1的优势:

1,框架思路清晰

2,组件完善

3,有前辈指导,开发经验完善

Angluarjs1的劣势:

1,致命劣势:官方已经不在维护该框架,未来组件将不会得到更新,时间就了就会被淘汰

2,与最新的angular 2相比,完全不一样,与以后的版本脱离,很难升级

Angluarjs 2的优势:

1,框架思路相比较angular 1 更加清晰

2,以typescript(es6封装)开发,开发更加轻松

3,真正的MVC结构

Angluarjs2的劣势:

1,致命劣势:框架较新,组件体系不够完善,导致开发周期边长

2,学习成本高

3,资料偏少,缺乏开发经验,而且无人指导

4,与Angluarjs1完全不一样,加长学习时间

5,环境搭建耗时

Vue 1 与 Vue 2:Vue 1 到 Vue 2 是一个版本的迭代(添加新特性)

Vue 相对其他框架优势:

1,学习成本不高,有angular基础学习速度会更快

2,组件和第三方集成相对Angular 2 较完善

3,框架自由度高,集成难度小

Vue 相对其他框架劣势:

1,相比Angular ,该框架思路不清晰

2,环境搭建耗时

React:使用人数偏少,一般公司用不到,不推荐使用

以上纯属个人观点,不喜勿喷

我们今天的关于AngularJS:$ observe和$ watch方法之间的区别angular watch的用法的分享就到这里,谢谢您的阅读,如果想了解更多关于AngularJs $parse、$eval和$observe、$watch详解、angularJS $scope的$watch方法监听model改变、Angularjs $watch使用方法、AngularJS 1,AngularJS 2,Vue 1 ,Vue 2, React之间的区别和优劣势比较的相关信息,可以在本站进行搜索。

本文标签: