jjzjj

javascript - 我应该总是将函数绑定(bind)到 $scope 对象吗?

coder 2024-07-22 原文

当我创建 Controller 时,我总是将函数添加到 $scope对象,像这样:

function DummyController($scope) {

  $scope.importantFunction = function () { /*...*/ };

  $scope.lessImportantFunction = function () { /*...*/ };

  $scope.bussinessLogicFunction = function () { /*...*/ };

  $scope.utilityFunction = function () { /*...*/ };

}

当然,我会很好地封装我的 Controller ,确保业务逻辑位于适当的组件(通过 DI 注入(inject))或服务中。因此 Controller 专注于协调 UI 和后端之间的事情。

但是,正如您所看到的 - 仍然有许多不同类型的功能。我喜欢保留更多,因为它提高了恕我直言的可读性。

问题
将许多函数附加到 $scope 对象是一个好习惯吗?它有性能开销吗?我知道$scope是一种特殊的对象,在 Angular 的摘要循环中不断地被评估,所以我这样做是对的还是我会坚持我的方法来自找麻烦?

(请注意:我不是在寻找替代方法。我在寻找对了解 Angular 内部结构的人的一些深思熟虑的分析。)

谢谢!

更新:

Anders 的回答非常好,向您展示了一些可以遵循的路径。今天偶遇了这位美女,一个chrome extension for Angular Js debugging and performance monitoring .它向您展示了所有范围和分配的变量,以及一些有趣的性能图表。任何 Angular 开发人员都必须拥有!

最佳答案

更新:

  • 我应该将所有函数和变量添加到范围吗?

    不,如果您需要在模板中访问它们,您应该只将函数和变量添加到您的范围。仅在 Controller 函数中访问的变量不应该在范围内,它应该是 Controller 函数的本地变量。
  • 如果我在范围内添加很多功能会影响性能吗?

    一般来说,没有。作用域上执行的函数如 ng-click="myFunction()"不应以明显的方式影响性能。但是如果你的函数是这样执行的:{{myFunction()}}它将为每个摘要执行,因为 Angular 需要知道它的返回值是否已更改,以便它可以更新 UI。
  • 如果我在作用域中添加很多变量会影响性能吗?

    如果你在 Angular 会脏检查它们的地方使用它们,它可能会影响性能。这些案例是您打印出来的地方,例如 {{myVariable}} , 如果您在 ng-model="myVariable" 中使用它们, ng-show="myVariable"等指令,如 ng-click不执行脏检查,因此不会减慢速度。 Angular 背后的人建议你不要在一页上使用超过 2000 个需要重新绘制/脏检查的表达式,因为在那之后你的性能会开始下降。 2000 的限制是他们在研究 Angular 性能时发现的。

    请注意,仅仅因为您在范围上添加了一个属性,并不意味着 Angular 会对它执行脏检查。它们必须在您的模板中使用才能执行脏检查(但不能用于 ng-click)。
  • 如果我想在我的 Angular 应用程序中获得最佳性能,我应该注意什么?

    就像我上面提到的,尝试将绑定(bind)模板表达式的数量保持在 2000 以下。如果您在您的范围内实现 watch,请确保 watch 的表达式执行得非常快。这是你不应该这样做的一个例子:
    $scope.items = [];
    for (var i = 0; i < 1000; i++) {
        $scope.items.push({prop1: 'val1', prop2: 'val2', prop3: 'val3'});
    }
    
    $scope.$watch('items', function() {
    
    }, true);
    

    通过添加 true作为 $watch 的第三个参数,你告诉 Angular 循环 $scope.items为每个摘要周期检查一千个项目的任何属性是否已更改,这在时间和内存上都将是昂贵的。

    你应该做的是:
    $scope.items = [];
    for (var i = 0; i < 1000; i++) {
        $scope.items.push({prop1: 'val1', prop2: 'val2', prop3: 'val3'});
    }
    
    $scope.$watch('items.length', function() {
    
    });
    

    即只在 $scope.items.length 时检查已经改变。该表达式将执行得非常快。


  • 原帖:

    如果您的问题是“向模板公开函数是否比对象更好”,那么是的,您应该尽可能多地使用函数。这样你就可以将逻辑封装在 Controller 内部,而不是让它渗入你的模板。举个例子:
    <div ng-show="shouldShow">Toggled div</div>
    <button ng-click="shouldShow = !shouldShow">Toggle<button>
    

    这里的模板对正在发生的事情有太多的了解。相反,这应该像这样解决:
    // controller
    var shouldShow = false;
    scope.toggle = function() {
        shouldShow = !shouldShow;
    }
    scope.shouldShow = function() {
        return shouldShow;
    }
    
    <!-- template -->
    <div ng-show="shouldShow()">Toggled div</div>
    <button ng-click="toggle()">Toggle<button>
    

    通过这样做,在不接触模板的情况下扩展 Controller 中的逻辑是微不足道的。虽然您现在的要求可能只是在按下按钮时切换 div,但明天的要求可能是在发生这种情况时更新应用程序的其他部分。如果您改用函数,则可以很容易地在函数中添加该逻辑,而无需更改模板。

    作用域上的函数比使用属性的开销要多一些,但是当那一天到来时,这些开销可能不会成为减慢应用程序速度的原因。所以在有意义的时候使用函数。

    但是你仍然应该尽量保持你的 Controller 尽可能小。如果它们增长到包含大量功能/功能,您可能应该将您的 Controller 拆分为可重用的指令。

    关于javascript - 我应该总是将函数绑定(bind)到 $scope 对象吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15018821/

    有关javascript - 我应该总是将函数绑定(bind)到 $scope 对象吗?的更多相关文章

    1. ruby - 如何从 ruby​​ 中的字符串运行任意对象方法? - 2

      总的来说,我对ruby​​还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用

    2. ruby-on-rails - 按天对 Mongoid 对象进行分组 - 2

      在控制台中反复尝试之后,我想到了这种方法,可以按发生日期对类似activerecord的(Mongoid)对象进行分组。我不确定这是完成此任务的最佳方法,但它确实有效。有没有人有更好的建议,或者这是一个很好的方法?#eventsisanarrayofactiverecord-likeobjectsthatincludeatimeattributeevents.map{|event|#converteventsarrayintoanarrayofhasheswiththedayofthemonthandtheevent{:number=>event.time.day,:event=>ev

    3. ruby - 检查 "command"的输出应该包含 NilClass 的意外崩溃 - 2

      为了将Cucumber用于命令行脚本,我按照提供的说明安装了arubagem。它在我的Gemfile中,我可以验证是否安装了正确的版本并且我已经包含了require'aruba/cucumber'在'features/env.rb'中为了确保它能正常工作,我写了以下场景:@announceScenario:Testingcucumber/arubaGivenablankslateThentheoutputfrom"ls-la"shouldcontain"drw"假设事情应该失败。它确实失败了,但失败的原因是错误的:@announceScenario:Testingcucumber/ar

    4. ruby-on-rails - 如何验证非模型(甚至非对象)字段 - 2

      我有一个表单,其中有很多字段取自数组(而不是模型或对象)。我如何验证这些字段的存在?solve_problem_pathdo|f|%>... 最佳答案 创建一个简单的类来包装请求参数并使用ActiveModel::Validations。#definedsomewhere,atthesimplest:require'ostruct'classSolvetrue#youcouldevencheckthesolutionwithavalidatorvalidatedoerrors.add(:base,"WRONG!!!")unlesss

    5. Ruby 写入和读取对象到文件 - 2

      好的,所以我的目标是轻松地将一些数据保存到磁盘以备后用。您如何简单地写入然后读取一个对象?所以如果我有一个简单的类classCattr_accessor:a,:bdefinitialize(a,b)@a,@b=a,bendend所以如果我从中非常快地制作一个objobj=C.new("foo","bar")#justgaveitsomerandomvalues然后我可以把它变成一个kindaidstring=obj.to_s#whichreturns""我终于可以将此字符串打印到文件或其他内容中。我的问题是,我该如何再次将这个id变回一个对象?我知道我可以自己挑选信息并制作一个接受该信

    6. ruby - ruby 中的 TOPLEVEL_BINDING 是什么? - 2

      它不等于主线程的binding,这个toplevel作用域是什么?此作用域与主线程中的binding有何不同?>ruby-e'putsTOPLEVEL_BINDING===binding'false 最佳答案 事实是,TOPLEVEL_BINDING始终引用Binding的预定义全局实例,而Kernel#binding创建的新实例>Binding每次封装当前执行上下文。在顶层,它们都包含相同的绑定(bind),但它们不是同一个对象,您无法使用==或===测试它们的绑定(bind)相等性。putsTOPLEVEL_BINDINGput

    7. ruby - 在没有 sass 引擎的情况下使用 sass 颜色函数 - 2

      我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re

    8. ruby-on-rails - 如果 Object::try 被发送到一个 nil 对象,为什么它会起作用? - 2

      如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象

    9. ruby-on-rails - 未在 Ruby 中初始化的对象 - 2

      我在Rails工作并有以下类(class):classPlayer当我运行时bundleexecrailsconsole然后尝试:a=Player.new("me",5.0,"UCLA")我回来了:=>#我不知道为什么Player对象不会在这里初始化。关于可能导致此问题的操作/解释的任何建议?谢谢,马里奥格 最佳答案 havenoideawhythePlayerobjectwouldn'tbeinitializedhere它没有初始化很简单,因为你还没有初始化它!您已经覆盖了ActiveRecord::Base初始化方法,但您没有调

    10. ruby - 如何在 Rails 4 中使用表单对象之前的验证回调? - 2

      我有一个服务模型/表及其注册表。在表单中,我几乎拥有服务的所有字段,但我想在验证服务对象之前自动设置其中一些值。示例:--服务Controller#创建Action:defcreate@service=Service.new@service_form=ServiceFormObject.new(@service)@service_form.validate(params[:service_form_object])and@service_form.saverespond_with(@service_form,location:admin_services_path)end在验证@ser

    随机推荐