Нужно ли моей 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 зависят от этого свойства, ошибки будут происходить, потому что ни один из них не будет знать, что делает другой.