Поиск…


Двухсторонняя привязка данных перестает работать

Следует иметь в виду, что:

  1. Угловое связывание данных основывается на прототипном наследовании JavaScript, поэтому оно подвержено переменному затенению .
  2. Дочерняя область, обычно прототипически наследуемая от своей родительской области. Единственное исключение из этого правила - это директива, которая имеет изолированную область действия, поскольку она не прототипически наследуется.
  3. Существуют некоторые директивы, которые создают новую дочернюю область: ng-repeat , ng-switch , ng-view , ng-if , ng-controller , ng-include и т. Д.

Это означает, что когда вы пытаетесь выполнить двустороннюю привязку некоторых данных к примитиву, находящемуся внутри детской области (или наоборот), все может работать не так, как ожидалось. Вот пример того, как легко «сломать» AngularJS.

Эту проблему можно легко избежать, выполнив следующие шаги:

  1. Имейте "." внутри вашего HTML-шаблона всякий раз, когда вы связываете некоторые данные
  2. Используйте синтаксис controllerAs поскольку он способствует использованию привязки к «пунктируемому» объекту
  3. $ parent может использоваться для доступа к переменным родительской scope а не к области содержимого. как внутри ng-if мы можем использовать ng-model="$parent.foo" ..

Альтернативой для этого является привязка ngModel к функции getter / setter, которая будет обновлять кэшированную версию модели при вызове с аргументами или возвращать ее при вызове без аргументов. Чтобы использовать функцию getter / setter, вам нужно добавить ng-model-options="{ getterSetter: true }" к элементу с атрибутом ngModal и вызвать функцию 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;
    };
}]);

Лучшая практика . Лучше всего держать геттеры быстрыми, потому что Угловые, скорее всего, назовут их чаще, чем другие части вашего кода ( ссылка ).

Что делать при использовании html5Mode

При использовании html5Mode([mode]) необходимо:

  1. Вы указываете базовый URL-адрес приложения с <base href=""> в index.html вашего index.html .

  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. Чтобы поддерживать прямую загрузку URL-адресов HTML5, вам необходимо активировать переписывание URL-адресов на стороне сервера. From AngularJS / Руководство разработчика / Использование $ location

    Использование этого режима требует перезаписи URL-адресов на стороне сервера, в основном вы должны переписать все свои ссылки на точку входа вашего приложения (например, index.html ). Требование <base> также важно для этого случая, так как позволяет Angular различать часть URL-адреса, которая является базой приложения, и путь, который должен обрабатывать приложение.

    Отличный ресурс для запросов перезаписи запросов для различных реализаций HTTP-сервера можно найти в FAQ по ui-router - Как настроить сервер для работы с html5Mode . Например, сходница

     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
    

7 Смертельные грехи AngularJS

Ниже приведен список ошибок, которые разработчики часто делают во время использования функций AngularJS, некоторые извлеченные уроки и решения для них.

1. Манипуляция DOM через контроллер

Это законно, но его следует избегать. Контроллеры - это места, где вы определяете свои зависимости, связываете свои данные с представлением и делаете дальнейшую бизнес-логику. Вы можете технически манипулировать DOM в контроллере, но всякий раз, когда вам нужна такая же или аналогичная манипуляция в другой части вашего приложения, вам понадобится другой контроллер. Поэтому лучшей практикой такого подхода является создание директивы, включающей все манипуляции и использование директивы во всем приложении. Следовательно, контроллер оставляет представление неповрежденным и делает его работу. В директиве функция связывания - лучшее место для манипулирования DOM. Он имеет полный доступ к области и элементу, поэтому, используя директиву, вы также можете воспользоваться преимуществами повторного использования.

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

Вы можете получить доступ к элементам DOM при связывании функции несколькими способами, такими как параметр element , angular.element() или чистый Javascript.

2. Связывание данных при переходе

AngularJS славится своей двусторонней привязкой данных. Однако иногда вы можете столкнуться с тем, что ваши данные только односторонне связаны внутри директив. Остановитесь там, AngularJS не ошибается, но, вероятно, вы. Директивы - это немного опасные места, так как задействованы дочерние области и изолированные области. Предположим, что у вас есть следующая директива с одним заключением

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

И внутри моего переключения у вас есть некоторые элементы, привязанные к данным во внешней области.

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

Вышеприведенный код не будет работать правильно. Здесь переключение создает дочернюю область, и вы можете получить переменную имени, но все изменения, внесенные вами в эту переменную, останутся там. Таким образом, вы можете действительно использовать эту переменную как $ parent.name . Однако это использование может быть не лучшей практикой. Лучшим подходом было бы обертывание переменных внутри объекта. Например, в контроллере вы можете создать:

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

Затем в выводе вы можете получить доступ к этой переменной через объект «data» и увидеть, что двусторонняя привязка работает отлично!

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

Не только в переходах, но и во всем приложении, рекомендуется использовать пунктирную нотацию.

3. Несколько директив вместе

Фактически законно использовать две директивы вместе внутри одного и того же элемента, если вы подчиняетесь правилу: две изолированные области не могут существовать на одном элементе. Вообще говоря, при создании новой настраиваемой директивы вы выделяете изолированную область для простой передачи параметров. Предполагая, что в директивах myDirA и myDirB есть выделенные области и myDirC нет, следующий элемент будет действителен:

<input my-dir-a my-dirc>

тогда как следующий элемент вызовет ошибку консоли:

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

Поэтому директивы должны использоваться разумно, принимая во внимание области.

4. Неправильное использование $ emit

$ emit, $ broadcast и $ on, они работают в принципе отправителя-получателя. Другими словами, они являются средством связи между контроллерами. Например, следующая строка испускает «someEvent» из контроллера A, который должен быть захвачен соответствующим контроллером B.

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

И следующая строка ловит 'someEvent'

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

Пока все кажется идеальным. Но помните, что если контроллер B еще не вызывается, событие не будет выловлено, что означает, что для его работы должны быть задействованы как контроллеры-эмиттеры, так и приемники. Итак, опять же, если вы не уверены, что вам определенно нужно использовать $ emit, создание службы кажется лучшим способом.

5. Неправильное использование $ scope. $ Watch

$ scope. $ watch используется для просмотра изменения переменной. Всякий раз, когда переменная изменена, этот метод вызывается. Однако одна распространенная ошибка заключается в изменении переменной внутри $ scope. $ Watch. Это вызовет непоследовательность и бесконечный цикл $ digest в какой-то момент.

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

Поэтому в приведенной выше функции убедитесь, что у вас нет операций с myVariable и newVal.

6. Методы привязки к представлениям

Это один из самых тяжких грехов. У AngularJS есть двусторонняя привязка, и всякий раз, когда что-то меняется, представления обновляются много раз. Таким образом, если вы привязываете метод к атрибуту представления, этот метод потенциально может называться сто раз, что также приводит вас в замешательство во время отладки. Однако для привязки метода существуют только некоторые атрибуты, такие как ng-click, ng-blur, ng-on-change и т. Д., Которые ожидают, что методы будут использоваться как пареметр. Например, предположим, что в вашей разметке есть следующее представление:

<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. Не использовать функции Углового

AngularJS обеспечивает большое удобство с некоторыми его функциями, не только упрощает ваш код, но и делает его более эффективным. Некоторые из этих функций перечислены ниже:

  1. angular.forEach для петель (осторожно, вы не можете «сломать», это может предотвратить только попадание в тело, поэтому рассмотрите производительность здесь.)
  2. угловой.элемент для DOM-селекторов
  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