AngularJS指令:用单向绑定从字符串解析数组

AngularJS directive: parsing array from string in one way binding

本文关键字:字符串 数组 绑定 指令 AngularJS      更新时间:2023-09-26

我正在创建一个单向绑定指令,它有一个包含数组的属性,如下所示:

app.directive('interestBox', function() {
    return {
        restrict: 'E',
        scope: {
            interests: '@'
        },
        templateUrl: '/static/templates/directive_templates/interestbox.html',
        link: function(scope, element, attrs) {
            scope.interests = scope.$eval(scope.interests); //currently, doing this for converting string to array
            console.log(scope.interests);
        }
    }
})
<interest-box interests="{{profile_data.interests}}">
</interest-box>

控制器:

$scope.profile_data.interests = [1, 2, 3, 4];

首先,我使用@而不是=的原因是我不需要控制器和指令之间的双向绑定(关于这个假设我是否正确?)

但是,当您拥有它时,@将DOM值解析为字符串。现在,由于我的属性"利益"是一个数组,我需要在指令中将其从字符串(@将其转换为)转换为数组。为此,我正在做:

$scope.interests = scope.$eval(scope.interests);

这对我来说感觉不对。从字符串中得到数组的最好方法是什么?

您希望在指令中拥有原始数组的副本以进行操作。修改后的数据准备好后,可以使用隔离的本地数据更新原始控制器阵列。在你的例子中,它看起来像这样:

angular.module('demo', [])
.controller('DemoController', function($scope, $timeout) {
    $scope.profile_data = {interests: [1,2,3]};
    $timeout(function() {$scope.profile_data.interests.push(4);}, 1000);
})
.directive('interestBox', function($timeout, $parse) {
    return {
        restrict: 'E',
        scope: {
            interestsOrig: '=interests'
        },
        template: '<pre>{{ interests }}</pre><button ng-click="updateInterests()">Update controller array</button>',
        link: function(scope, element, attrs) {
            
            scope.interests = angular.copy(scope.interestsOrig);
            
            // Modify interests, push new, remove old
            $timeout(function() {
                scope.interests.push(5); 
                scope.interests.splice(0, 1)
            }, 2000);
            
            // Update original controller interests with local
            scope.updateInterests = function() {
                scope.interestsOrig = scope.interests;
            };
        }
    }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.7/angular.min.js"></script>
<div ng-app="demo" ng-controller="DemoController">
    <h4>Controller</h4>
    <pre>{{ profile_data.interests }}</pre>
    <h4>Directive</h4>
    <interest-box interests="profile_data.interests"></interest-box>
</div>

将一个变量从一种类型共享到另一种类型,然后执行强制类型转换总是错误的

根据AngularJS文档,当你将指令定义对象的scope属性声明为Object时,你会得到一个具有隔离作用域的指令

在这种情况下,我认为你不需要一个隔离作用域,只需要一个简单的子作用域。当用子作用域创建指令时,父作用域的值会被复制到新的子作用域…

angular
  .module('test', [])
  .controller('ProfileCtrl', function($scope) {
    var vm = $scope;
  
    vm.interests = [1, 2, 3, 4, 5, 6];
  })
  .directive('interests', function() {
  
    function InterstsPostLink(iScope, iElement, iAttributes) {
      iScope.interests = [].concat(iScope.interests)
      iScope.addInterest = function(val) {
          iScope.interests.push(val)
      };
      
      iScope.newInterest = 'Hello';
    }
  
    var ddo = {
      templateUrl: 'interests-list',
      link: InterstsPostLink,
      scope: true
    };
    return ddo;
  })
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<article data-ng-app="test">
  <div data-ng-controller="ProfileCtrl">
    
    <h3>ProfileCtrl Value</h3>
    <div ng-bind="interests | json"></div>
    <hr />
    
    
    <div interests></div>
  </div>
  
  <script type="text/ng-template" id="interests-list">
    <h3>Directive Value</h3>
    <div ng-bind="interests | json"></div>
    <input type="text" ng-model="newInterest">
    <button ng-click="addInterest(newInterest)">Add</button>
  </script>
</article>