【问题标题】:AngularJS getter / setterAngularJS 获取器/设置器
【发布时间】:2014-10-16 15:50:52
【问题描述】:

我正在学习 Angular,我正在尝试找出使用 getter/setter 的最佳解决方案。

也就是说,我正在使用一个公开 getter 和 setter 的库(就像 Moment.js 所做的那样)。

我尝试了几种处理 getter 和 setter 的方法,它们是:

index.html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <title>Example - example-ngModel-getter-setter-production</title>
  <script data-require="jquery@2.1.1" data-semver="2.1.1" src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
  <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.0-beta.18/angular.min.js">    </script>
  <script src="app.js"></script>
</head>

<body ng-app="getterSetterExample">
  <div ng-controller="ExampleController">
    <form name="userForm">
      Name :
      <input type="text" name="userName" ng-model="user.name" ng-model-options="{ getterSetter: true }" />
      <br/>Name1:
      <input type="text" name="userName1" ng-model="user1.name" ng-model-options="{ getterSetter: true }" />
      <br/>Name2:
      <input type="text" name="userName2" ng-model="user2.name" ng-model-options="{ getterSetter: true }" />
      <br/>Name3:
      <input type="text" name="userName3" ng-model="user3.name" ng-model-options="{ getterSetter: true }" />
    </form>
    <pre>user.name =         <span ng-bind="user.name()"></span>
      </pre>
    <pre>user1.name =        <span ng-bind="user1.name()"></span>
      </pre>
    <pre>user2.name =        <span ng-bind="user2.name()"></span>
      </pre>
    <pre>user3.name =        <span ng-bind="user3.name()"></span>
      </pre>
  </div>
</body>

</html>

app.js

  angular.module('getterSetterExample', [])
    .controller('ExampleController', ['$scope',
      function($scope) {
        var _name = 'Brian';
        var _name3 = 'Joe';


        var name1 = {
          _name: 'George',
          name:function(newName) {
            if (angular.isDefined(newName)) {
              this._name = newName;
            }
            return this._name;
          }
        };

        var name2 = {
          _name: 'Michael',
          name:function(newName) {
            if (angular.isDefined(newName)) {
              this._name = newName;
            }
            return this._name;
          }
        };

        var name3 = {
          name:function(newName) {
            if (angular.isDefined(newName)) {
              _name3 = newName;
            }
            return _name3;
          }
        };

        $scope.user = {
          name: function(newName) {
            if (angular.isDefined(newName)) {
              _name = newName;
            }
            return _name;
          }
        };

        $scope.user1 = {
          name: name1.name
        };

        $scope.user2 = {
          name: function(newName) {
            return name2.name(newName);
          }
        };

        $scope.user3 = {
          name: name3.name
        };

      }
    ]);

你可以在这里试试:http://plnkr.co/edit/S1qKre9umNpLOt0sjpZf?p=preview

2 个问题:

user1 尝试直接使用 name1 对象提供的 getter/setter,它不能正常工作,你能解释一下原因吗?

有没有办法避免像我在 user3 中所做的那样为每个 getter/setter 重写“代理”?使用外部库提供的 getter/setter 的最佳方法是什么?

感谢您的帮助

【问题讨论】:

    标签: javascript angularjs setter getter


    【解决方案1】:

    user1 尝试直接使用 name1 对象提供的 getter/setter,它不能正常工作,你能解释一下原因吗?

    问题在于上下文,您只是通过执行以下操作复制函数引用name1.name:-

        $scope.user1 = {
          name: name1.name
        };
    

    所以当它在 getter 中运行 this 时,实际上将指向 window/global(在非严格模式下)。您可以使用Function.bind 解决此问题。

    例子:-

        $scope.user1 = {
          name: name1.name.bind(name1)
        };
    

    Demo

    有没有办法避免像我在 user3 中所做的那样为每个 getter/setter 重写“代理”?

    我只想创建一个包装器,这样我就不会遇到这样的上下文问题。

        $scope.user = getModel('name', 'Brian');
    
        $scope.user1 = getModel('name', 'George');
    
        $scope.user2 = getModel('name', 'Michael');
    
        $scope.user3 = getModel('name', 'Joe');
    
        $scope.address = getModel('address');
    
    
      //You can improve this by passing an optional getter functionality as well for some specific evaluation on the value when set.
      function getModel(propertyName, defValue) {
          var obj =  {};
    
          obj._defVal = defValue;
          obj[propertyName] = function(newVal){
            if (angular.isDefined(newVal)) {
              obj[prop] = newVal;
            }
            return obj[prop];
          }
    
          return obj;
        }
       }
    

    或者只是

     function getModel(propertyName, defValue) {
          var obj =  {};
           var propValue = defValue;
          obj[propertyName] = function(newVal){
            if (angular.isDefined(newVal)) {
              propValue = newVal;
            }
            return propValue;
          }
          return obj;
        }
      }
    

    Demo2

    【讨论】:

    • 我担心范围。您指出错误是执行期间的错误范围。我尝试修改代码以将 name2 包含到范围中,如下所示:我替换了 var name2通过 $scope.name2 和修改 index.html ng-model="name2.name"。我期望通过将它绑定到范围来解决范围问题。哪里错了?
    • "您指出错误是执行期间的错误范围" 我并不是指 this 指向的错误上下文。我没明白你的意思。你能把你的代码粘贴到一个plunker..
    • 我在plnkr.co/edit/3dh1DmGvIy6V7YPPEfKV?p=preview(第 8 版)这里编辑了代码——查看 index.html 中的第 20 行和 app.js 中的第 18 行。我希望它在执行时绑定到 $scope。
    • @ChrisDunom 不是真的.. 请参阅角度代码if (ctrl.$options &amp;&amp; ctrl.$options.getterSetter &amp;&amp; isFunction(modelValue)) { modelValue = modelValue(); } 中的行,基本上函数引用是modelValue,它只是在没有上下文的情况下执行。它只是正在执行的函数引用的副本。当我们在无法控制执行上下文的代码中使用this 时,这始终是问题。
    • 感谢您的澄清。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-24
    • 2013-02-07
    • 1970-01-01
    相关资源
    最近更新 更多