我正在尝试使用 Angular 和 es6 Promise 构建一个深入列表。如果不使用 Promise,我的代码将按照下面的代码片段中的演示进行工作。每次单击父项时,它都会展开子项(为简单起见,示例中仅显示 foo 和 bar)。
angular.module('demo', [])
.controller('DemoController', ['$scope', 'dataService', function($scope, dataSvc) {
$scope.entities = dataSvc.loadInitialData();
}])
.directive('drillDown', ['$compile', 'dataService', function($compile, dataSvc) {
return {
restrict: 'A',
scope: {
entities: '='
},
controller: function($scope) {
$scope.load = function() {
this.entity.subEntities = dataSvc.load();
};
},
compile: function(element) {
var contents = element.contents().remove();
var compiled = null;
return function(scope, element) {
if (!compiled) {
compiled = $compile(contents);
}
compiled(scope, function(clone) {
element.append(clone);
});
};
},
template:
'<li ng-repeat="entity in entities">' +
'<a href="#" ng-click="load()"><span ng-bind="entity.name"></span></a>' +
'<ul drill-down entities="entity.subEntities"></ul>' +
'</li>'
};
}])
.service('dataService', function() {
this.loadInitialData = function() {
return [
{
name: 'foo',
subEntities: []
},
{
name: 'bar',
subEntities: []
}
];
};
this.load = function() {
return this.loadInitialData();
};
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.0/angular.min.js"></script>
<div ng-app="demo" ng-controller="DemoController">
<ul drill-down entities="entities"></ul>
</div>
但是,当我将其更改为使用 Promise 时,出现了问题:现在您必须双击该元素才能展开它,并且范围也变得困惑。
本质上的区别仅在于服务和指令 Controller 中的 load
函数。到目前为止,我还没有真正研究过 Angular 的 $q
api,但为什么我不能只使用 Promise 呢? $q
有什么魔力吗?
angular.module('demo', [])
.controller('DemoController', ['$scope', 'dataService', function($scope, dataSvc) {
$scope.entities = dataSvc.loadInitialData();
}])
.directive('drillDown', ['$compile', 'dataService', function($compile, dataSvc) {
return {
restrict: 'A',
scope: {
entities: '='
},
controller: function($scope) {
$scope.load = function() {
var s = this;
dataSvc.load().then(function(res) {
s.entity.subEntities = res;
});
};
},
compile: function(element) {
var contents = element.contents().remove();
var compiled = null;
return function(scope, element) {
if (!compiled) {
compiled = $compile(contents);
}
compiled(scope, function(clone) {
element.append(clone);
});
};
},
template:
'<li ng-repeat="entity in entities">' +
'<a href="#" ng-click="load()"><span ng-bind="entity.name"></span></a>' +
'<ul drill-down entities="entity.subEntities"></ul>' +
'</li>'
};
}])
.service('dataService', function() {
this.loadInitialData = function() {
return [
{
name: 'foo',
subEntities: []
},
{
name: 'bar',
subEntities: []
}
];
};
this.load = function() {
return new Promise(function(resolve, reject) {
resolve([
{
name: 'foo',
subEntities: []
},
{
name: 'bar',
subEntities: []
}
]);
});
};
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.0/angular.min.js"></script>
<div ng-app="demo" ng-controller="DemoController">
<ul drill-down entities="entities"></ul>
</div>
最佳答案
这将要求 ES6 Promise 要么公开一个用于设置调度程序的钩子(Hook)(如 Bluebird Promise),要么公开“Post-then”钩子(Hook)——这两者都不是公开的。
您必须通过执行以下操作将 ES6 promise 强制为 $q
:
$q.when(dataSvc.load()).then(...
或者,您可以编写一个帮助器将其绑定(bind)到范围:
var withDigest = function(fn){
fn().then(function(){
$rootScope.evalAsync(angular.noop); // schedule digest if not scheduled
});
};
然后执行:
withDigest(function(){
return dataSvc.load().then(...
});
关于javascript - 不能简单地使用 ES6 Promise 来更新 ng-repeat 中的数据吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30835399/