상대적으로 말하면 Jquery는 DOM 작업에 중점을 두고 있는 반면 AngularJS는 뷰 모델과 양방향 바인딩에 중점을 두고 있습니다.
DOM 작업 문제
요소 노드 추가, 요소 노드 제거, 요소 콘텐츠 가져오기, 요소 숨기기 또는 표시 등 DOM 작업에 jQuery를 사용하지 마세요. 이러한 작업을 구현하려면 지시문을 사용해야 하며, 필요한 경우 직접 지시문을 작성해야 합니다.
웹 사이트 웹 프런트엔드 개발 시 습관을 바꾸는 것이 어렵다면 웹 페이지에서 jQuery를 제거하는 것을 고려해 보세요. 실제로 AngularJS의 $http 서비스는 매우 강력하며 기본적으로 jQuery의 ajax 기능을 대체할 수 있으며 AngularJS에는 jQLite가 포함되어 있습니다. 일반적으로 사용되는 jQuery DOM 작업 방법, 이벤트 바인딩 등을 포함하여 내부적으로 구현된 jQuery의 하위 집합입니다. . 하지만 이것이 AngularJS를 사용할 때 jQuery를 사용할 수 없다는 의미는 아닙니다. 웹 페이지에 jQuery가 로드된 경우 AngularJS는 jQuery를 먼저 사용하고, 그렇지 않으면 jQLite로 대체됩니다.
모바일 앱이나 모바일 웹 개발이라면 Jquery를 도입하지 않는 것이 좋습니다. Jquery의 일부 기능이 꼭 필요한 경우에는 Zepto.js를 도입하세요. 하지만 저를 믿으세요. AngularJS를 사용하면 Jquery가 필요하지 않습니다!
자신만의 지시문을 작성해야 하는 상황은 일반적으로 타사 jQuery 플러그인을 사용할 때입니다. 플러그인은 AngularJS 외부에서 폼 값을 변경하기 때문에 즉시 모델에 반영할 수 없습니다. 예를 들어, 우리는 jQueryUI datepicker 플러그인을 많이 사용합니다. 날짜를 선택하면 플러그인이 입력 입력 상자에 날짜 문자열을 채웁니다. View는 변경되지만 Model은 업데이트되지 않습니다. $('.datepicker').datepicker(); 이 코드는 AngularJS의 관리 범위에 속하지 않기 때문입니다. DOM 변경 사항을 모델에 즉시 업데이트하는 지시문을 작성해야 합니다.
var directives = angular.module('directives', []); directives.directive('datepicker', function() { return function(scope, element, attrs) { element.datepicker({ inline: true, dateFormat: 'dd.mm.yy', onSelect: function(dateText) { var modelPath = $(this).attr('ng-model'); putObject(modelPath, scope, dateText); scope.$apply(); } }); } });
그렇다면 이 지시문을 HTML에 소개합니다
<input type="text" datepicker ng-model="myObject.myDateValue" />
지시어는 HTML에 사용자 정의 태그 속성을 작성하여 플러그인 기능을 구현하고 HTML 기능을 효과적으로 보완하는 것입니다. 이 선언적 구문은 HTML을 확장합니다. 사용과 코드 유지 관리를 용이하게 하기 위해 프로젝트의 공통 기능과 페이지 구성 요소를 지시어로 캡슐화하는 것이 좋습니다.
Bootstrap 프레임워크의 플러그인과 jQuery를 기반으로 하는 기타 널리 사용되는 UI 구성 요소를 포함하여 우리가 사용할 수 있는 많은 지시문을 제공하는 AngularUI 프로젝트가 있다는 점에 유의해야 합니다. 이제 AngularJS 커뮤니티가 활성화되고 생태계가 탄탄해졌습니다.
ngOption의 값
은 큰 함정입니다. ngOption에 의해 생성된 221f08282418e2996498697df914ce4e의 5a07473c87748fb1bf73f23d45547ab8 옵션 값(각 f27989812beae9f6405808e298a46122의 값 부분)을 보면 확실히 헛된 것입니다. 여기에 있는 값은 항상 사용자가 지정하는 양식 옵션 값이 아닌 AngularJS 내부 요소의 인덱스가 되기 때문입니다.
여전히 개념을 변경할 필요가 있습니다. AngularJS는 더 이상 데이터 상호 작용에 양식을 사용하지 않고 모델을 사용합니다. $http를 사용하여 모델을 제출하고, PHP에서는 file_get_contents('php://input')를 사용하여 프런트 엔드에서 제출한 데이터를 얻습니다.
입력 유형='숫자' 문제
일부 AngularJS 버전에서는 입력 상자가 입력 유형='숫자'로 설정되면 모바일 장치에서 ng-change 메서드가 실패합니다. .
{{ }} 문제
페이지가 초기화되면 사용자에게 {{ }}가 표시될 수 있으며, 이후 실제 콘텐츠가 나타나기 전에 잠시 깜박입니다.
해결책:
ng-cloak 지시어를 사용하여 숨기기
{{ }} 대신 ng-bind 사용
비즈니스 로직에서 인터페이스 분리
컨트롤러는 DOM을 직접 참조해서는 안 되지만 뷰의 동작을 제어해야 합니다. 예를 들어 "사용자가 X를 조작하면 어떻게 될까요?", "어디서 구할 수 있나요?" 등은 인터페이스와 독립적이며 뷰의 논리와는 아무런 관련이 없습니다. 그 역할은 단순히 "X를 수행"하는 것입니다.
DOM 작업은 지시문 내부에 배치되어야 합니다.
기존 함수를 최대한 재사용하세요
작성한 함수는 AngularJS에서 구현되었을 가능성이 높습니다. 일부 코드는 보다 Angular 방식으로 추상화되어 재사용될 수 있습니다. 즉, jQuery의 지루한 코드 중 상당수를 대체할 수 있습니다.
1.ng-repeat
ng-repeat는 매우 유용합니다. Ajax가 서버에서 데이터를 가져온 후 우리는 종종 jQuery(예: 위에서 언급한 예)를 사용하여 일부 HTML 컨테이너 노드에 더 많은 요소를 추가하는데, 이는 AngularJS에서 나쁜 습관입니다. ng-repeat를 사용하면 모든 것이 매우 간단해집니다. $scope에 배열(모델)을 정의하여 서버에서 가져온 데이터를 저장한 다음 ng-repeat를 사용하여 이를 DOM에 바인딩합니다. 다음 예는 친구 모델을 초기화하고 정의합니다
<div ng-init="friends = [{name:'John', age:25}, {name:'Mary', age:28}]"> I have {{friends.length}} friends. They are: <ul> <li ng-repeat="friend in friends"> [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old. </li> </ul> </div>
2. ng-show
ng-show 也很有用。使用 jQuery 来根据条件控制界面元素的显示隐藏,这很常见。但是 Angular 有更好的方式来做到这一点。ng-show (以及 ng-hide) 可以根据布尔表达式来决定隐藏和显示。
对于数组或字符串,可以用strXXXX.length控制显示,否则在移动设备上会不正常。
类似的内置 directives 还有 ng-disabled, ng-switch 等等,用于条件控制,语法简洁,都很强大。
3. ng-class
ng-class 用于条件性地给元素添加 class,以前我们也经常用 jQuery 来实现。Angular 中的 ng-class 当然更好用了,例子:
1d7c26ea023fee7ffae44d3aac1b7375...16b28748ea4df4d9c2150843fecfba68
在这里 ng-class 接受一个 object 对象,key 为 CSS class 名,值为 $scope 变量控制的条件表达式,其他类似的内置 directives 还有 ng-class-even 和 ng-class-odd,很实用。
ng-show和ng-if的使用场景问题
使用ng-show和ng-if都实现控制页面元素显示的功能,但2者是不同的,ng-if会动态创建DOM,ng-show只是切换已有DOM的显示,相当于设置style="display:none",如果使用before和after等css伪类控制显示效果,可能会出现问题,需要根据情况合理使用ng-show和ng-if。
$watch 和 $apply
AngularJS 的双向数据绑定是最令人兴奋的特性了,然而它也不是全能的魔法,在某些情况下你需要做一些小小的修正。
当你使用 ng-model, ng-repeat 等等来绑定一个元素的值时, AngularJS 为那个值创建了一个 $watch,只要这个值在 AngularJS 的范围内有任何改变,所有的地方都会同步更新。而你在写自定义的 directive 时,你需要定义你自己的 $watch 来实现这种自动同步。
有时候你在代码中改变了 model 的值,view 却没有更新,这在自定义事件绑定中经常遇到。这时你就需要手动调用 scope.$apply() 来触发界面更新。上面 datepicker 的例子已经说明了这一点。第三方插件可能会有 call back,我们也可以把回调函数写成匿名函数作为参数传入$apply()中。
将 ng-repeat 和其他 directives 结合起来
ng-repeat 很有用,不过它和 DOM 绑定了,很难在同一个元素上使用其他 directives (比如 ng-show, ng-controller 等等)。
如果你想对整个循环使用某个 directive,你可以在 repeat 外再包一层父元素把 directive 写在那儿;如果你想对循环内部的每一个元素使用某个 directive,那么把它放到 ng-repeat 的一个子节点上即可。
Scope的问题
Scope 在 templates 模板中应该是 read-only 的,而在 controller 里应该是 write-only 的。Scope 的目的是引用 model,而不是成为 model。model 就是我们定义的 JavaScript 对象。
$rootScope 是可以用的,不过很可能被滥用
Scopes 在 AngularJS 中形成一定的层级关系,树状结构必然有一个根节点。通常我们用不到它,因为几乎每个 view 都有一个 controller 以及相对应的自己的 scope。
但偶尔有一些数据我们希望全局应用在整个 app 中,这时我们可以将数据注入 $rootScope。因为其他 scope 都会继承 root scope,所以那些注入的数据对于 ng-show 这类 directive 都是可用的,就像是在本地 $scope 中的变量一样。
当然,全局变量是邪恶的,你必须很小心地使用 $rootScope。特别是不要用于代码,而仅仅用于注入数据。如果你非常希望在 $rootScope 写一个函数,那最好把它写到 service 里,这样只有用到的时候它才会被注入,测试起来也方便些。
相反,如果一个函数的功能仅仅是存储和返回一些数据,就不要把它创建成一个 service。
子作用域的原型继承问题
辛酸泪,这个也是个大坑。作用域变量的继承是基于javascript原型继承机制的,在使用涉及到作用域的指令如ng-template,ion-modal等时需要特别注意,相关的查找顺序这里就不细说了。