Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
angular.module('app', ['ngResource'])
.factory 'APISession', ($resource) ->
"$resource:nomunge"
$resource "/session.json"
angular.module('app', ['ngResource'])
.factory('APISession', ['$resource', ($resource) ->
$resource "/session.json"
])
window.TranslationsEditCtrl = ['$scope', 'APITranslation']
window.TranslationsEditCtrl.push (self, APITranslation) ->
# Controller code here
module.controller('TranslationEditCtrl', ['$scope', function ($scope) {
Data-binding не так уж и ресурсоемок
Другое дело куча отдельных watcher-ов на каждый {{..}} внутри ng-repeat
Только ng-repeat свой делать все же, наверное, не стоит, лучше какую-нибудь директиву
Именно в них дело
ng-repeat — это и есть директива, только встроенная в фреймворк.
после пары-тройки тысяч записей в ng-repeat при взаимодейсвии с элементом списка весит страницу, потому что при каждом взаимодействии вызывается $digest, котоый заставляет проверять каждый забинденный элемент
У меня есть определенные сомнения, что в scope одновременно для каких-то задач требуется держать более такого количества элементов
scope его вообще лучше не держать, потому как память все равно забъет.Up/Down — пред/след, PageUp/PageDown — прыжок через 10 событий, End/Home — конец/начало списка. Нажал кнопку, держишь и смотришь, как меняется состояние объекта.{
_id: "51447fdee002580db060e10b",
date: 1363392000000,
sections: [
{
caption: "Foo",
address: 393220,
counters: [2, 2]
}, {
caption: "Bar",
address: 15842696,
errors: {
main: ["ERR_BADFRAME", "ERR_AB_OFF"]
dupl: ["ERR_BADFRAME", "ERR_AB_OFF"]
}
}, {
caption: "Baz",
address: 245,
warnings: {
dupl: ["DEV_SHIELD_A"]
}
}
],
srvtimestamp: 1363443678891,
trmbias: -18000000,
trmtimestamp: 1363447489556,
witherror: true,
withwarning: true
}
scope было удобно, но когда начались тормоза, пришлось переносить его в сервис, а ngRepet заменять кастомной директивой, потому что он работать умеет только с тем, что лежит в scope.И не нужно мне сейчас говорить, что если на странице больше 1000 элементов, то это плохой UX, знаю, слышал, но не раз видел обратное.
Angular же после третьей тысячи событий начинал тормозить, потому что весь массив событий лежал в scope. Держать его в scope было удобно, но когда начались тормоза, пришлось переносить его в сервис
Ну вот видите, вы просто не умели его готовить.
а ngRepet заменять кастомной директивой, потому что он работать умеет только с тем, что лежит в scope.
.directive('bindStatic', function(){
return function(scope, elem, attrs) {
elem.text(scope.$eval(attrs.bindStatic));
}
});
Вот абстрагируйтесь от Angular и поясните, почему в объекте, которую контролирует модель, вместо всех 5000 событий должно лежать только 50 текщих отображаемых?
И, скорее всего, то же самое на backbone решилось бы без всяких вопросов: «А где храненить 5000 событий?».
Потому что scope — это не модель. Об этом заявляется, например, вот здесь в документации, и подробно подчеркивается в официальном видео Best Practices. Постарайтесь вникнуть в эту мысль, она все объясняет. В модели могут жить 50 тысяч, 100 тысяч объектов любой сложности, и ограничивает это только память. А scope — это некоторая транзитная сущность для связки модели и отображения, можем называть ее моделью отображения (View-Model). Модель отображения не должна хранить ничего, что не требуется отображать.
In Angular, a model is any data that is reachable as a property of an angular Scope object. The name of the property is the model identifier and the value is any JavaScript object (including arrays and primitives).
The only requirement for a JavaScript object to be a model in Angular is that the object must be referenced by an Angular scope as a property of that scope object.
Treat scope is read-only in templates & write-only in controllers
— The purpose of the scope is to refer to the model not to be a model
— The model is your JavaScript objects
Scope has references to the model. So you create your own model object, manually put the reference to the model object to the scope. In view you say «model dot whatever property in a model you want to access». Similary if you have a form, you should have a model «form» and in a scope basically say «model dot property X» and view is updating property in a model, not a propery of a scope.
$scope.firstName = "Bob";
$scope.lastName = "Dylan";
$scope.age = 71;
$scope.form = {
firstName: "Bob",
lastName: "Dylan",
age: 71
}
Этот слайд он сопровождает примерно следующими словами:
И если я хочу отобразить список из 5 000 элементов, я кладу в Scope массив из 5 000 элементов. Это моя модель для отображения.
Из этого монолога я опять делаю вывод, что любая единичная сущность в Scope — это модель.
Вы так говорите, как будто на значения в сервисах нельзя повесить watch.Ну, я бы это и сказал, на самом деле. Никакого собственного scope у сервисов нет, а задействовать $rootScope в этих целях — кощунство.
You can't really show more than about 2000 pieces of information to a human on a single page. Anything more than that is really bad UI, and humans can't process this anyway.
So the real question is this: can you do 2000 comparisons in 50 ms even on slow browsers?
if (isChecked) {
specialParagraph.show();
} else {
specialParagraph.hide();
}
specialParagraph.toggle(isChecked)
$(function() {
$('#toggleShowHide).change(function() {
var isChecked = $('#toggleShowHide).is(':checked');
$('#specialParagraph').toggle(isChecked);
});
});
<div ng-app ng-controller="SearchCtrl">
<form action="/search" ng-submit="ajaxSubmit($event)">
<input type="text" ng-model="query" name="query">
<input type="submit">
</form>
</div>
module.controller('SearchCtrl', ['$scope', function ($scope) {
$scope.ajaxSubmit = function($event) {
//$event === undefined
}
}]);
Это реально работающая схема в полном согласии с принципами MVC, обеспечивающая очень чистое разделение между представлением, контроллером и моделью.
And for this reason, I hereby declare AngularJS to be MVW framework — Model-View-Whatever. Where Whatever stands for «whatever works for you».
$("input.toggle").change(function(){
$("div.toggle").toggle();
}); User agents must treat elements and attributes that they do not understand as semantically neutral; leaving them in the DOM (for DOM processors), and styling them according to CSS (for CSS processors), but not inferring any meaning from them.
«непонятно что но понятно как» это здорово конечно :) как вы можете понять «как» если не можете понять «что»?
button x-signal="click: sendMail"; //...
slots: {
sendMail: function() { },
// ...
}
избавились от «безликих» событий
x-signal="click: sendMail".контроллер может ничего не знать о разметке/классах
сигнал, как и событие может передаваться по дереву контроллеров
из view может ещё N-колличество элементов посылать этот сигнал
по необходимости, мы можем сделать слот или сигнал не активным
return;.on(..), а все слоты мы складываем в объекте «slots» нашего контроллера. И еще один плюс в декларативном биндинге, что в контроллере мы явно разделаем «методы контроллера»/«слоты».this.slots('sendMail').disable() — a) слот мы не сможем вызвать (пока не .enable(...) ), и б) если слотов больше нет у сигнала в данном или выше по дереву контроллере, то соответствующей кнопке/пункту меню присвоится :disabled. И не надо создавать лишних биндингов к кнопке.$(function() {
function toggle() {
var isChecked = $('#toggleShowHide).is(':checked');
var specialParagraph = $('#specialParagraph');
if (isChecked) {
specialParagraph.show();
} else {
specialParagraph.hide();
}
}
$('#toggleShowHide).change(function() {
toggle();
});
toggle();
});
$('#checkBox').change(function() {
$('#content').toggle(300);
});


возьми этот элемент и его атрибут, посмотри на его значение, сделай так-то и так-то.
Все тоже самое делает под капотом Ангулар.Разумеется. Так же, как например браузер под капотом выполняет императивные инструкции по рендерингу страницы, что не лишает нас удобной возможности определять ее внешний вид в декларативном HTML, оставляя его парсинг заботам браузера.
$(function() {
function toggle() {
var isChecked = $('#toggleShowHide).is(':checked');
var specialParagraph = $('#specialParagraph');
if (isChecked) {
specialParagraph.show();
} else {
specialParagraph.hide();
}
}
$('#toggleShowHide).change(function() {
toggle();
});
toggle();
});
$('#toggleShowHide').on('click', function() {
$('#specialParagraph').toggle(this.checked);
});
AngularJS для привыкших к jQuery