如何将设置对象从控制器传递到服务?

2024-01-10

tl;dr;

我需要传达多个服务所需的状态,这些状态源自绑定到控制器范围的数据。有什么好的“Angular zen”方式可以做到这一点?

背景故事

我正在开发一个单页应用程序,经过深思熟虑后决定使用 AngularJS。页面的布局方式类似于:

实际的布局并不重要,对于类似的布局,概念保持不变。 我需要传达与以下范围相关的信息SettingsController到控制器中的服务ngView要求。当用户对任何滑块进行修改时,我还需要更新从控制器中的服务获取的内容。

我尝试过的

我想到的唯一方法是:http://jsfiddle.net/5sNcG/ http://jsfiddle.net/5sNcG/我必须自己编写一个绑定并将侦听器添加到范围更改中。我可能离这里很远,并且有一种明显的“角度”方式可以做到这一点 - 然而,尽管我努力,但我无法找到它。

/code from fiddle.
var app = angular.module("myApp",[]);

app.controller("HomeCtrl",function($scope,FooService,$interval){
    FooService.change(function(){
        console.log("HI",FooService.getFoo());
        $scope.foo = FooService.getFoo();
    });
});

app.factory("Configuration",function(){
    var config = {data:'lol'};
    var callbacks = [];
    return {
        list:function(){ return config;},
        update:function(){
            callbacks.forEach(function(x){ x();});
        },
        change:function(fn){
            callbacks.push(fn); // I never remove these, so this is a memory leak!
        }
    }
});
app.service("FooService",function(Configuration){
    return {
        getFoo: function(){
            return Configuration.list().data+" bar";    
        },change:function(fn){
            Configuration.change(fn);    
        }
    }
});
app.controller("SettingsCtrl",function($scope,Configuration){

    $scope.config = Configuration.list();
    $scope.$watch('config',function(){
        Configuration.update();
    },true);
});

我也考虑过$rootScope广播,但这看起来更像是全球国家

无论我尝试什么,我都有一个具有全局状态的单例我们都知道我不想要单身 http://misko.hevery.com/2008/08/17/singletons-are-pathological-liars/.

因为这似乎是一个相当常见的 Angular 用例。解决这个问题的惯用方法是什么?


我过去遇到过类似的事情,并考虑了四种可能的方法:

  • Using $broadcast
  • 将设置存储在$rootScope
  • 观察者模式(就像你在这里一样)
  • Using $watch从控制器

以下是我对每个问题的想法:

$广播

在我看到的 AngularJS 演示中,Miško Hevery 谈到了使用$broadcast(即事件)及其用例。要点是$broadcast更适合对与您正在处理的任何内容不紧密相关的事件做出反应,否则可能会更好地选择替代方案。同样针对这个主题,最佳实践 https://github.com/angular/angular.js/wiki/Best-PracticesAngular wiki 上的指南建议:

仅对原子事件使用 .$broadcast()、.$emit() 和 .$on():活动 与整个应用程序全局相关(例如用户 身份验证或应用程序关闭)。

在这里,因为您的设置与填充的内容密切相关ng-view,它会建议使用的替代方案$broadcast是优选的。

$rootScope

正如您提到的(并且希望避免),这是一种全球状态。将设置公开给我的整个应用程序也不是/不是我个人的偏好,尽管它通常是一个简单的选择。我个人保留$rootScope用于配置设置和“软”变量,例如页面标题等。我不会选择使用此选项。

观察者模式

针对配置工厂注册回调是一种可靠的方法。关于您的持久回调,您可以监听$destroy作用域上的事件,调用remove配置工厂上的方法来删除回调。这可以被认为是一个很好的例子$broadcast使用;控制器关注该事件并且必须对其做出反应,但事件本身并不特定于控制器/配置服务共享的数据。

$watch

通过使用共享服务,可以将其注入到与设置相关的任何控制器中。现在,对配置的任何更改都会触发您的回调,而某些视图可能只涉及一两个配置设置。$watch将使您能够更轻松地观察仅对这些属性的更改。我无法谈论开销与注册回调,但这对我来说感觉是最“有角度”的方式。

这就是如何使用它来实现$watch:

var app = angular.module("myApp",[]);

app.factory("Configuration",function(){
   var data = {
     settingOne: true,
     settingTwo: false 
   };
   return data;
})

app.controller("SettingsCtrl",function($scope, Configuration){
  // do something
})

app.controller("HomeCtrl",function($scope, Configuration){
   // detect any change to configuration settings
   $scope.$watch(function() {
     return Configuration;
   }, function(data) {
     // do something
   }, true)

   // alternatively only react to settingTwo changing
   $scope.$watch(function() {
     return Configuration.settingTwo
   }, function(data) {
     // do something
   })
})

请注意,如果您需要稍微复杂的配置工厂,您可以转而使用 getter/setter 方法并将配置设置本身保持私有。然后,在$watch,您应该观察方法调用而不是属性本身。

UPDATE:

在回答时,我更喜欢采用$watch在控制器内。使用框架开发一段时间后,我现在尝试保留$watch完全脱离控制器,而是在可能的情况下更喜欢在值更改时直接调用函数,或者通过利用ng-change.

这样做的原因之一是它增加了测试控制器的复杂性,但也许更重要的是它效率低下:对于每个$digest循环角度调用,每个注册$watch无论如何都会被评估,并且它很可能会响应对现有值所做的更改$watch.

这里有一篇关于这个问题的非常好的文章,而不是从这个角度推测缺点和解决方案:Angular JS - 你可能不应该在控制器中使用 $watch http://www.benlesh.com/2013/10/title.html.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何将设置对象从控制器传递到服务? 的相关文章

  • JQuery datepickers-从开始日期设置结束日期

    使用了两个 Jquery 日期选择器 StartDate 和 EndDate
  • 水平滚动的表格上的“粘性”标题......完全不可能?

    经过过去几个小时的研究后 我开始认为这是不可能的 即使在最新的浏览器上也是如此 HTML table具有水平滚动的元素 带有 粘性 thead在顶部 作为垂直滚动的周围网页的一部分 这是我的尝试 a height 100px backgro
  • 设置双指缩放时精确的滚动位置

    我正在创建一个地图应用程序 它将标记图像放置在画布上并滚动到它 我正在使用浏览器的捏缩放和滚动来放大 缩小地图 然而 我注意到有一些奇怪的行为 我想知道如何解决它 这有点难以解释 但我们开始吧 假设您处于网页的标准缩放级别 无法进一步缩小
  • 访问 nuxt 配置文件中的存储

    我想添加通过 Nuxt 静态生成的动态路由 我定义了一个客户端 服务器端存储asyncData方法 我想将这个存储值 一个数组 映射到我的nuxt config js文件使其成为 动态 静态 路线图nuxt generate命令 但如何访问
  • Ionic/Cordova 应用程序中的身份验证

    首先 我不是专业人士 在我成为一名更好的开发人员的过程中 我试图了解需要什么以及如何完成为 Ionic Framework 应用程序创建注册 登录 大多数单页应用程序 SPA 在节点服务器上处理身份验证 该服务器还为客户端提供 HTML 就
  • JavaScript 将键添加到数组中的每个值

    我下面有这个数组 它由一个简单的数组组成 我想要完成的是放一把钥匙id在每个数组值前面以实现类似的效果 id a id b id c id d 有没有一种简单的方法可以做到这一点 任何帮助将不胜感激 谢谢 var test a b c d
  • 如何在 React Native 上显示 SVG 文件?

    我想显示 svg 文件 我有一堆 svg 图像 但我找不到显示的方式 我尝试使用Image and Use的组成部分反应本机 svg https github com magicismight react native svg但他们不这样做
  • 如何在 Web 服务器上设置 gzip 压缩?

    我有一个嵌入式网络服务器 总共有 2 兆空间 通常 您使用 gzip 文件对客户端有利 但这会节省我们在服务器上的空间 我读到你可以只 gzip js 文件并将其保存在服务器上 我在 IIS 上测试过 但没有任何运气 为了使这项工作成功 我
  • webpack中动态加载外部模块失败

    我正在尝试建立以下架构 一个核心 React 应用程序 它具有一些基本功能 并且能够在运行时加载其他 React 组件 这些额外的 React 组件可以按需加载 并且它们在构建核心应用程序时不可用 因此它们不能包含在核心应用程序的捆绑包中
  • 如何使用新的analytics.js跟踪多个帐户?

    我需要使用 Google 的新的analytics js 跟踪一个页面上两个帐户的综合浏览量 有大量教程和示例如何使用较旧的 ga js 进行操作 但我发现的只是这个分析文档页面 https developers google com an
  • Web组件中嵌套槽的内容不可见

    我有一个 Web 组件 它应该接受任意元素来包装其内容 虽然我可以在 Chrome 开发工具中看到插槽已正确分配 但 DOM 中什么也没有出现 以前有人见过这个问题吗 定义 class ExampleParent extends HTMLE
  • javascript 是否有等效的 __repr__ ?

    我最接近Python的东西repr这是 function User name password this name name this password password User prototype toString function r
  • 如何动态调整jqgrid到当前窗口大小?

    如何动态调整jqgrid到当前窗口大小 基于javascript jQuery 最好的例子在这里 TinyMCE 去 http www tinymce com tryit full php http www tinymce com tryi
  • 类中可以有生成器 getter 吗?

    我的意思是吸气剂是发电机 我相信这一切都是 ES6 也许像这样 class a get count let i 10 while i yield i let b new a for const i of b count console lo
  • 扩展 RegExp 以获取文件扩展名

    我知道 已经有很多基于 RegExp 的解决方案 但是我找不到适合我需求的解决方案 我有以下函数来获取 URL 的各个部分 但我还需要文件扩展名 var getPathParts function url var m url match w
  • 如何重复 ajax 请求,直到满足 RxJS Observable 的条件?

    我正在尝试重复请求 直到响应包含使用 RxJS 的数据 此时我想调用成功 或失败 处理程序 但我在使用 RxJS 时遇到了麻烦 这是我目前的方法 redux observable action observable mergeMap gt
  • ChartJs:如何按时间值(而不是像素)以编程方式平移

    我使用的是chartJs 3 6 1 和 Chartjs plugin zoom 1 2 1 但我认为这并不重要 我有 2 个时间序列折线图 当我通过拖放平移一个图表时 我也想移动 平移另一个图表 为此 我为 graphA 启用了缩放 平移
  • 尝试使用 Javascript 解决对称差异

    我正在尝试找出对称的解决方案 使用 javascript 完成以下任务的差异 目标 接受未指定数量的数组作为参数 保留数组中数字的原始顺序 不删除单个数组中数字的重复项 删除数组中出现的重复项 因此 例如 如果输入是 1 1 2 6 2 3
  • 将多维数组转换为单数组(Javascript)

    我有一个对象数组 来自 XLSX js 解析器 因此其长度和内容各不相同 表示已给予项目的资助 简化后 它看起来像这样 var grants id p 1 location loc 1 type A funds 5000 id p 2 lo
  • 如何在运行脚本之前提交活动单元格中所做的更改? (Google 表格/Google Apps 脚本)

    我正在使用 Google Apps 脚本在 Google 表格中创建提交表单 该表单位于一页上 提交内容被移至第二个隐藏页面 当用户填写表单后 他们按下提交页面上的按钮以激活脚本 我遇到的问题是 当用户填写最后一个单元格然后单击按钮时 输入

随机推荐