zoukankan      html  css  js  c++  java
  • angular parse eval parse VS eval

    Notes: parse 和 eval 等service之前都有一个$ 美元符号

    parse  angular中重要指令介绍( eval,  parse和 compile)  Advanced Angular: parse

    $parse

    ----------------------------------------------------------------------------------------------------

    $parse 

     $parse服务是将一个Angular expression转化为一个函数

    Converts Angular expression into a function.

    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');

    Returns

    调用$parse后返回一个函数

    function(context, locals)
    a function which represents the compiled expression:

    1. context – {object} – an object against which any expressions embedded in(angular表达式所在的上下文) the strings are evaluated against (typically a scope object).
    2. locals – {object=} – local variables context object, useful for overriding values in context(locals可以覆盖掉context里面的值).

    The returned function also has the following properties:

    1. literal – {boolean} – whether the expression's top-level node is a JavaScript literal.
    2. constant – {boolean} – whether the expression is made entirely of JavaScript constant literals.
    3. assign – {?function(context, value)} – if the expression is assignable, this will be set to a function to change its value on the given context(改变表达式所在的上下文中的值).

    ----------------------------------------------------------------------------------------------

    Advanced Angular: $parse

    If you want to step up in your AngularJS knowledge, $parse is one of the most important services that you should know about. It is used in most of the directives, and opens up your imagination to a new set of possibilities.

    So, what does it do? Let’s start with a place we all well know: ngClick.

    ngClick directive, takes an expression, and executes the expression when the directive element is clicked. So, how does it work internally? Yep, you guessed it: with $parse.

    $parse takes an expression, and returns you a function. When you call the returned function with context(带着上下文作为第一个参数) (more on that later) as first argument, it will execute the expression with the given context.

    Let’s see it with an example:

    function MyService($parse) {
      var context = {
        author: { name: 'Umur'},
        title: '$parse Service',
        doSomething: function (something) {
          alert(something);
        }
      };
      var parsedAuthorNameFn = $parse('author.name');
      var parsedTitleFn = $parse('title');
      var parsedDoSomethingFn = $parse('doSomething(author.name)');
     
      var authorName = parsedAuthorNameFn(context);
      // = 'Umur'
      var parsedTitle = parsedTitleFn(context);
      // = '$parse Service'
      var parsedDoSomething = parsedDoSomethingFn(context);
      // shows you an alert 'Umur'
    }

    So this is very cool, we can evaluate strings with a context safely. Let’s write a very basic myClick directive.

    angular.module('my-module', [])
      .directive('myClick', function ($parse) {
        return {
          link: function (scope, elm, attrs) {
            var onClick = $parse(attrs.myClick);
            elm.on('click', function (e){
              // The event originated outside of angular,
              // We need to call $apply
              scope.$apply(function () {
                onClick(scope); // 传递了一个上下文参数
              });
            });
          }
        }
    });

    See, the pure javascript object turns out to the our scope!

    This works, but if you look at the docs of ngClick, it lets us to inject $event object to the function. How does that happen? It is because the parsed function accepts an optional second argument for additional context.

    在angular的ngClick中,是可以传递$event参数的,我们这里是自定义了一个参数,传递了进去

    We have access to event object in the click callback, and we can just pass this through.

    angular.module('my-module', [])
      .directive('myClick', function ($parse) {
        return {
          link: function (scope, elm, attrs) {
            var onClick = $parse(attrs.myClick);
            elm.on('click', function (e){
              // The event originated outside of angular,
              // We need to call $apply
              scope.$apply(function () {
                onClick(scope, {$event: e});// 构造了一个自己的$event对象,传递了进去
              });
          });
        }
      }
    });

    If you don’t need to pass additional context, you can save some bytes and remove code of the code. Here is a way to do it cooler. How does it work exercise it left to the reader. Please leave a comment if you think you’ve found the answer!

    angular.module('my-module', [])
      .directive('myClick', function ($parse) {
        return {
          link: function (scope, elm, attrs) {
            var onClick = $parse(attrs.myClick);
            elm.on('click', function (e) {
              scope.$apply(onClick);
            });
          }
        }
    });

    $eval

    Angular.js: How does $eval work and why is it different from vanilla eval?

    $eval and $parse don't evaluate JavaScript; they evaluate AngularJS expressions.( $eval$parse处理的不是js表达式,而是Angular表达式)

    The linked documentation explains the differences between expressions and JavaScript.

    Q: What exactly is $eval doing? Why does it need its own mini parsing language?

    From the docs:

    Expressions are JavaScript-like code snippets that are usually placed in bindings such as {{ expression }}. Expressions are processed by $parse service(内部调用$parse服务).

    It's a JavaScript-like mini-language that limits what you can run (e.g. no control flow statements, excepting the ternary operator) as well as adds some AngularJS goodness (e.g. filters).

    Q: Why isn't plain old javascript "eval" being used?

    Because it's not actually evaluating JavaScript. As the docs say:

    If ... you do want to run arbitrary JavaScript code, you should make it a controller method and call the method. If you want to eval() an angular expression from JavaScript, use the $eval() method.

    The docs linked to above have a lot more information.

    ($parse vs $eval)

    $parse/$eval和$observe/$watch如何区分

    $parse和$eval

    首先,$parse跟$eval都是用来解析表达式的, 但是$parse是作为一个单独的服务存在的。$eval是作为scope的方法来使用的。
    $parse典型的使用是放在设置字符串表达式映射在真实对象上的值。也可以从$parse上直接获取到表达式对应的值。

    var getter = $parse('user.name'); 
    var setter = getter.assign; 
    setter(scope, 'new name');
    getter(context, locals) // 传入作用域,返回值
    setter(scope,'new name') // 修改映射在scope上的属性的值为‘new value’
    

    $eval 即scope.$eval,是执行当前作用域下的表达式,如:scope.$eval('a+b'); 而这个里的a,b是来自 scope = {a: 2, b:3};
    看看源码它的实现是

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

    可以找到它也是基于$parse,不过它的参数已经被固定为this,就是当前的scope,所以$eval只是在$parse基础上的封装而已,是一种$parse快捷的API。

  • 相关阅读:
    从一个表中查数据,插入另一个表
    sql 字段字符串内容替换
    安装VS2010后,如何设置老版本的项目文件不是默认用VS2010打开
    题解 [JOI 2019 Final] 独特的城市
    题解 [JOI 2019 Final] 硬币收藏
    题解 [CF720A] Closing ceremony
    [学习笔记] Miller-Rabin 质数测试
    题解 [CF332C] Students' Revenge
    题解 [CF525D] Arthur and Walls
    SpringMVC-拦截器
  • 原文地址:https://www.cnblogs.com/oneplace/p/6139202.html
Copyright © 2011-2022 走看看