AngularJS getter / setter

4

我正在学习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个问题:
用户1试图直接使用name1对象提供的getter/setter,但它不能正常工作,您能解释为什么吗?
有没有办法避免像用户3那样为每个getter/setter重新编写“代理”,最好的方法是使用外部库提供的getter/setter?
感谢您的帮助。
1个回答

4
用户1试图直接使用name1对象提供的getter/setter,但它不能正常工作,你能解释一下原因吗?
问题出在上下文中,你只是简单地复制函数引用 name1.name,这样做会出问题:
    $scope.user1 = {
      name: name1.name
    };

当运行时,getter中的this实际上会指向window/全局对象(在非严格模式下)。您可以通过使用Function.bind来解决这个问题。

示例:

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

演示

有没有办法避免像 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包含到作用域中,像这样:我用$scope.name2替换了var name2,并修改了index.html ng-model="name2.name"。我希望通过将其绑定到作用域来解决作用域问题。错在哪里? - Chris Dunom
您指出错误是执行期间作用域错误,但实际上我指的是由于“this”指向错误的上下文。我不太明白您的意思。您能在Plunker中粘贴您的代码吗? - PSL
我已经在这里编辑了代码http://plnkr.co/edit/3dh1DmGvIy6V7YPPEfKV?p=preview(第8个版本) - 查看index.html的第20行和app.js的第18行。我期望这在执行时绑定到$scope。 - Chris Dunom
@ChrisDunom 不是很准确.. 请看来自Angular代码的这一行 if (ctrl.$options && ctrl.$options.getterSetter && isFunction(modelValue)) { modelValue = modelValue(); } 基本上,函数引用是 modelValue,它只是在没有上下文的情况下被执行。 它只是被执行的函数引用副本。 当我们在代码片段中使用 this 时,我们无法控制执行上下文,这总是问题所在。 - PSL
谢谢你的澄清。 - Chris Dunom

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接