Berkat sejumlah besar sumber berharga saya punya beberapa rekomendasi umum untuk menerapkan komponen dalam aplikasi AngularJS:
Pengendali
Kontroler harus hanya merupakan interaksi antara model dan tampilan. Cobalah membuatnya setipis mungkin.
Sangat disarankan untuk menghindari logika bisnis dalam pengontrol. Itu harus dipindahkan ke model.
Pengontrol dapat berkomunikasi dengan pengontrol lain menggunakan doa metode (mungkin ketika anak-anak ingin berkomunikasi dengan orang tua) atau $ emit , $ broadcast dan $ on metode. Pesan yang dipancarkan dan disiarkan harus dijaga agar tetap minimum.
Pengontrol seharusnya tidak peduli dengan presentasi atau manipulasi DOM.
Cobalah untuk menghindari pengendali bersarang . Dalam hal ini pengendali orangtua diartikan sebagai model. Suntikkan model sebagai layanan bersama.
Lingkup pada pengontrol harus digunakan untuk model penjilidan dengan tampilan dan
enkapsulasi Model Tampilan sebagaimana untuk pola desain Model Presentasi .
Cakupan
Perlakukan ruang lingkup sebagai read-only dalam templat dan write-only di controller . Tujuan dari ruang lingkup adalah untuk merujuk pada model, bukan untuk menjadi model.
Saat melakukan pengikatan dua arah (model-ng) pastikan Anda tidak mengikat langsung ke properti scope.
Model
Model dalam AngularJS adalah singleton yang ditentukan oleh layanan .
Model menyediakan cara terbaik untuk memisahkan data dan tampilan.
Model adalah kandidat utama untuk pengujian unit, karena mereka biasanya memiliki tepat satu dependensi (beberapa bentuk emitor acara, biasanya $ rootScope ) dan berisi logika domain yang sangat dapat diuji .
Model harus dipertimbangkan sebagai implementasi dari unit tertentu. Ini didasarkan pada prinsip tanggung jawab tunggal. Unit adalah contoh yang bertanggung jawab atas ruang lingkup logika terkait yang dapat mewakili entitas tunggal di dunia nyata dan menggambarkannya dalam dunia pemrograman dalam hal data dan status .
Model harus merangkum data aplikasi Anda dan menyediakan API
untuk mengakses dan memanipulasi data itu.
Model harus portabel sehingga dapat dengan mudah diangkut ke aplikasi serupa.
Dengan mengisolasi unit logic dalam model Anda, Anda telah membuatnya lebih mudah untuk menemukan, memperbarui, dan memelihara.
Model dapat menggunakan metode model global yang lebih umum yang umum untuk seluruh aplikasi.
Cobalah untuk menghindari komposisi model lain ke dalam model Anda menggunakan injeksi ketergantungan jika tidak benar-benar tergantung untuk mengurangi kopling komponen dan meningkatkan unit testability dan usability .
Cobalah untuk menghindari menggunakan pendengar acara dalam model. Itu membuat mereka lebih sulit untuk menguji dan umumnya membunuh model dalam hal prinsip tanggung jawab tunggal.
Implementasi Model
Karena model harus merangkum beberapa logika dalam hal data dan keadaan, itu harus secara arsitektural membatasi akses ke para anggotanya sehingga kami dapat menjamin kopling longgar.
Cara untuk melakukannya dalam aplikasi AngularJS adalah dengan mendefinisikannya menggunakan jenis layanan pabrik . Ini akan memungkinkan kami untuk mendefinisikan properti dan metode pribadi dengan sangat mudah dan juga mengembalikan yang dapat diakses secara publik di satu tempat yang akan membuatnya benar-benar dapat dibaca oleh pengembang.
Contoh :
angular.module('search')
.factory( 'searchModel', ['searchResource', function (searchResource) {
var itemsPerPage = 10,
currentPage = 1,
totalPages = 0,
allLoaded = false,
searchQuery;
function init(params) {
itemsPerPage = params.itemsPerPage || itemsPerPage;
searchQuery = params.substring || searchQuery;
}
function findItems(page, queryParams) {
searchQuery = queryParams.substring || searchQuery;
return searchResource.fetch(searchQuery, page, itemsPerPage).then( function (results) {
totalPages = results.totalPages;
currentPage = results.currentPage;
allLoaded = totalPages <= currentPage;
return results.list
});
}
function findNext() {
return findItems(currentPage + 1);
}
function isAllLoaded() {
return allLoaded;
}
// return public model API
return {
/**
* @param {Object} params
*/
init: init,
/**
* @param {Number} page
* @param {Object} queryParams
* @return {Object} promise
*/
find: findItems,
/**
* @return {Boolean}
*/
allLoaded: isAllLoaded,
/**
* @return {Object} promise
*/
findNext: findNext
};
});
Membuat instance baru
Cobalah untuk menghindari memiliki pabrik yang mengembalikan fungsi baru karena ini mulai memecah injeksi ketergantungan dan perpustakaan akan berperilaku canggung, terutama untuk pihak ketiga.
Cara yang lebih baik untuk mencapai hal yang sama adalah dengan menggunakan pabrik sebagai API untuk mengembalikan koleksi objek dengan metode pengambil dan penyetel yang melekat padanya.
angular.module('car')
.factory( 'carModel', ['carResource', function (carResource) {
function Car(data) {
angular.extend(this, data);
}
Car.prototype = {
save: function () {
// TODO: strip irrelevant fields
var carData = //...
return carResource.save(carData);
}
};
function getCarById ( id ) {
return carResource.getById(id).then(function (data) {
return new Car(data);
});
}
// the public API
return {
// ...
findById: getCarById
// ...
};
});
Model Global
Secara umum cobalah untuk menghindari situasi seperti itu dan desain model Anda dengan benar sehingga dapat disuntikkan ke pengontrol dan digunakan dalam pandangan Anda.
Dalam kasus tertentu beberapa metode memerlukan aksesibilitas global dalam aplikasi. Untuk memungkinkannya, Anda dapat mendefinisikan properti ' umum ' di $ rootScope dan mengikatnya ke commonModel selama aplikasi bootstrap:
angular.module('app', ['app.common'])
.config(...)
.run(['$rootScope', 'commonModel', function ($rootScope, commonModel) {
$rootScope.common = 'commonModel';
}]);
Semua metode global Anda akan hidup dalam properti ' umum '. Ini adalah semacam namespace .
Tetapi jangan mendefinisikan metode apa pun secara langsung di $ rootScope Anda . Hal ini dapat menyebabkan perilaku yang tidak terduga saat digunakan dengan arahan ngModel dalam lingkup tampilan Anda, umumnya membuang sampah di ruang lingkup Anda dan mengarah ke metode lingkup mengatasi masalah.
Sumber
Sumber daya memungkinkan Anda berinteraksi dengan berbagai sumber data .
Harus diimplementasikan menggunakan prinsip tanggung jawab tunggal .
Dalam kasus tertentu, ini adalah proxy yang dapat digunakan kembali ke titik akhir HTTP / JSON.
Sumber daya disuntikkan dalam model dan memberikan kemungkinan untuk mengirim / mengambil data.
Implementasi sumber daya
Pabrik yang membuat objek sumber daya yang memungkinkan Anda berinteraksi dengan sumber data sisi server RESTful.
Objek sumber daya yang dikembalikan memiliki metode tindakan yang menyediakan perilaku tingkat tinggi tanpa perlu berinteraksi dengan layanan $ http tingkat rendah.
Jasa
Baik model maupun sumber daya adalah layanan .
Layanan tidak terkait, unit fungsionalitas yang digabungkan secara mandiri yang mandiri.
Layanan adalah fitur yang dibawa Angular ke aplikasi web sisi klien dari sisi server, di mana layanan telah umum digunakan untuk waktu yang lama.
Layanan di aplikasi Angular adalah objek yang dapat diganti yang disatukan menggunakan injeksi ketergantungan.
Angular hadir dengan berbagai jenis layanan. Masing-masing dengan kasus penggunaannya sendiri. Silakan baca Memahami Jenis Layanan untuk detailnya.
Cobalah untuk mempertimbangkan prinsip-prinsip utama arsitektur layanan dalam aplikasi Anda.
Secara umum menurut Glosarium Layanan Web :
Layanan adalah sumber daya abstrak yang mewakili kemampuan melakukan tugas yang membentuk fungsionalitas yang koheren dari sudut pandang entitas penyedia dan entitas pemohon. Untuk digunakan, layanan harus direalisasikan oleh agen penyedia beton.
Struktur sisi klien
Secara umum sisi klien dari aplikasi ini dibagi menjadi beberapa modul . Setiap modul harus dapat diuji sebagai satu unit.
Cobalah untuk mendefinisikan modul tergantung pada fitur / fungsi atau tampilan , bukan berdasarkan jenis. Lihat presentasi Misko untuk detailnya.
Komponen modul dapat dikelompokkan secara konvensional berdasarkan jenis seperti pengontrol, model, tampilan, filter, arahan, dll.
Tetapi modul itu sendiri tetap dapat digunakan kembali , dapat ditransfer dan diuji .
Juga jauh lebih mudah bagi pengembang untuk menemukan beberapa bagian kode dan semua dependensinya.
Lihat Organisasi Kode di AngularJS Besar dan Aplikasi JavaScript untuk detailnya.
Contoh penataan folder :
|-- src/
| |-- app/
| | |-- app.js
| | |-- home/
| | | |-- home.js
| | | |-- homeCtrl.js
| | | |-- home.spec.js
| | | |-- home.tpl.html
| | | |-- home.less
| | |-- user/
| | | |-- user.js
| | | |-- userCtrl.js
| | | |-- userModel.js
| | | |-- userResource.js
| | | |-- user.spec.js
| | | |-- user.tpl.html
| | | |-- user.less
| | | |-- create/
| | | | |-- create.js
| | | | |-- createCtrl.js
| | | | |-- create.tpl.html
| |-- common/
| | |-- authentication/
| | | |-- authentication.js
| | | |-- authenticationModel.js
| | | |-- authenticationService.js
| |-- assets/
| | |-- images/
| | | |-- logo.png
| | | |-- user/
| | | | |-- user-icon.png
| | | | |-- user-default-avatar.png
| |-- index.html
Contoh yang bagus dari penataan aplikasi sudut diterapkan oleh aplikasi angular - https://github.com/angular-app/angular-app/tree/master/client/src
Ini juga dipertimbangkan oleh generator aplikasi modern - https://github.com/yeoman/generator-angular/issues/109