Нужно ли моей ng-модели иметь точную точку, чтобы избежать проблем с областью?

В соответствии с https://github.com/angular/angular.js/wiki/Understanding-Scopes проблема заключается в попытке привязки данных к примитивам, прикрепленным к вашему $scope:

Наследование областей обычно является простым, и вам часто даже не нужно знать, что это происходит... пока вы не попробуете привязку двухсторонней привязки (т.е. элементы формы, ng-model) к примитиву (например, число, string, boolean), определенный в родительской области изнутри области содержимого. Это не работает так, как многие люди ожидают, что он должен работать.

Рекомендация

Эту проблему с примитивами можно легко избежать, следуя "лучшей практике" всегда иметь ".". в ваших ng-моделях


Теперь у меня есть эта очень простая настройка, которая нарушает эти правила:

HTML:

<input type="text" ng-model="theText" />
<button ng-disabled="shouldDisable()">Button</button>

JS:

function MyController($scope) {
    $scope.theText = "";
    $scope.shouldDisable = function () {
         return $scope.theText.length >= 2;
    };
}

Это действительно плохо? Это будет запутать меня каким-то ужасным способом, когда я начну пытаться использовать дочерние области? Как-то?


Мне нужно изменить его на что-то вроде

function MyController($scope) {
    $scope.theText = { value: "" };
    $scope.shouldDisable = function () {
         return $scope.theText.value.length >= 2;
    };
}

и

<input type="text" ng-model="theText.value" />
<button ng-disabled="shouldDisable()">Button</button>

чтобы я следовал лучшей практике? Какой конкретный пример вы можете дать мне, где последний спасет меня от какого-то ужасного последствия, которое будет присутствовать в первом?

Ответ 1

Многое представляет новые области применения. Скажем, что в ваших контроллерах вы действительно хотите добавить вкладки: первая вкладка представляет собой фактический рендеринг, вторая вкладка - это форма (так, чтобы у вас был просмотр в реальном времени).

Вы решили использовать для этого директиву:

<tabs>
  <tab name="view">
    <pre>{{theText|formatInSomeWay}}</pre>
  </tab>
  <tab name="edit" focus="true">
    <input type="text" ng-model="theText" />
  </tab>
</tabs>

Ну, знаешь что? <tabs> имеет свой собственный объем и сломал ваш контроллер один! Поэтому, когда вы редактируете, angular сделает что-то подобное в js:

$scope.theText = element.val();

который не будет пересекать цепочку прототипов, чтобы попытаться установить theText на родителей.

EDIT: просто чтобы быть ясным, я использую только "вкладки". Когда я говорю: "Многие вещи вводят новую область действия", я имею в виду это: ng-include, ng-view, ng-switch, ng-controller (конечно) и т.д.

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

Ответ 2

Скажем, у вас есть области M, A и B, где M - родительский элемент как A, так и B.

Если один из (A, B) пытается записать в область M, он будет работать только с не-примитивными типами. Причина этого в том, что не-примитивные типы передаются по ссылке.

Примитивные типы, с другой стороны, не являются, поэтому попытка написать в theText в области M создаст новое свойство с тем же именем в области A или B, соответственно, вместо записи на M. Если оба A и B зависят от этого свойства, ошибки будут происходить, потому что ни один из них не будет знать, что делает другой.