在我永无止境的追求以"正确"的角度方式做事的过程中,我一直在阅读很多关于如何让控制器观察角度服务中的模型变化.
一些网站称在控制器上使用$ watch是完全错误的:
请勿在控制器中使用$ watch.几乎在所有情况下都很难测试并且完全没有必要.使用范围上的方法来更新手表正在更改的值.
只要你自己清理完以后其他人看起来很好:
$ watch函数本身返回一个函数,该函数在调用时解除$ watch的绑定.因此,当不再需要$ watch时,我们只需调用$ watch返回的函数.
有一些问题和其他声誉良好的网站似乎正确地说,在控制器中使用$ watch是注意角度服务维护模型中的变化的好方法.
该https://github.com/angular/angular.js/wiki/Best-Practices网站,我想我们可以给多一点的重量,直接说是$范围.$手表应该更换事件的需要.但是,对于处理超过100个模型和REST端点的复杂SPA,选择使用$ watch来避免事件$broadcast/$emit可能最终导致大量手表.另一方面,如果我们不使用$ watch,对于非平凡的应用程序,我们最终会产生大量的意大利面条.
这是一个输/输的情况吗?这是事件和手表之间的错误选择吗?我知道你可以在很多情况下使用双向绑定,但有时你只需要一种方法来监听变化.
编辑
Ilan Frumer的评论让我重新思考我的要求,所以也许不仅仅是询问在控制器中使用$ watch是否主观好/坏,让我用这样的方式提出问题:
哪种实现可能会首先造成性能瓶颈?让控制器监听事件(必须已经广播/发出),或者$watch在控制器中设置-es.请记住,大型应用程序.
哪个实现首先会引起维护问题:$watch-es或事件?可以说,无论哪种方式都存在耦合(紧密/松散)......事件观察者需要知道要监听什么,而且$watch- 外部值(如MyDataService.getAccountNumber())需要知道在$ scope范围之外发生的事情.
**一年后编辑**
自从我提出这个问题以来,Angular已经改变/改进了很多,但我仍然得到+ 1,所以我想在提到角度团队的代码时会提到这一点,我看到了控制器中观察者的模式(或者有一个范围被销毁的指令):
$scope.$on('$destroy', $scope.$watch('scopeVariable', functionIWantToCall));
这需要$ watch函数返回的内容 - 可以调用以取消注册观察者的函数 - 并在控制器被销毁时将其提供给事件处理程序.这会自动清理观察者.
无论控制器中的手表是否具有代码味道,如果您使用它们,我相信角度团队对此模式的使用应该作为如何使用它们的强烈建议.
谢谢!
我正在使用角度ui-router获得具有多个视图的angularJS SPA设置.
当我在教程和操作方法中看到网络时,我看到了一堆混合的依赖项.ui-router github页面包含ui.router用作模块依赖的示例,而Ben Schwartz 教程等其他文章则使用ui.state.
有什么不同?一个被弃用了吗?是ui.state子集ui.router吗?
我正在构建一个新的SPA前端,以取代现有企业遗留的过时且需要更新的系统大杂烩.我是棱角分明的新人,想看看社区能否给我一些看法.我会陈述我的问题,然后问我的问题.
我必须基于来自.jsinclude的数据生成几个复选框系列,其数据如下:
$scope.fieldMappings.investmentObjectiveMap = [
{'id':"CAPITAL PRESERVATION", 'name':"Capital Preservation"},
{'id':"STABLE", 'name':"Moderate"},
{'id':"BALANCED", 'name':"Moderate Growth"},
// etc
{'id':"NONE", 'name':"None"}
];
Run Code Online (Sandbox Code Playgroud)
复选框是使用a创建的ng-repeat,如下所示:
<div ng-repeat="investmentObjective in fieldMappings.investmentObjectiveMap">
...
</div>
Run Code Online (Sandbox Code Playgroud)
但是,我需要复选框表示的值映射到不同的模型(不仅仅是2对方式绑定到fieldmappings对象).为此,我创建了一个指令,它接受一个destarray最终映射到模型的目标数组.我也知道我需要处理一些非常具体的gui控件,例如如果检查了其他任何内容则取消选中"None",或者如果其他所有内容都未选中则选中"None".此外,"无"在每组复选框中都不是一个选项,因此指令需要足够通用以接受验证函数,该函数可以checked根据已经点击的内容来调整复选框组输入的状态,但足够聪明如果没有调用选项,不要破坏"NONE".我开始通过添加一个在控制器中调用函数的ng-click来做到这一点,但是在查看堆栈溢出时,我读到人们说将DOM操作代码放在控制器中是不好的 - 它应该在指令中.所以我需要另一个指令吗?
到目前为止:(html):
<input my-checkbox-group
type="checkbox"
fieldobj="investmentObjective"
ng-click="validationfunc()"
validationfunc="clearOnNone()"
destarray="investor.investmentObjective" />
Run Code Online (Sandbox Code Playgroud)
指令代码:
.directive("myCheckboxGroup", function () {
return {
restrict: "A",
scope: {
destarray: "=", // the source of all the checkbox values
fieldobj: "=", // the array the values came from …Run Code Online (Sandbox Code Playgroud) 我试图用这个种子项目作为模型来连接Karma测试运行器.
我拉进了种子项目,构建它,测试运行器运行良好.
当我编辑karma.conf.js配置文件以开始包含我的项目中的文件,并将其移动到我当前的设置(种子项目之外)时,我收到此错误:
Running "karma:dev" (karma) task
ERROR [config]: Error in config file!
[ReferenceError: JASMINE is not defined]
ReferenceError: JASMINE is not defined
at module.exports (C:\dev_AD_2014.01_PHASE1\config\karma-dev.conf.js:4:7)
...
Run Code Online (Sandbox Code Playgroud)
我想我看到它在抱怨......在种子工程,这是因果报应的配置文件是较旧的格式,即必须有JASMINE和JASMINE_ADAPTER地方规定:
种子项目业力配置片段
files = [
JASMINE,
JASMINE_ADAPTER,
'../app/lib/angular/angular.js',
'lib/angular/angular-mocks.js',
'../app/js/*.js',
....
];
exclude = ['karma.conf.js'];
...
Run Code Online (Sandbox Code Playgroud)
我的新设置使用了所有最新的grunt插件,并希望配置文件包含在模块定义中,如下所示:
我的业力配置片段
module.exports = function(config) {
config.set({
files: [
JASMINE,
JASMINE_ADAPTER,
// library and vendor files
'../dev/vendor/**/*.js'
'../dev/app/**/*.js'
],
exclude: ['**/*.e2e.js', '../config/*.js'],
reporters: ['progress'],
...
Run Code Online (Sandbox Code Playgroud)
所以看起来问题很清楚:一些grunt插件的较新版本需要模块化定义,但是设置JASMINE等等更长,因为它们是定义的变量.这是我的猜测,但我对如何解决这个问题感到有点迷茫.如果我可以帮助它,我不想使用种子项目附带的Karma版本......我认为它的版本是0.4.4.我相信最新的稳定版本是0.10.x.
我究竟做错了什么? …
我正在使用webpack 2,它会告诉我我的打字稿代码是否存在编译问题.但是,我还没有找到一种方法来运行tslint并让它在webpack运行在dev-server模式时检测到的每个更改都运行.
我试过让tslint-loader工作,但对于我项目中的每个文件,它只是告诉我:
/src/main.tsNo指定了有效规则
我正在使用它:
rules: [
{
test: /\.ts$/,
enforce: 'pre',
loader: 'tslint-loader',
options: {
configuration: {
configFile: true // I have also tried setting this to "tslint.json"
}
}
},
... more loaders...
Run Code Online (Sandbox Code Playgroud)
仍然没有快乐.
有一种方法可以:
tslint ./src/**/*.ts -t --force,但--watch根据tslint文档还有一个不存在的附加标志.我不想使用我的编辑器(例如VS Code),因为我团队中的每个人都不会使用它.我希望解决方案包含在webpack配置或package.json脚本中.
谢谢!
我是 requireJS 的新手,我想启动并运行一个简单的入门“hello worldish”项目。不过,我遗漏了一些东西,因为angular is not defined在GreetCtrl尝试加载时出现 JS 错误。
索引.html:
<!DOCTYPE html>
<html ng-app="ReqApp" ng-controller="GreetCtrl">
<body>
<h1>{{greeting}}!</h1>
<script src="assets/require/require.js" data-main="assets/require/main"></script>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)
主要.js:
require.config({
// alias libraries paths
paths: {
'domReady': 'domReady',
'angular': '../../vendor/angular/angular.min',
'GreetCtrl': '../../src/app/modules/GreetCtrl',
'app': '../../src/app/app'
},
// angular does not support AMD out of the box, put it in a shim
shim: {
'angular': {
exports: 'angular'
}
},
// kick start application
deps: ['./bootstrap']
});
Run Code Online (Sandbox Code Playgroud)
引导程序.js:
define([
'require',
'angular',
'app'
], function …Run Code Online (Sandbox Code Playgroud) 我正在尝试将requirejs集成到现有项目中,该项目在node/grunt堆栈上运行.我想使用r.js优化器将所有内容连接在一起并通过依赖关系来实现它的魔力.
我能够让r.js构建一个.js文件,并且没有错误......但没有任何反应.我在我的代码中设置了断点,但没有任何东西被启动 - 应用程序从未实际运行 bootstrap.js文件.我已经尝试将bootstrap.js放在一个立即函数中,当然它确实运行了,但依赖项尚未加载(似乎).我在这里错过了什么?
文件结构:
app
-> modules
- -> common
- - -> auth.js // contains an auth call that needs to return before I bootstrap angular
-> app.js
-> index.html
config
-> main.js
node_modules
vendor
-> angular/jquery/require/domready/etc
gruntfile.js
Run Code Online (Sandbox Code Playgroud)
gruntfile requirejs任务:
requirejs: {
compile: {
options: {
name: 'app',
out: 'build/js/app.js',
baseUrl: 'app',
mainConfigFile: 'config/main.js',
optimize: "none"
}
}
},
Run Code Online (Sandbox Code Playgroud)
main.js配置:
require.config({
paths: {
'bootstrap': '../app/bootstrap',
'domReady': '../vendor/requirejs-domready/domReady',
'angular': '../vendor/angular/angular',
'jquery': '../vendor/jquery/jquery.min',
'app': 'app',
'auth': '../app/modules/common/auth',
requireLib: …Run Code Online (Sandbox Code Playgroud) 我正在尝试为返回角度承诺($ q库)的方法编写测试.
我不知所措.我正在使用Karma运行测试,我需要弄清楚如何确认该AccountSearchResult.validate()函数返回一个promise,确认promise是否被拒绝,并检查使用promise返回的对象.
例如,正在测试的方法具有以下(简化):
.factory('AccountSearchResult', ['$q',
function($q) {
return {
validate: function(result) {
if (!result.accountFound) {
return $q.reject({
message: "That account or userID was not found"
});
}
else {
return $q.when(result);
}
}
};
}]);
Run Code Online (Sandbox Code Playgroud)
我以为我可以这样写一个测试:
it("it should return an object with a message property", function () {
promise = AccountSearchResult.validate({accountFound:false});
expect(promise).to.eventually.have.property("message"); // PASSES
});
Run Code Online (Sandbox Code Playgroud)
这传递了,但这也是错误的(错误的):
it("it should return an object with a message property", function () {
promise = AccountSearchResult.validate({accountFound:false});
expect(promise).to.eventually.have.property("I_DONT_EXIST"); // PASSES, should fail
}); …Run Code Online (Sandbox Code Playgroud) 我正在设置一个寻找所有单元测试文件的业力任务的咕噜声.我需要访问所有*.js文件和*.spec.js文件,但我想排除所有*.e2e.js文件.根据节点glob文档,我希望以下工作(在karma.conf.js中):
files: [
'vendor/angular/angular.js',
'vendor/angular-mocks/angular-mocks.js',
'vendor/angular-resource/angular-resource.js',
'app/**/*.js',
'!app/**/*.e2e.js'
],
Run Code Online (Sandbox Code Playgroud)
但是,当我尝试运行我的grunt test任务时,它仍然会尝试加载这些e2e.js测试,因为每个测试都引用了量角器,因此业力会被混淆.根据我的控制台,我看到URL是这样的:
userdirectory/repo/!app/mytest.e2e.js
似乎完整的文件路径(或至少其中一些)正在预先添加到我在karma.conf.js中提供的文件glob模式中.在加载业力任务之后,咕噜咕噜咕噜咕噜吗?
感谢SO社区的一些帮助,我有一个工作角度SPA,使用ui-router库使用多个状态/视图.但是我得到的行为似乎与angular-ui-router文档不一致.
从他们关于onEnter的文档中,我希望无论何时使用$state.go("home"),onEnter()与该状态的配置对象相关的事件都会启动,但我不认为它会发生.例:
/* myApp module */
var myApp = angular.module('myApp', ['ui.router'])
.config(['$stateProvider', function ($stateProvider) {
$stateProvider.state('home', {
url: "/",
views: {
'top': {
url: "",
template: '<div>top! {{topmsg}}</div>',
controller: function ($scope) {
$scope.topmsg = "loaded top!";
console.log("top ctrl!");
},
onEnter: function () {
console.log("entered bottom state's onEnter function");
}
},
'middle': {
url: "",
template: '<div>middle! {{middlemsg}}</div>',
controller: function ($scope) {
$scope.middlemsg = "loaded middle!";
console.log("middle ctrl!");
},
onEnter: function …Run Code Online (Sandbox Code Playgroud) 我使用r.js将jsSPA中的所有代码拼凑成1个文件.我使用grunt的`grunt-contrib-requirejs'任务,具体如下:
requirejs: {
compile: {
options: {
name: 'app',
out: 'build/js/app.js',
baseUrl: 'app',
mainConfigFile: 'config/main.js',
preserveLicenseComments: true,
optimize: "none"
}
}
}
Run Code Online (Sandbox Code Playgroud)
我还使用构建任务将构建文件夹压缩成zip文件,以便发送给我们公司的变更管理人员.
我想有两个requirejs任务 - 一个uglifies(用于发送到CM)和一个没有(在开发期间).这可能吗?我尝试用不同的名字创建一个新任务,咕噜咕噜地叫着我......应该很简单.这可能吗?有没有理由不这样做?
提前致谢!
我想测试一个简单的Angular 2数据服务.该服务使用Http,但没有别的.在快速入门指南中,它说:
但是,使用不依赖于Angular的独立单元测试来探索应用程序类的内部逻辑通常会更有成效.这些测试通常更小,更易于阅读,编写和维护.
编写一个隔离单元测试的例子是,对于简单的服务,你可以通过在每个测试中创建一个新实例来测试服务...可能是这样的:
beforeEach(() => { service = new EventDataService(); });
it('#getEvents should return an observable', () => {
expect(service.getEvents()).toBe(Observable.from([]);
});
Run Code Online (Sandbox Code Playgroud)
但是,我的EventDataService使用Http,所以如果我不将Http放在构造函数中,我会收到错误:
beforeEach(() => { service = new EventDataService(http: Http); });
Run Code Online (Sandbox Code Playgroud)
但是Http不存在,除非我导入它,我不想做 - 我不想测试Http.我尝试将http取消,但我尝试的所有方法最终都失败了或导致我导入更多东西以满足打字稿之神......
我敢肯定我在想这个.我已经尝试过很多关于Angular 2测试的网站上的建议,但是对于我来说,任何超过几个月的建议都是我怀疑的,因为在过去的6-12个月里框架发生了很大变化.对于这样一个简单的例子,我觉得我应该能够保持这么简单.
我做错了什么吗?我使用的是Angular 2 V 2.4.10,Webpack 2.3.1,Sinon 2.1.0和Typescript 2.2.1.
服务:
import { Injectable } from "@angular/core";
import { Http } from "@angular/http";
import { Observable } from "rxjs";
import { Event } from "../event/event.interface";
@Injectable()
export class EventDataService {
events: Event[]; …Run Code Online (Sandbox Code Playgroud) 我有一个要测试的类,它具有多个外部依赖项和几个内部方法。我想编写一个测试MethodA,但没有方法A的内部调用来MethodB进行实际锻炼MethodB。我想模拟/存根MethodB并返回特定的内容。通常我会使用when/thenReturn它,但是它的行为却不像我预期的那样-在创建模拟本身时,它实际上跳入了方法B。
MyService.java
@Service
public class MyService {
@Autowired
private ServiceA serviceA;
@Autowired
private ServiceB serviceB;
public SomeObject methodA() {
// some logic using serviceA.method and serviceB.method that creates "output"
SomeObject someObject = methodB(output);
return someObject;
}
public SomeObject methodB(SomeObject someObject) {
// deep mysteries done here to someObject
return someObject
}
}
Run Code Online (Sandbox Code Playgroud)
MyServiceTest.java
public class MyServiceTest {
@Mock
private ServiceA serviceA;
@Mock
private ServiceB serviceB;
@InjectMocks
private MyService …Run Code Online (Sandbox Code Playgroud) angularjs ×7
gruntjs ×4
karma-runner ×3
requirejs ×3
r.js ×2
amd ×1
angular ×1
chai ×1
jasmine ×1
java ×1
mockito ×1
tslint ×1
typescript ×1
unit-testing ×1
webpack-2 ×1