55+1 прием для улучшения javascript-кода / Татьяна Бабич...

Post on 14-Apr-2017

261 Views

Category:

Engineering

3 Downloads

Preview:

Click to see full reader

TRANSCRIPT

55+1 приемдля улучшения JavaScript-кодаБабич ТатьянаРуководитель Frontend отдела компании SimbirSoft

На старт! Внимание! Марш! Проект будет больше, чем предполагается

Состав команды может поменяться

Время реализации сильно ограничено

Соблюдайте LIFT - принципы 1

locate

identify

flat

try to stay DRY

LIFT

-

-

-

-

Соблюдайте LIFT - принципы.

Соблюдайте LIFT - принципы.

Спустя парумесяцев

controllers/LoginController.jsRegistrationController.jsProfileController.jsSearchResultsController.jsFeedController.js

directives.jsfilters.jsmodels/

Feed.jsCartModel.jsProfileModel.jsSearchResultsModel.jsUserModel.js

services/FeedService.jsCartService.jsUserService.jsProfileService.js

Соблюдайте LIFT - принципы.

Спустя полгодаcontrollers/

LoginController.jsRegistrationController.jsProductDetailController.jsSearchResultsController.jsUsersController.jsUsersProfileController.jsOpinionController.jsInstrumentsController.jsFeedController.jsRecoveryController.jsNavigationContoller.js

directives.jsfilters.js

models/CartModel.jsProductModel.jsSearchResultsModel.jsUserModel.jsNavigation.jsRecovery.jsFeed.jsInstruments.jsOpinion.jsUsers.jsUsersProfile.js

services/...

Модульность

Модульностьproduct/

search/ SearchResultsController.js SearchResultsModel.js

ProductDetailController.jsProductModel.jsProductService.js

user/LoginController.jsRegistrationController.jsRecoveryController.jsUserModel.jsUserService.js

instruments/ InstrumentsController.jsInstrumentsModel.jsInstrumentsService.js

feed/FeedController.js FeedModel.jsFeedService.js

Принцип единой ответственности

Модульность

2

/* directives.js */

angular .module('app.project')

.directive('orderCalendarRange', orderCalendarRange)

.directive('salesCustomerInfo', salesCustomerInfo)

.directive('sharedSpinner', sharedSpinner);

function orderCalendarRange() { /* implementation details */}

function salesCustomerInfo() { /* implementation details */}

function sharedSpinner() { /* implementation details */}

/* calendarRange.directive.js */

angular .module('sales.order') .directive('acmeOrderCalendarRange', orderCalendarRange);

function orderCalendarRange() { /* implementation details */}

/* customerInfo.directive.js */ angular .module('sales.widgets') .directive('acmeSalesCustomerInfo', salesCustomerInfo);

function salesCustomerInfo() { /* implementation details */}

/* spinner.directive.js */

angular .module('shared.widgets') .directive('acmeSharedSpinner', sharedSpinner);

function sharedSpinner() { /* implementation details */}

Применяйте единый codestyle. Используйте анализаторы кода. Включите их в систему контроля версий

4

Модульность

Соблюдайте правила именования переменных3profile.controller.js ProfileController.js

Создайте константы для всех переменных от сторонних библиотек в вашем проекте

5

Модульность

Оптимизируйте ваши «велосипеды», тестируйте их, а главное документируйте

6

1 модуль = 1 задача

Модульность

приватностьслабая связность

Модульность

независимость

Создавайте много небольших независимых модулей

Создавайте ре-используемые модули9

8

Модульность

Создавайте главный модуль и не загромождайте его7

Модульность

Используйте IIFE10

;(function() { ... var app = angular.module('myApp'); ...})();

console.log(app) // not defined

Переносите логику из контроллера в фабрики и сервисы12

Контроллеры

Формируйте $scope в определенном месте11

Контроллеры

Используйте синтаксис controllerAs

Контроллеры

<div ng-controller="UserController as user"> {{ user.name }}</div>

function UserController() { this.name = {}; this.someFuncion = function() { };}

function UserController() { var vm = this; vm.name = {}; vm.sumeFunc = function() { };}

Для шаблонов Для контроллеров

или

13

function User() { angular.extend(this, {

someVar: { name: 'Name'

},anotherVar: [],doSomething: function doSomething() {

} });}

angular .module('app') .controller('User', User);

Контроллеры

Замена vm синтаксиса

Задавайте отдельный контроллер для каждого шаблона

// route-config.jsangular .module('app') .config(config);

function config($routeProvider) { $routeProvider .when('/user', { templateUrl: 'user.html', controller: 'UserController', controllerAs: 'vm' });}

<!-- user.html --><div></div>

14

Контроллеры

Используйте одноразовую привязку данных {{:: ... }}

Не используйте ng-class для установки CSS свойств, если это возможно сделать средствами только CSS

17

16

Минимизация количества $watcher - ов

Правильно используйте $rootScope15

Минимизация количества $watcher-ов

Минимизация количества $watcher - ов

Переносите манипуляции с DOM в директивы19

Не храните ссылки на DOM элементы в $scope18

Избегайте работы с большими данными21

Создавайте директивы с изолированным $scope20

Используйте track by для циклов22

Минимизация количества $watcher - ов

Переносите тяжелую логику из фильтров в контроллеры и сервисы

24

Удаляйте ненужные фильтры23

Используйте $watchCollection вместо $watch (с 3-им параметром).Избегайте установки флага objectEquality в true

$scope.$watch(…, …, true);

26

Минимизация количества $watcher - ов

Откажитесь от использования $watch там, где это возможно25

Отписывайтесь от watches и event listeners27

Минимизация количества $watcher - ов

var stopFunction = $scope.$on('someEvent', function() { ... }); // Обработчик добавленstopFunction(); // Обработчик удален

Если это возможно, сокращайте количество вызовов ng-model

ng-model-options=”{debounce: 250}”

Старайтесь избегать использования ng-mouse-over и подобных директив

29

28

Оптимизация $digest вызовов

Оптимизация $digest вызовов

Избегайте использования сокращенного синтаксиса объявления зависимостей без учета минификации кода

angular .module('app') .controller('Dashboard', Dashboard);

function Dashboard(common, dataservice) {}

30

Аннотация внедрения зависимостей

Аннотация внедрения зависимостей

angular.module('app').controller('Dashboard', d);function d(a, b) { }

Используйте $inject для задания зависимостей

angular .module('app') .controller('Dashboard', Dashboard);

Dashboard.$inject = ['$location', '$routeParams', 'common', 'dataservice'];

function Dashboard($location, $routeParams, common, dataservice) {}

Используйте ng-annotate с /** @ngInject */32

31

Аннотация внедрения зависимостей

Архитектура

Замените всплытие событий использованием Медиатора33

Архитектура

Паттерн «Фасад»скрытие деталей реализации конкретного функционала

Архитектура

Создавайте «врапперы» над вашими библиотеками 34

Переключайте CSS классы вместо перестроения DOM

Скрывайте элементы перед изменением37

36

Оптимизация CSS

Упрощайте DOM35

DOM - оптимизация

Генерируйте элементы отдельно от страницы 38

Оптимизация CSS

Клонируйте ваши узлы, изменяйте копии, а затем заменяйте ими оригиналы

Используйте только быстрые обертки над DOM операциями jquery

40

39

Не чередуйте запись и чтение DOM41

Тестируйте css-transitions43

Оптимизация CSS

Избавляйтесь от тяжелых CSS свойств: border-radius, box-shadow, rotate

42

Оптимизация CSS

.disable-hover { pointer-events: none;}

Отключайте сложные :hover анимации во время скроллинга44

Оптимизация CSS

Указывайте четкие размеры изображениям, тем самым ускоряя reflow и repaint

45

Выстраивайте цепочки методов46

Получение данных

Получение данных

(function(module) {'use strict';module.factory('signUpService', signUpService);signUpService.$inject = ['$ionicLoading', 'firebaseService', '$ionicPopup', '$state',

'$q'];function signUpService($ionicLoading, firebaseService, $ionicPopup, $state, $q) {

return { signUp: function(user, userCred) { var newUser = { user: user, userCred: userCred };

/* Registration chain */ checkUsername(newUser) .then(createUser) .then(authByPassword) .then(pushUserDetails) .then(reserveUsername) .catch(throwError); } }; [...]

}}(angular.module('starter')));

Используйте объекты вместо массива аргументов

var alert = new Alert(id, { x: 100, y: 75, width: 300, height: 200, title: "Error", message: message, titleColor: "blue", bgColor: "white", textColor: "black", icon: "error", modal: true});

48

Получение данных

Получайте общие данные не блокируя загрузку основных данных47

Не изменяйте массив arguments. Копируйте его в настоящий, используя [].slice.call(arguments)

49

Получение данных

Не применяйте цикл for in для массивов50

class ExampleController {

constructor() {

this.controllerName = 'Example Controller';

}

}

export { ExampleController }

ES6

ES6Используйте классы для контроллеров и сервисов51

Помещайте export в конец модуля

function sumTwo(a, b) {return a + b;

}

function sumThree(a, b, c) {return a + b + c;

}

let api = {sumTwo,sumThree

};

export default api;

52

ES6

Оставьте декларации VAR внутри унаследованного кода, чтобы обозначить, что он должен быть тщательно переработан

53

ES6

Используйте стрелочные функции

когда вам нужно сохранить лексическое значение thisвместо функциональных выражений, когда это возможно

54

myModule.component('appFooter', { template: '<footer></footer>',

bindings: { entityName: '=' }, controller: function() {

this.getCurrentYear = function() {};}

});

ES6

Используйте API компонент55

+1 советПишите тесты.

Вопросы?

top related