AngularJS는 많은 Google 제품에서 사용되어 온 뛰어난 프런트엔드 JS 프레임워크입니다. AngularJS에는 MVC, 모듈화, 자동화된 양방향 데이터 바인딩, 의미 태그, 종속성 주입 등 많은 기능이 있으며 그 중 가장 핵심은 다음과 같습니다. 이 기사에서는 주로 jQuery를 사용하는 방법과 AngularJS 프로그래밍 아이디어를 사용하는 방법을 공유합니다.
1. 클라이언트 측 웹 애플리케이션을 어떻게 다르게 설계하고 디자인할 수 있나요? 그들 사이의 가장 큰 차이점은 무엇입니까? (역자 주: jQuery 및 Angular.js 참조)
2. 하지 말아야 할 것과 사용하지 말아야 할 것은 무엇입니까?
3. 서버 측 고려 사항/제약 사항이 있나요?
제가 찾고 있는 것은 jQuery와 Angular.js의 상세한 비교입니다. ”
다음은 Josh David Miller의 가장 좋은 답변입니다.
1. 페이지를 먼저 디자인한 다음 DOM 조작을 사용하여 변경하지 마세요.
jQuery에서는 페이지를 먼저 디자인한 다음 변경하게 됩니다. 이는 jQuery가 점점 더 확장되고 커지도록 설계되었기 때문입니다.
하지만 Angular.js에서는 처음부터 아키텍처를 염두에 두어야 합니다. DOM을 사용하고 싶습니다. Angular.js로 jQuery를 확장하지 마세요.
마찬가지로 jQuery가 X, Y, Z를 수행할 수 있다는 생각으로 시작하지 마세요. 따라서 그냥 Angular.js를 추가하겠습니다. 처음에는 여러분을 유혹하기가 정말 쉽습니다. 그렇기 때문에 저는 항상 Angular.js 초보자에게 적어도 "Angular 방식"에 익숙해질 때까지 jQuery를 전혀 사용하지 말 것을 권장합니다
저는 여기 있습니다(번역가의 메모: stackoverflow를 참조합니다. ). 메일링 리스트에서 많은 개발자가 jQuery 플러그인용으로 150~200줄의 코드를 가져온 다음 혼란스럽고 복잡한 콜백과 $apply를 Angular.js와 함께 사용하면 결국 작동합니다. 그러나 대부분의 경우 작은 Angular.js 코드로 jQuery 플러그인을 다시 작성할 수 있으며 이 방법을 사용하면 모든 것이 단순하고 명확해집니다.
이런 유형의 문제에 대한 결론은 다음과 같습니다. 문제를 해결할 때 먼저 "Angular.js 사고"를 사용하여 해결책을 찾을 수 없으면 물어보세요. 커뮤니티에서 여전히 간단한 해결책이 없다면 jQuery를 사용해 보세요. 하지만 jqeury를 버팀목으로 삼지 마십시오. 그렇지 않으면 결코 Angular.js를 마스터할 수 없습니다.
3. 아키텍처 측면에서
먼저 알아야 할 것은 단일 페이지 구조는 웹 페이지가 아니기 때문에 서버 측 개발자의 사고와 클라이언트 측 개발자의 사고가 필요합니다. 애플리케이션을 독립적이고 확장 가능하며 테스트 가능한 구성 요소로 나누는 방법에 대해
그렇다면 어떻게 해야 할까요? "angualrjs 사고"를 어떻게 사용합니까? jQuery와 비교하여 몇 가지 일반적인 원칙이 있습니다.
뷰는 "공식적으로 문서화되어 있습니다".
jQuery에서는 프로그래밍 방식으로 뷰를 변경합니다. 다음과 같이 ul 태그를 통해 드롭다운 메뉴를 정의할 수 있습니다.
<ul class="main-menu"> <li class="active"> <a href="#/home">Home</a> </li> <li> <a href="#/menu1">Menu 1</a> <ul> <li><a href="#/sm1">Submenu 1</a></li> <li><a href="#/sm2">Submenu 2</a></li> <li><a href="#/sm3">Submenu 3</a></li> </ul> </li> <li> <a href="#/home">Menu 2</a> </li> </ul>
jQuery에서는 애플리케이션 논리에 따라 다음과 유사한 명령문을 사용하여 활성화할 수 있습니다. 팔로우
$('.main-menu').dropdownMenu();
뷰만 보면, 아니, 바로 그 기능을 보실 수 있을 겁니다. 소규모 애플리케이션의 경우 이는 괜찮습니다. 그러나 대규모 애플리케이션의 경우 상황이 갑자기 혼란스러워지고 유지 관리가 어려워집니다.
그러나 Angular.js에서 뷰는 뷰 기반 기능에 대한 공식적인 문서입니다. 우리의 ul은 다음과 같이 선언됩니다:
<ul class="main-menu"dropdown-menu> ... </ul>
둘 다 실제로 동일한 작업을 수행하지만 Angular.js 버전에서는 이 템플릿을 보는 사람은 누구나 무슨 일이 일어날지 알 수 있습니다. 새로운 개발자가 팀에 합류할 때마다 dropdownMenu라는 지시문이 뷰에 적용되는 것을 한 눈에 볼 수 있으며, 정답을 찾기 위해 코드를 추측하거나 연구할 필요가 없습니다. 뷰 자체가 무슨 일이 일어날지 알려줍니다. 훨씬 더 명확합니다.
angualrjs의 초보자는 종종 다음과 같은 질문을 합니다: 특정 유형의 모든 링크를 어떻게 찾고 여기에 명령을 추가합니까? 내 친구들은 우리의 대답을 보고 충격을 받았습니다. 절대 이러지 마세요. 하지만 내가 이렇게 하지 말라고 조언하는 이유는 절반은 jQuery이고 절반은 angulrjs이고 그건 정말 나쁘기 때문입니다. 여기서 문제는 개발자가 angualrjs 컨텍스트에서 jQuery 방식을 사용하기를 원한다는 것입니다. 그리고 이것은 확실히 작동하지 않을 것입니다. 조회수는 공식 기록입니다. 지시문의 범위 밖에서 DOM을 변경해서는 안 됩니다(자세한 내용은 아래 참조). 게다가 지시 사항이 뷰에 적용되어 목적이 자연스럽게 명확해졌습니다.
기억하세요: 먼저 디자인한 다음 수정하지 마세요. 먼저 설계를 하고 그 다음으로 디자인을 생각해야 합니다.
데이터 바인딩
이것은 현재 Angular.js의 가장 멋진 기능 중 하나이며 앞서 언급한 모든 필수 DOM 작업을 즉시 종료합니다. 직접 할 필요가 없습니다. Angular.js가 자동으로 뷰를 업데이트합니다!
在jQuery里, 我们响应事件并更新内容,大概是这个样子:
$.ajax({ url:'/myEndpoint.json', success:function( data, status ) { $('ul#log').append('<li>Data Received!</li>'); } });
视图则看上去是这样的:
<ul class="messages"id="log"> </ul>
除了关注点混合的问题,这里同样有之前提到的表征目的的问题。更重要的是,我们不得不手动引用并更新dom节点。并且如果我们想要删除一个日志,我们不得不再次对dom编程操作。我们怎样才能抛开dom来测试逻辑呢?还有,如果我们希望改变展现呢?
真是让人凌乱。。。
但是在Angular.js中,我们可以这样做:
$http( '/myEndpoint.json').then(function( response ) { $scope.log.push( { msg:'Data Received!'} ); });
我们的视图看上去是这样的:
<ul class="messages"> <li ng-repeat="entry in log">{{ entry.msg }}</li> </ul>
但是考虑到刚才提到的问题,我们的视图看上去可以是这样的:
<div class="messages"> <div class="alert"ng-repeat="entry in log"> {{ entry.msg }} </div> </div>
现在,替换掉了无序列表,我们使用Bootstrap警告框。同时我们根本不需要改变控制器代码!更重要的是,不论日志何时或者如何更新,视图也会跟着改变。自动的!漂亮!
虽然我没有在这里演示出来,但是数据绑定是双向的。所以这些日志信息同样可以在视图中被编辑,就像这样:
<input ng-model= "entry.msg" />
是不是更开心了?
不同的模型层
在jQuery中,dom有点像模型。但是在angualrjs中,我们有一个分离的模型层, 而这个模型层可以让我们用任何方式管理,完全独立于视图。这对于上面说的数据绑定很有帮助, 还可以维护关注点分离,并且引入更多的可测试性。其它的答案提到了这点,所以我这里就不再赘述了。
关注点分离
以上所有的这些把我们带入了这样的主题:保持你的关注点分离。你的视图表现的像记录什么会发生(大部分情况)的正式记录;你的模型表现你的数据;你有一个服务层来执行可重用的任务;你执行dom操作并通过指令扩展你的视图;并且你用控制器来组合这些。这些同样已经在其它答案中提到,我在这里唯一还要提出的一个事情就是可测试性,我会在下文的另一节里专门讨论。
依赖注入
依赖注入是让我们实现关注点分离的方法。如果你是一个服务器端的开发者(从java到php),你可能对这个概念已经非常熟悉了,但是如果你是一个来自jQuery的客户端的朋友,那么你可能会认为这个概念是傻浅挫。但是它可不是:)
从一个更广的观点来看, 依赖注入意味着你可以非常自由的声明组件,然后你可以通过任意其它组件,呼叫一个它的实例,然后授权。
你不需要知道载入顺序,或者文件位置,或者其它类似的东西。这种强大的力量可能不会立刻显现,但是我这里会提供一个(通常)的例子:测试。
比如在我们的应用中,需要一个通过REST API,同时也依赖于应用状态,本地存储实现了服务器端存储的服务。当在我们的控制器上跑测试的时候,我们不希望与服务器端通讯-毕竟我们在测试控制器。我们能够仅仅添加一个与我们原始组件同名的mock服务,注入器将确保我们的控制器自动获取伪造对象–我们的控制器不会也不需要知道它们的区别。
那么既然提到测试……
4. 保持测试驱动的开发
这个其实是关于架构的第三节的一部分,但是这个主题非常重要,所以我需要将其提出来作为自成体系的部分。
那些你看过,用过,写过的所有jQuery插件,它们中有多少有相应的测试包?不是很多吧? 因为jQuery可不是很遵守这个规矩。但是angualrjs是。
在jQuery中, 测试的唯一方法是用示例页面来独立地创建组件,针对该页面我们的测试可以实施dom操作。于是我们就不得不分离地开发一个组件然后将其集成进我们的应用。多么不方便啊!
那么多时间啊,当我们使用jQuery开发时,我们选择使用迭代开发代替测试驱动的开发。可以谁又能怪我们呢?
但是因为我们有关注点分离,我们能够在Angular.js里反复使用测试驱动开发。举个例子,我们想要一个超简单的指令来指示在菜单中我们目前的路径是什么。我们可以在视图中这样声明我们想获取的:
<a href="/hello"when-active>Hello</a>
好了,我们现在可以写个测试:
it( 'should add "active" when the route changes', inject(function() { varelm = $compile('<a href="/hello" when-active>Hello</a>')( $scope ); $location.path('/not-matching'); expect( elm.hasClass('active') ).toBeFalsey(); $location.path('/hello'); expect( elm.hasClass('active') ).toBeTruthy(); }));
我们运行测试,并确认它是失败的。那么我们来写下我们的指令:
.directive( 'whenActive',function( $location ) { return{ scope:true, link:function( scope, element, attrs ) { scope.$on('$routeChangeSuccess',function() { if( $location.path() == element.attr('href') ) { element.addClass('active'); } else{ element.removeClass('active'); } }); } }; });
现在我们的测试通过了,并且我们的菜单按照请求运行。我们的开发是迭代并且测试驱动的,太酷了哦!
5. 从概念上来看,指令不是打包的jQuery
你会经常听到“只在指令里做dom操作”。这是必要的。请对它表示出尊重!
但是让我们谈点更深入的。。。
一些指令只是装饰那些在视图里的已有的(想想ngClass),因此有时候就直接进行dom操作,基本上都能搞定。但是如果一个指令像个“widget”并有一个模板,
那它同样要遵守关注点分离原则。也就是说,这个模板也应该与它在链接和控制器函数里的实现保持最大的独立。
Angular.js自带着一套工具让这件事变得简单; 使用ngClass我们能够动态的更新类;ngBind允许双向的数据绑定;ngShow和ngHide以编程的方式显示或隐藏一个元素;还有更多–包括我们自己写的那些。换句话说, 我们可以不用DOM操作来实现所有的酷炫的事儿。 dom操作越少,指令越容易测试,它们也更容易样式化,在未来它们也更容易改变,并且也变得更加可重用和可分发。
我看到很多Angular.js开发新手将指令当做放置一堆jQuery的地方。换句话说, 他们认为:“既然我不能在控制器里做dom操纵,那么我就把这段代码放到指令里”。当然这看上去好多了,但是通常这仍然是错的。
想一下在第三节里我们编写的日志记录。即使我们将其放到一个指令里,我们仍然希望用“anggualjs方式”来做这件事情。这仍然没有做任何dom操作!在很多情况下dom操作是必须的,但是这种情况其实比你想的少得多!在你在你的应用中到处使用dmo操作之前,问问你自己,这真的是必须的吗。可能有更好的方法呢。
这里用一个简单的例子来展示我们经常会看到的一个模式。我们需要一个切换按钮。(注意:这个例子有那么一点人为设计的技巧并且有点啰嗦,但是很多更复杂的情况其实也完全可以根据这个例子的方式来解决。)
.directive( 'myDirective',function() { return{ template:'<a class="btn">Toggle me!</a>', link:function( scope, element, attrs ) { varon =false; $(element).click(function() { if( on ) { $(element).removeClass('active'); } else{ $(element).addClass('active'); } on = !on; }); } }; });
这里有一些错误。第一,jQuery不是必须的。我们这里做的一切都不需要jQuery!第二, 即使是我们的页面上已经有jQuery,也没有理由一定要在这里使用它;我们可以简单的使用angular.element,而且就算在一个没有jQuery的项目中我们的组件仍然可以工作。第三,即使我们假设为了让这个指令工作,jQuery是必须的,如果jqury被加载,那么jqLite(angler.element)一定会使用jQuery。所以我们不需要使用$(译者注:jQuery的一个标识符号,是jQuery函数的别名)–我们可以使用angular.element。第四, 紧接第三点,jqLite元素不需要被包裹在$里–传递给link函数的element已经是一个jQuery元素!第五, 我上一节已经提过的,为什么我们要将模板混合进我们的逻辑呢?
这个指令可以更精简的重写(即时在更复杂的例子里也一样):
.directive( 'myDirective',function() { return{ scope:true, template:'<a class="btn" ng-class="{active: on}" ng-click="toggle()">Toggle me!</a>', link:function( scope, element, attrs ) { scope.on =false; scope.toggle =function() { scope.on = !$scope.on; }; } }; });
再次强调,模板的那些代码都是在模板里的,所以你或者你的使用者能够很方便的将其换成一个符合任何需要的样式,同时逻辑不被改变。这就是重用性-赞!
当然,还有其它很多好处–比如测试 – 这很容易! 不论什么在模板中,指令的内部API绝不会被接触,所以重构就变得容易。你可以在不接触指令的情况下随意改变你的模板。并且不论你怎么变,你的测试仍可以通过。
耶!
所以如果指令不只是一组jQuery风格的函数,那么它们是什么呢?指令其实就是html的扩展。如果html不能完成你希望它做的一些事情,你就写一个指令来做,并且当它是html的一部分来使用。
换句话说, 如果Angular.js一下子无法完成手头的工作,想想看你的团队是否能用ngClick、ngClass等来搞定它。
以上内容主要是关于会jQuery,该如何用AngularJS编程思想,希望对大家有帮助。
相关推荐:
위 내용은 AngularJS 프로그래밍 아이디어를 사용하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!