gpt4 book ai didi

javascript - AngularJS - 使用 controllerAs 语法和服务属性的 DRY 双向数据绑定(bind)

转载 作者:搜寻专家 更新时间:2023-11-01 04:15:42 24 4
gpt4 key购买 nike

我偶然发现了一个应该是常见且明显的问题,但我似乎无法解决这个问题。

我正在开发一个小型原型(prototype)应用程序。我的后端开发人员在 JSON 对象中为我提供了配置文件数据。比方说,它看起来像这样:

profile = {Name: 'John', Email: 'john@mail.com', DOB: '1980-11-03'}

我需要在多个位置使用这些值,而且我也不想在 Controller 中放置后端 http 调用,所以我创建了一个服务来处理这个问题:

angular.module('app', [])
.service('ProfileService', ['$http', function ($http) {
var service = this;

service.Name = null;
service.Email = null;
service.DOB = null;

service.getProfile = function () {
return $http.get('/profile').then(function (response) {
service.Name = response.data.Name;
service.Email = response.data.Email;
service.DOB = response.data.DOB;
return true;
});
};

return service;
}])
.controller('ProfileCtr', ['ProfileService', function (service) {
var vm = this;

service.getProfile().then(function () {
vm.Name = service.Name;
vm.Email = service.Email;
vm.DOB = service.DOB;
});
}]);

这个解决方案有很多问题:

  1. 由于配置文件数据由基元组成,直接绑定(bind)到服务属性不会自动提供数据同步。
  2. 更重要的是,它打破了 DRY 概念,因为我至少在 3 个不同的地方(数据库架构、getProfile() 和 Controller )编写了数据声明。

一个解决方案是添加一个间接层并在服务中创建一个对象:

angular.module('app', [])
.service('ProfileService', ['$http', function ($http) {
var service = this;

service.profile = {};

service.getProfile = function () {
return $http.get('/profile').then(function (response) {
for (key in response.data) {
service.profile[key] = response.data[key];
};
return true;
});
};

return service;
}])
.controller('ProfileCtr', ['ProfileService', function (service) {
var vm = this;

service.getProfile().then(function () {
vm.profile = service.profile;
});
}]);

这通常有效,但现在我得到了笨拙的 controllerAs 语法:

<div ng-controller="ProfileCtr as ctr">
<h1> {{ ctr.profile.Name }}</h1>
<p> Email: {{ ctr.profile.Email }} <br /> DOB: {{ ctr.profile.DOB }}</p>
</div>

我想知道是否有一种方法可以同时满足我:干净的 HTML {{ ctr.Name }} 语法 一种 DRY 编程风格。

感谢任何提示!

最佳答案

我觉得你想要的不止于此,但对我来说这至少是干的:

angular.module('app', [])
.service('ProfileService', ['$http', function ($http) {
var service = this;
service.getProfile = function () {
return $http.get('/profile').then(function (response) {
return response.data;
});
};

return service;
}])
.controller('ProfileCtr', ['ProfileService', function (ProfileService) {
var vm = this;

ProfileService.getProfile().then(function (profile) {
vm.profile= profile;
});
}]);

服务获取数据。您也可以在此处添加缓存功能。 Controller 使用服务来获取数据。没有重复代码。

我喜欢使用 $scope 变量,它可以消除一层间接问题。但是,controllerAs 确实有它的优势,特别是如果您使用嵌套 Controller 并且想要弄清楚您使用的是哪个 Controller 。 $scope 标识符将在版本 2 中删除。

为这部分 html 使用指令而不是 Controller 应该使您的代码更易于阅读和重用。还建议做好升级到版本 2 的准备。

然后:

app.directive('isolateScopeWithControllerAs', function () {

var controller = ['ProfileService', function (ProfileService) {

var vm = this;

ProfileService.getProfile().then(function (profile) {
vm.profile= profile;
});

}];

return {
restrict: 'EA', //Default for 1.3+
controller: controller,
controllerAs: 'vm',
bindToController: true, //required in 1.3+ with controllerAs
templateUrl: // path to template
};
});

然后你的 HTML 仍然给你:

    <h1> {{ vm.profile.Name }}</h1>
<p> Email: {{ vm.profile.Email }} <br /> DOB: {{ vm.profile.DOB }}</p>

ProfileCtr as vm 如果您对多个对象使用该指令,则将有更多用处。例如,如果您有一个用户指令,那么您可以:

controllerAs: 'user',

使用 user.profile.nameng-repeat='friend in user.friends'

关于javascript - AngularJS - 使用 controllerAs 语法和服务属性的 DRY 双向数据绑定(bind),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30912547/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com