angular中重要指令介绍($eval,$parse和$compile)

  在angular的服务中,有一些服务你不得不去了解,因为他可以说是ng的核心,而今天,我要介绍的就是ng的两个核心服务,$parse和$compile。其实这两个服务讲的人已经很多了,但是100个读者就有100个哈姆雷特,我在这里讲讲自己对于他们两个服务的理解。

  大家可能会疑问,$eval呢,其实他并不是一个服务,他是scope里面的一个方法,并不能算服务,而且它也基于parse的,所以只能算是$parse的另一种写法而已,我们看一下ng源码中$eval的定义是怎样的就知道了  

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

  相信看完源码大家就明白了吧,好了,现在就开始两种核心服务的讲解了,如果感觉我说的不对的话,欢迎在评论区或者私聊指出,免得祸害其他读者。

  再讲这两个服务的时候,我要先讲一个在本贴的概念:上下文

  我相信,很多人都听过这个“上下文”,但是可能有点模糊,在我这里给大家解释解释看看大家接不接受这个说法。

  还记得angular的数据绑定吗?比如:我现在有个有个叫TestCtrl的控制器,他的内容如下:  

  .controller(‘TestCtrl‘, function($scope) {
         $scope.test = "Boo!!!"
    })

  而在html中我们的代码是这样的

<body ng-controller="TestCtrl">
    {{test}}
</body>

  那么,大家不用想都知道结果了,页面上肯定会显示 Boo!!!的字样。

  但是如果我删掉ng-controller的指令呢?也就是我没有在html申明控制器,你直接绑定{{test}}会如何呢?

  结果只有一个,那就是页面啥都没有(ps:因为你申明了ng-app)。讲到这里大家明白了吗?

  控制器就相当于一个上下文的容器,真正的上下文其实是$scope,当页面绑定test,如果申明了控制器,当前上下文就是控制器里面的$scope,ng会去找一下你这个控制器的上下文$scope有没有test,如果有,他当然就显示出来了,但是你不申明控制器的时候呢?他的上下文容器就是ng-app了,那么他真正的上下文就是$rootScope,这个时候他就会寻找$rootScope有没有test。

  好了,上下文的概念已经讲完了,其实挺容易理解的,基本上和this非常相似

  那么言归正传,我们开始讲$parse,首先我们要看的是ng的API文档

var getter = $parse(‘user.name‘);
var setter = getter.assign;
var context = {user:{name:‘angular‘}};
var locals = {user:{name:‘local‘}};

expect(getter(context)).toEqual(‘angular‘);
setter(context, ‘newValue‘);
expect(context.user.name).toEqual(‘newValue‘);
expect(getter(context, locals)).toEqual(‘local‘);

  大家看到的是ng文档里面对于$parse服务性价比最高的几行代码,

  getter和setter就是大家所熟知的get方法和set方法了,context和locals仅仅是json对象而已,目的就是模拟上下文关系

  大家看到的下面四个语句最终都能通过测试,现在我们一个个来分析,分析之前我要解释一遍什么叫$parse

  $parse服务其实就是一种解析表达式的功能,就像ng-model=“test”,你在html中写这个东西谁知道你ng-model=“test”中,其实你想绑定的是当前控制器(上下文容器)中scope(上下文)中的test里面的值,ng就是通过$parse服务去帮助你解析这个表达式的,所以在调用$parse服务的时候你需要传递上下文对象,让ng知道你是要去哪里的scope(上下文)去找你这个test。

  所以我们看到第一行测试代码是这样的:  

getter(context)).toEqual(‘angular‘) //实际上就是 $parse(‘user.name‘)(context)

  在这个context就是上下文,他能返回“angular“这个字符串的原理就是经过这三步的:

    1.获取当前的表达式user.name

    2.获取当前的上下文对象{user:{name:‘angular‘}}

    3.在上下问对象中寻找表达式,最终获得“angular“这个字符创

  所以这句测试代码是成功的。

  我们看第二个方法setter方法

setter(context, ‘newValue‘);//实际上就是 $parse(‘user.name‘).assign(context, ‘newValue‘)
expect(context.user.name).toEqual(‘newValue‘);//测试数据上下文的值是否被改变

  这里的setter方法其实是改变值得方法    

    1.获取当前的表达式user.name

    2.获取当前的上下文对象{user:{name:‘angular‘}}

    3.改变表达式中的值,将上下文对象编程{user:{name:‘newValue‘}}

  于是上下文对象发生了改变,重新用getter方法去获取表达式的时候,上下文已经从{user:{name:‘angular‘}} --> {user:{name:‘newValue‘}},最后获取的表达式的值自然就是“newValue”了,所以测试代码也是通过的。  

expect(getter(context, locals)).toEqual(‘local‘);//实际上就是$parse(‘user.name‘)(context, locals)

  这里要表现的其实是上下文的替换功能。

    在getter的方法中我们不仅可以选择第一个上下文,但是如果我们传递了第二个参数,那么第一个上下文就会被第二个上下文覆盖,注意是覆盖.    

       1.获取当前的表达式user.name

       2.获取当前的上下文对象{user:{name:‘angular‘}}

       3.覆盖当前的上下文{user:{name:‘local‘}}

       4.获取解析之后表达式的值

    重新回到$eval这个地方,我们看待$eval源码中可以看出$eval只有get功能,而没有set功能,但是有些时候我们可以选择传递第二个上下文,来达到修改值得效果。

    在这里$parse服务就已将说完了,还是那句话

    此贴为原创,如有转载,请注明

时间: 2024-10-18 06:29:02

angular中重要指令介绍($eval,$parse和$compile)的相关文章

Angular中ngCookies模块介绍

1.Cookie介绍 Cookie总是保存在客户端中,按在客户端中的存储位置,可分为内存Cookie和硬盘Cookie.内存Cookie由浏览器维护,保存在内存中,浏览器关闭后就消失了,其存在时间是短暂的.硬盘Cookie保存在硬盘里,有一个过期时间,除非用户手工清理或到了过期时间,硬盘Cookie不会被删除,其存在时间是长期的.所以,按存在时间,可分为非持久Cookie和持久Cookie. 主要因为HTTP协议无状态性,服务器需要知道用户在之前的页面做了哪些操作,所欲引入Cookie,是一种解

angular中transclude的理解

今天被这个transclude搞糊涂了,弄了半天,才知道原来使用起来很简单.很烦恼为社么书中的对于这个的介绍这么晦涩难懂.直到看到了这篇文章,才让我弄清楚了. 一.transclude介绍 transclude是angular中自定义指令中的一个参数.中文就是嵌入的意思.也就是说通过这个参数设置,可以将指令内容嵌入到自定义指令中的模版中.其值默认是false,当为true时,会起到嵌入的作用. 二.使用 首先我们先看一下不使用tranclude的情况: js: app.directive('my

Angular中的内置指令和自定义指令

NG中的指令,到底是什么(what)? 为什么会有(why)?以及怎样使用(how)? What: 在NG中,指令扩展HTML功能,为 DOM 元素调用方法.定义行为绑定数据等. Why: 最大程度减少DOM操作,实现数据绑定,与业务逻辑进行交互. How: 指令主要分为两种:内置指令和自定义指令,通过下面的例子,简单记录一下如何去使用. 内置指令 在官方API文档上罗列了很多指令,内置指令可以分为:普通指令 和 事件指令,他们都是作用于HTML之上的,通过添加属性的方式来实现的.简单看一下一些

Angular.js中的指令——易懂全解析

<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"> </span><span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">angular.js中,指令是最基础的

angular中出现错误的提示指令[ng:areq]的原因

angular.min.js:80 Error: [ng:areq] http://errors.angularjs.org/1.2.9/ng/areq?p0=sellerService&p1=not%20a%20function%2C%20got%20undefined at angular.min.js:2 at ub (angular.min.js:14) at Pa (angular.min.js:14) at angular.min.js:57 at angular.min.js:45

走进AngularJs(二) ng模板中常用指令的使用方式

通过使用模板,我们可以把model和controller中的数据组装起来呈现给浏览器,还可以通过数据绑定,实时更新视图,让我们的页面变成动态的.ng的模板真是让我爱不释手.学习ng道路还很漫长,从模板开始入手是个不错方式,因为这部分内容相对简单好理解,而且是视图层的东西,大家都喜欢可以立马看得见的东西嘛.本篇我将搜罗模板中的常用指令一一测试,了解其使用方法,有点像背单词的感觉,会比较枯燥.不过对于初学,这样的枯燥是必须要经历的,开始~ 一.模板中可使用的东西及表达式 模板中可以使用的东西包括以下

(七)理解angular中的module和injector,即依赖注入

依赖注入(DI)的好处不再赘言,使用过spring框架的都知道.angularjs作为前台js框架,也提供了对DI的支持,这是javascript/jquery不具备的特性.angularjs中与DI相关有angular.module().angular.injector(). $injector.$provide.对于一个DI容器来说,必须具备3个要素:服务的注册.依赖关系的声明.对象的获取.比如spring中,服务的注册是通过xml配置文件的<bean>标签或是注解@Repository.

Angular 2 属性指令 vs 结构指令

Angular 2 的指令有以下三种: 组件(Component directive):用于构建UI组件,继承于 Directive 类 属性指令(Attribute directive):  用于改变组件的外观或行为 结构指令(Structural directive):  用于动态添加或删除DOM元素来改变DOM布局 组件 import { Component } from '@angular/core'; @Component({       selector: 'my-app', // 

angular中的动画效果

用angular来形成动画效果的代码如下 <!DOCTYPE html> <html lang="en" ng-app="app"> <head> <meta charset="UTF-8"> <title></title> <style> .box { width: 100px; height: 100px; background: red; } </st