Sangat terlambat ke utas, tetapi teknik yang saya gunakan, pra-Angular, adalah untuk mengambil keuntungan dari JSON dan fleksibilitas JS untuk referensi kunci koleksi yang dinamis, dan menggunakan fakta lingkungan yang tidak dapat dicabut (nama server host, bahasa browser saat ini) , dll.) sebagai input untuk secara selektif membedakan / memilih nama kunci yang suffixed dalam struktur data JSON.
Ini tidak hanya menyediakan konteks lingkungan penerapan (per OP) tetapi konteks sewenang-wenang (seperti bahasa) untuk memberikan i18n atau varian lain yang diperlukan secara bersamaan, dan (idealnya) dalam manifes konfigurasi tunggal, tanpa duplikasi, dan jelas terlihat.
DALAM TENTANG 10 LINES VANILLA JS
Contoh yang terlalu sederhana tetapi klasik: URL dasar endpoint API dalam file properti berformat JSON yang bervariasi per lingkungan di mana (natch) server host juga akan bervariasi:
...
'svcs': {
'VER': '2.3',
'API@localhost': 'http://localhost:9090/',
'API@www.uat.productionwebsite.com': 'https://www.uat.productionwebsite.com:9090/res/',
'API@www.productionwebsite.com': 'https://www.productionwebsite.com:9090/api/res/'
},
...
Kunci ke fungsi diskriminasi adalah hanya nama host server dalam permintaan.
Ini, secara alami, dapat dikombinasikan dengan kunci tambahan berdasarkan pada pengaturan bahasa pengguna:
...
'app': {
'NAME': 'Ferry Reservations',
'NAME@fr': 'Réservations de ferry',
'NAME@de': 'Fähren Reservierungen'
},
...
Cakupan diskriminasi / preferensi dapat terbatas pada kunci individual (seperti di atas) di mana kunci "dasar" hanya ditimpa jika ada kunci yang cocok + akhiran untuk input ke fungsi - atau seluruh struktur, dan struktur itu sendiri diuraikan secara rekursif untuk mencocokkan sufiks / preferensi preferensi:
'help': {
'BLURB': 'This pre-production environment is not supported. Contact Development Team with questions.',
'PHONE': '808-867-5309',
'EMAIL': 'coder.jen@lostnumber.com'
},
'help@www.productionwebsite.com': {
'BLURB': 'Please contact Customer Service Center',
'BLURB@fr': 'S\'il vous plaît communiquer avec notre Centre de service à la clientèle',
'BLURB@de': 'Bitte kontaktieren Sie unseren Kundendienst!!1!',
'PHONE': '1-800-CUS-TOMR',
'EMAIL': 'customer.service@productionwebsite.com'
},
SO, jika pengguna yang mengunjungi situs web produksi memiliki pengaturan preferensi bahasa Jerman ( de ), konfigurasi di atas akan runtuh ke:
'help': {
'BLURB': 'Bitte kontaktieren Sie unseren Kundendienst!!1!',
'PHONE': '1-800-CUS-TOMR',
'EMAIL': 'customer.service@productionwebsite.com'
},
Seperti apa fungsi penulisan ulang preferensi / diskriminasi JSON? Tidak banyak:
// prefer(object,suffix|[suffixes]) by/par/durch storsoc
// prefer({ a: 'apple', a@env: 'banana', b: 'carrot' },'env') -> { a: 'banana', b: 'carrot' }
function prefer(o,sufs) {
for (var key in o) {
if (!o.hasOwnProperty(key)) continue; // skip non-instance props
if(key.split('@')[1]) { // suffixed!
// replace root prop with the suffixed prop if among prefs
if(o[key] && sufs.indexOf(key.split('@')[1]) > -1) o[key.split('@')[0]] = JSON.parse(JSON.stringify(o[key]));
// and nuke the suffixed prop to tidy up
delete o[key];
// continue with root key ...
key = key.split('@')[0];
}
// ... in case it's a collection itself, recurse it!
if(o[key] && typeof o[key] === 'object') prefer(o[key],sufs);
};
};
Dalam implementasi kami, yang mencakup situs web Angular dan pra-Angular, kami cukup mem-bootstrap konfigurasi jauh di depan panggilan sumber daya lainnya dengan menempatkan JSON dalam penutupan JS yang dapat dieksekusi sendiri, termasuk fungsi prefer (), dan memasukkan properti dasar dari nama host dan kode bahasa (dan menerima sufiks arbitrer tambahan apa pun yang mungkin Anda butuhkan):
(function(prefs){ var props = {
'svcs': {
'VER': '2.3',
'API@localhost': 'http://localhost:9090/',
'API@www.uat.productionwebsite.com': 'https://www.uat.productionwebsite.com:9090/res/',
'API@www.productionwebsite.com': 'https://www.productionwebsite.com:9090/api/res/'
},
...
/* yadda yadda moar JSON und bisque */
function prefer(o,sufs) {
// body of prefer function, broken for e.g.
};
// convert string and comma-separated-string to array .. and process it
prefs = [].concat( ( prefs.split ? prefs.split(',') : prefs ) || []);
prefer(props,prefs);
window.app_props = JSON.parse(JSON.stringify(props));
})([location.hostname, ((window.navigator.userLanguage || window.navigator.language).split('-')[0]) ] );
Situs pra-Angular sekarang akan memiliki jendela collapsed (no @ suffixed keys ) .app_props untuk merujuk.
Situs Angular, sebagai langkah bootstrap / init, cukup menyalin objek prop yang mati ke $ rootScope, dan (secara opsional) menghancurkannya dari ruang lingkup global / jendela
app.constant('props',angular.copy(window.app_props || {})).run( function ($rootScope,props) { $rootScope.props = props; delete window.app_props;} );
untuk selanjutnya disuntikkan ke pengendali:
app.controller('CtrlApp',function($log,props){ ... } );
atau disebut dari binding dalam tampilan:
<span>{{ props.help.blurb }} {{ props.help.email }}</span>
Peringatan? Karakter @ tidak valid penamaan variabel / kunci JS / JSON, tetapi sejauh ini diterima. Jika itu adalah deal-breaker, gantikan konvensi yang Anda suka, seperti "__" (double garis bawah) selama Anda tetap menggunakannya.
Teknik ini bisa diterapkan di sisi server, porting ke Java atau C # tetapi efisiensi / kekompakan Anda mungkin bervariasi.
Bergantian, fungsi / konvensi dapat menjadi bagian dari skrip kompilasi front-end Anda, sehingga JSON lengkap semua-lingkungan / semua-bahasa tidak pernah dikirimkan melalui kabel.
MEMPERBARUI
Kami telah mengembangkan penggunaan teknik ini untuk memungkinkan beberapa sufiks pada kunci, untuk menghindari dipaksa menggunakan koleksi (Anda masih bisa, sedalam yang Anda inginkan), dan juga untuk menghormati urutan sufiks yang disukai.
Contoh (juga lihat jsFiddle yang berfungsi ):
var o = { 'a':'apple', 'a@dev':'apple-dev', 'a@fr':'pomme',
'b':'banana', 'b@fr':'banane', 'b@dev&fr':'banane-dev',
'c':{ 'o':'c-dot-oh', 'o@fr':'c-point-oh' }, 'c@dev': { 'o':'c-dot-oh-dev', 'o@fr':'c-point-oh-dev' } };
/*1*/ prefer(o,'dev'); // { a:'apple-dev', b:'banana', c:{o:'c-dot-oh-dev'} }
/*2*/ prefer(o,'fr'); // { a:'pomme', b:'banane', c:{o:'c-point-oh'} }
/*3*/ prefer(o,'dev,fr'); // { a:'apple-dev', b:'banane-dev', c:{o:'c-point-oh-dev'} }
/*4*/ prefer(o,['fr','dev']); // { a:'pomme', b:'banane-dev', c:{o:'c-point-oh-dev'} }
/*5*/ prefer(o); // { a:'apple', b:'banana', c:{o:'c-dot-oh'} }
1/2 (penggunaan dasar) lebih suka kunci '@dev', buang semua kunci sufiks lainnya
3 lebih suka '@dev' daripada '@fr', lebih suka '@ dev & fr' daripada yang lainnya
4 (sama dengan 3 tetapi lebih suka '@fr' daripada '@dev')
5 tidak ada sufiks pilihan, tetes SEMUA properti sufiks
Ini mencapai ini dengan mencetak setiap properti suffix dan mempromosikan nilai properti suffix ke properti non-suffix ketika iterating atas properti dan menemukan akhiran skor yang lebih tinggi.
Beberapa efisiensi dalam versi ini, termasuk menghilangkan ketergantungan pada JSON untuk menyalin dalam, dan hanya berulang ke objek yang bertahan dari putaran penilaian di kedalamannya:
function prefer(obj,suf) {
function pr(o,s) {
for (var p in o) {
if (!o.hasOwnProperty(p) || !p.split('@')[1] || p.split('@@')[1] ) continue; // ignore: proto-prop OR not-suffixed OR temp prop score
var b = p.split('@')[0]; // base prop name
if(!!!o['@@'+b]) o['@@'+b] = 0; // +score placeholder
var ps = p.split('@')[1].split('&'); // array of property suffixes
var sc = 0; var v = 0; // reset (running)score and value
while(ps.length) {
// suffix value: index(of found suffix in prefs)^10
v = Math.floor(Math.pow(10,s.indexOf(ps.pop())));
if(!v) { sc = 0; break; } // found suf NOT in prefs, zero score (delete later)
sc += v;
}
if(sc > o['@@'+b]) { o['@@'+b] = sc; o[b] = o[p]; } // hi-score! promote to base prop
delete o[p];
}
for (var p in o) if(p.split('@@')[1]) delete o[p]; // remove scores
for (var p in o) if(typeof o[p] === 'object') pr(o[p],s); // recurse surviving objs
}
if( typeof obj !== 'object' ) return; // validate
suf = ( (suf || suf === 0 ) && ( suf.length || suf === parseFloat(suf) ) ? suf.toString().split(',') : []); // array|string|number|comma-separated-string -> array-of-strings
pr(obj,suf.reverse());
}
'ngconstant:development'
di'serve'
- jika Anda memasukkannya ke dalam config menonton di bawah'gruntfile'
sepertitasks: ['ngconstant:development']
- Anda tidak perlu me-restartgrunt serve
ketika Anda memperbarui variabel pembangunan di gruntfile tersebut.