수색…


양방향 데이터 바인딩이 작동하지 않는다

하나는 다음을 염두에 두어야합니다.

  1. Angular의 데이터 바인딩은 JavaScript의 프로토 타입 상속에 의존하므로 가변적 인 섀도 잉이 필요 합니다.
  2. 하위 범위는 일반적으로 부모 범위에서 프로토 타입 적으로 상속됩니다. 이 규칙의 한 가지 예외는 prototypically 상속하지 않으므로 격리 된 범위가있는 지시문입니다.
  3. ng-repeat , ng-switch , ng-view , ng-if , ng-controller , ng-include 등 새로운 하위 범위를 만드는 일부 지시문이 있습니다.

즉, 자식 범위 안에있는 기본 요소에 양방향 데이터를 양방향으로 바인딩하려고하면 (또는 그 반대의 경우) 예상대로 작동하지 않을 수 있습니다. 다음 은 AngularJS를 "중단" 하는 것이 얼마나 쉬운 지 보여주는 예입니다.

이 문제는 다음 단계를 따르면 쉽게 피할 수 있습니다.

  1. 가지고있다 "." 일부 데이터를 바인딩 할 때마다 HTML 템플릿 내부에서
  2. "점으로 찍힌"객체에 대한 바인딩 사용을 촉진함에 따라 controllerAs 구문을 사용하십시오.
  3. $ parent는 하위 범위가 아닌 상위 scope 변수에 액세스하는 데 사용할 수 있습니다. 우리가 ng-model="$parent.foo" 사용할 수 ng-if inside처럼.

위의 대안은 ngModel 을 인수로 호출 할 때 모델의 캐시 된 버전을 업데이트하거나 인수없이 호출하면 반환하는 getter / setter 함수에 바인딩하는 것입니다. getter / setter 함수를 사용하려면 ngModal 특성이있는 요소에 ng-model-options="{ getterSetter: true }" 를 추가하고 해당 값을 expression에 표시하려면 getter 함수를 호출해야합니다 ( 실례 ).

전망:

<div ng-app="myApp" ng-controller="MainCtrl">
    <input type="text" ng-model="foo" ng-model-options="{ getterSetter: true }">
    <div ng-if="truthyValue">
        <!-- I'm a child scope (inside ng-if), but i'm synced with changes from the outside scope -->
        <input type="text" ng-model="foo">
    </div>
    <div>$scope.foo: {{ foo() }}</div>
</div>

제어 장치:

angular.module('myApp', []).controller('MainCtrl', ['$scope', function($scope) {
    $scope.truthyValue = true;
      
    var _foo = 'hello'; // this will be used to cache/represent the value of the 'foo' model 
      
    $scope.foo = function(val) {
        // the function return the the internal '_foo' varibale when called with zero arguments,
        // and update the internal `_foo` when called with an argument
        return arguments.length ? (_foo = val) : _foo;
    };
}]);

모범 사례 : getter는 코드의 다른 부분 ( 참조 )보다 자주 호출하기 때문에 getter를 빠르게 유지하는 것이 가장 좋습니다.

html5Mode를 사용할 때 할 일

html5Mode([mode]) 때 다음이 필요합니다.

  1. index.html 의 머리 부분에 <base href=""> 를 사용하여 응용 프로그램의 기본 URL을 지정합니다.

  2. base 태그가 url 요청을 가진 태그 앞에 오는 것이 중요합니다. 그렇지 않으면 "Resource interpreted as stylesheet but transferred with MIME type text/html" 오류가 발생할 수 있습니다. 예 :

    <head>
        <meta charset="utf-8">
        <title>Job Seeker</title>
    
        <base href="/">
    
        <link rel="stylesheet" href="bower_components/bootstrap/dist/css/bootstrap.css" />
        <link rel="stylesheet" href="/styles/main.css">
    </head>
    
  3. 당신이 지정하는 희망을 설정하지 않으면 base , 태그를 구성 $locationProvider 필요하지 않도록 base 으로 정의 객체를 전달하여 태그를 requireBase:false$locationProvider.html5Mode() 과 같은 :

    $locationProvider.html5Mode({
        enabled: true,
        requireBase: false
    });
    
  4. HTML5 URL의 직접로드를 지원하려면 서버 측 URL 다시 쓰기를 활성화해야합니다. AngularJS / Developer Guide / Using $ location을 참조하십시오.

    이 모드를 사용하려면 서버 측에서 URL 재 작성이 필요합니다. 기본적으로 응용 프로그램의 진입 점 (예 : index.html )에 대한 모든 링크를 다시 작성해야합니다. <base> 태그를 요구하는 것은이 경우에도 중요합니다. Angular가 응용 프로그램 기본 URL 인 부분과 응용 프로그램에서 처리해야하는 경로를 구별 할 수 있기 때문입니다.

    다양한 HTTP 서버 구현에 대한 요청 재 작성 예제에 대한 훌륭한 참고 자료는 ui-router FAQ - How to : html5Mode와 작동하도록 서버를 구성하는 방법을 참조하십시오 . 예를 들어, Apache

     RewriteEngine on
    
     # Don't rewrite files or directories
     RewriteCond %{REQUEST_FILENAME} -f [OR]
     RewriteCond %{REQUEST_FILENAME} -d
     RewriteRule ^ - [L]
    
     # Rewrite everything else to index.html to allow html5 state links
     RewriteRule ^ index.html [L]
    

    nginx

     server {
         server_name my-app;
    
         root /path/to/app;
    
         location / {
             try_files $uri $uri/ /index.html;
         }
     }
    

    표하다

     var express = require('express');
     var app = express();
    
     app.use('/js', express.static(__dirname + '/js'));
     app.use('/dist', express.static(__dirname + '/../dist'));
     app.use('/css', express.static(__dirname + '/css'));
     app.use('/partials', express.static(__dirname + '/partials'));
    
     app.all('/*', function(req, res, next) {
         // Just send the index.html for other files to support HTML5Mode
         res.sendFile('index.html', { root: __dirname });
     });
    
     app.listen(3006); //the port you want to use
    

Angular의 치명적인 죄 7

다음은 AngularJS 기능을 사용할 때 개발자가 자주 범하는 실수 목록, 일부 학습 된 교훈 및 해결 방법입니다.

1. 컨트롤러를 통한 DOM 조작

그것은 합법적이지만 반드시 피해야합니다. 컨트롤러는 의존성을 정의하고 데이터를 뷰에 바인딩하고 추가 비즈니스 로직을 만드는 곳입니다. 기술적으로 컨트롤러에서 DOM을 조작 할 수 있지만, 앱의 다른 부분에서 동일하거나 유사한 조작이 필요할 때마다 다른 컨트롤러가 필요할 것입니다. 따라서이 방법의 가장 좋은 방법은 모든 조작을 포함하는 지시문을 작성하고 앱 전체에서 지시문을 사용하는 것입니다. 따라서 컨트롤러는보기를 그대로두고 작업을 수행합니다. 지시문에서 연결 함수는 DOM을 조작하는 가장 좋은 장소입니다. 범위와 요소에 대한 완전한 액세스 권한을 가지므로 지시문을 사용하면 재사용 가능성을 활용할 수도 있습니다.

link: function($scope, element, attrs) {
    //The best place to manipulate DOM
}

element 매개 변수, angular.element() 메소드 또는 pure Javascript와 같은 여러 가지 방법을 통해 링크 함수에서 DOM 요소에 액세스 할 수 있습니다.

2. 결합에서의 데이터 바인딩

AngularJS는 양방향 데이터 바인딩으로 유명합니다. 그러나 데이터가 지시문 내에서 단방향으로 바인딩되는 경우가 있습니다. 그만, AngularJS는 잘못 아니었지만 아마도 당신. 지시문은 자식 범위와 격리 된 범위가 관련되어 있기 때문에 약간 위험합니다. 다음과 같은 지시어가 있다고 가정 해보십시오.

<my-dir>
    <my-transclusion>
    </my-transclusion>
</my-dir>

그리고 my-transclusion 내부에는 외부 범위의 데이터에 바인딩되는 요소가 있습니다.

<my-dir>
    <my-transclusion>
        <input ng-model="name">
    </my-transclusion>
</my-dir>

위의 코드는 올바르게 작동하지 않습니다. 여기에서 transclusion은 하위 범위를 만들고 이름 변수를 얻을 수 있지만이 변수에 대한 모든 변경 사항은 그대로 유지됩니다. 따라서이 변수에 $ parent.name 으로 실제로 액세스 할 수 있습니다. 그러나이 사용은 모범 사례가 아닐 수도 있습니다. 더 나은 접근 방법은 객체 내부에 변수를 래핑하는 것입니다. 예를 들어 컨트롤러에서 다음을 만들 수 있습니다.

$scope.data = {
    name: 'someName'
}

그리고 나서, '데이터'개체를 통해이 변수에 액세스하여 양방향 바인딩이 완벽하게 작동하는지 확인할 수 있습니다.

<input ng-model="data.name">

결론적으로뿐만 아니라 앱 전체에서 점으로 구분 된 표기법을 사용하는 것이 좋습니다.

3. 여러 지시어 함께

두 요소가 같은 요소에 존재할 수는 없습니다. 규칙을 준수하는 한 동일한 요소 내에서 두 개의 지시문을 함께 사용하는 것이 실제로 가능합니다. 일반적으로 새 사용자 지정 지정 문을 만들 때 매개 변수 전달을 쉽게하기 위해 격리 된 범위를 할당합니다. myDirA 및 myDirB 지시문이 isoleted 범위를 갖고 myDirC 지시문이없는 것으로 가정하면 다음 요소가 유효합니다.

<input my-dir-a my-dirc>

다음 요소는 콘솔 오류를 유발합니다.

<input my-dir-a my-dir-b>

따라서 지시문은 범위를 고려하여 현명하게 사용해야합니다.

4. $ em의 오용

$ emit, $ broadcast 및 $ on은 송수신기 원리로 작동합니다. 다른 말로 표현하자면, 그들은 컨트롤러 간의 통신 수단입니다. 예를 들어, 다음 행은 컨트롤러 A에서 'someEvent'를 내보내 관련 컨트롤러 B가 catch합니다.

$scope.$emit('someEvent', args);

그리고 다음 줄은 'someEvent'

$scope.$on('someEvent', function(){});

지금까지 모든 것이 완벽 해 보입니다. 그러나 제어기 B가 아직 호출되지 않으면 이벤트가 잡히지 않을 것임을 기억하십시오. 즉, 송신기 및 수신기 제어기를 호출하여이 작업을 수행해야 함을 의미합니다. 다시 말해, $ emit을 사용해야한다는 확신이 없다면 서비스를 만드는 것이 더 좋은 방법 인 것 같습니다.

5. $ scope의 오용. $ watch

$ scope. $ watch는 변수 변경을 감시하는 데 사용됩니다. 변수가 변경 될 때마다이 메소드가 호출됩니다. 그러나 한 가지 일반적인 실수는 $ scope 내부의 변수를 변경하는 것입니다. 이것은 어떤 점에서 불일치와 무한한 $ digest loop를 일으킬 것입니다.

$scope.$watch('myCtrl.myVariable', function(newVal) {
    this.myVariable++;
});

따라서 위 함수에서 myVariable 및 newVal에 대한 연산이 없는지 확인하십시오.

6. 뷰에 메소드 바인딩하기

이것은 가장 치명적인 죄들 중 하나입니다. AngularJS에는 양방향 바인딩이 있으며, 무언가가 변경 될 때마다 뷰가 여러 번 업데이트됩니다. 따라서 뷰의 속성에 메소드를 바인드하면 해당 메소드가 백 번 호출 될 수 있으므로 디버깅하는 동안 문제가 발생할 수 있습니다. 그러나 ng-click, ng-blur, ng-on-change 등 메서드 바인딩을 위해 작성된 일부 속성 만 있으면 해당 메서드가 paremeter로 간주됩니다. 예를 들어, 마크 업에 다음보기가 있다고 가정합니다.

<input ng-disabled="myCtrl.isDisabled()" ng-model="myCtrl.name">

여기에서는 isDisabled 메소드를 통해 뷰의 사용 불가능 상태를 점검합니다. 컨트롤러 myCtrl에는 다음과 같은 기능이 있습니다.

vm.isDisabled = function(){
    if(someCondition)
        return true;
    else
        return false;
}

이론적으로는 정확하지만 기술적으로 볼 때이 메서드는 무수히 실행되므로 과부하가 발생할 수 있습니다. 이 문제를 해결하려면 변수를 바인딩해야합니다. 컨트롤러에서 다음 변수가 있어야합니다.

vm.isDisabled

컨트롤러 활성화시이 변수를 다시 시작할 수 있습니다

if(someCondition)
    vm.isDisabled = true
else
    vm.isDisabled = false

조건이 안정적이지 않으면이 이벤트를 다른 이벤트에 바인딩 할 수 있습니다. 그런 다음이 변수를 뷰에 바인딩해야합니다.

<input ng-disabled="myCtrl.isDisabled" ng-model="myCtrl.name">

이제 뷰의 모든 속성은 기대 한 바를 가지며 필요한 경우에만 메소드가 실행됩니다.

7. Angular의 기능을 사용하지 않음

AngularJS는 코드 기능을 단순화 할뿐 아니라 코드를 더욱 효율적으로 만들어주는 기능을 제공합니다. 이러한 기능 중 일부는 다음과 같습니다.

  1. angular.for 루프에 대해 (주의, 당신은 "깨뜨릴 수 없다", 그것은 몸에만 들어가기를 막을 수 있으므로 여기서 성능을 고려하십시오.)
  2. DOM 셀렉터의 angular.element
  3. angular.copy : 주 개체를 수정하지 않을 때 사용하십시오
  4. 양식 유효성 검사 는 이미 훌륭합니다. 깨끗하고, 깨끗하고, 만졌고, 타당하고, 필요한 것을 사용하십시오.
  5. Chrome 디버거 외에도 모바일 개발을 위해 원격 디버깅 을 사용하십시오.
  6. 그리고 Batarang 을 사용했는지 확인하십시오. 범위를 쉽게 조사 할 수있는 무료 Chrome 확장 프로그램입니다.
  7. .


Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow