Apakah nuansa prototaip skop / warisan prototaip dalam AngularJS?
Jawapan Pantas:
Skop kanak-kanak lazimnya mewarisi skop induknya, tetapi bukan selalu. Satu pengecualian kepada peraturan ini ialah arahan dengan skop: { ... } -- ini mewujudkan skop "pengasingan" yang tidak diwarisi secara prototaip. Konstruk ini sering digunakan semasa mencipta arahan "komponen boleh guna semula".
Mengenai nuansa, warisan skop biasanya mudah... sehingga anda memerlukan pengikatan data 2 hala (cth., borang elemen, ng-model) dalam skop kanak-kanak. Ng-repeat, ng-switch dan ng-include boleh membuat anda tersandung jika anda cuba mengikat kepada primitif (cth., nombor, rentetan, boolean) dalam skop induk dari dalam skop anak. Ia tidak berfungsi seperti yang dijangkakan kebanyakan orang. Skop kanak-kanak mendapat hartanya sendiri yang menyembunyikan/melindungi harta induk dengan nama yang sama. Penyelesaian anda ialah:
Pembangun AngularJS baharu selalunya tidak menyedari bahawa ng-repeat, ng-switch, ng-view, ng-include dan ng-if semua mencipta baharu skop kanak-kanak, jadi masalah sering muncul apabila arahan ini terlibat. (Lihat contoh ini untuk gambaran ringkas masalah itu.)
Isu primitif ini boleh dielakkan dengan mudah dengan mengikuti "amalan terbaik" sentiasa mempunyai '.' dalam model-ng anda – tonton 3 minit bernilai. Misko menunjukkan isu pengikatan primitif dengan suis-ng.
Mempunyai '.' dalam model anda akan memastikan bahawa warisan prototaip sedang dimainkan. Jadi, gunakan:
L-o-n-g Jawapan:
Memahami Prototaip Warisan
Adalah penting untuk memahami warisan prototaip sebelum membincangkan warisan skop.
Andaikan parentScope mempunyai sifat aString, aNumber, anArray, anObject dan aFunction. Jika prototaip childScope mewarisi daripada parentScope, kami mempunyai:
[Imej rajah warisan prototaip]
Jika kami cuba mengakses sifat yang ditakrifkan pada parentScope daripada skop kanak-kanak, JavaScript akan melihat dahulu skop anak, bukan cari harta, kemudian cari dalam skop yang diwarisi, dan cari harta itu. (Jika ia tidak menjumpai harta dalam parentScope, ia akan meneruskan rantaian prototaip... sehingga ke skop akar). Jadi, ini semua adalah benar:
childScope.aString === 'parent string' childScope.anArray[1] === 20 childScope.anObject.property1 === 'parent prop1' childScope.aFunction() === 'parent output'
Andaikan kita melakukan ini:
childScope.aString === 'parent string' childScope.anArray[1] === 20 childScope.anObject.property1 === 'parent prop1' childScope.aFunction() === 'parent output'
Rantaian prototaip tidak dirujuk dan sifat aString baharu ditambahkan pada childScope. Sifat baharu ini menyembunyikan/melindungi sifat parentScope dengan nama yang sama. Ini akan menjadi sangat penting apabila kita membincangkan ng-repeat dan ng-include di bawah.
[Imej gambar rajah penyembunyian harta]
Andaikata kita melakukan ini:
childScope.aString = 'child string'
Rantaian prototaip dirujuk kerana objek (anArray dan anObject) tidak ditemui dalam childScope. Objek ditemui dalam parentScope, dan nilai harta dikemas kini pada objek asal. Tiada sifat baharu ditambahkan pada childScope; tiada objek baru dicipta. (Perhatikan bahawa dalam tatasusunan dan fungsi JavaScript juga merupakan objek.)
[Imej ikut rajah rantai prototaip]
Andaikata kita melakukan ini:
childScope.anArray[1] = '22' childScope.anObject.property1 = 'child prop1'
The rantaian prototaip tidak dirujuk dan skop kanak-kanak mendapat dua sifat objek baharu yang menyembunyikan/melindungi sifat objek parentScope dengan perkara yang sama nama.
[Imej lebih banyak rajah penyembunyian harta]
Warisan Skop Sudut
Para pesaing:
Secara lalai, arahan tidak mencipta skop baharu (iaitu, skop: palsu).
ng-include
Andaikan kita ada dalam pengawal kita:
childScope.anArray = [100, 555] childScope.anObject = { name: 'Mark', country: 'USA' }
Dan dalam HTML kami:
$scope.myPrimitive = 50; $scope.myObject = {aNumber: 11};
Setiap ng-include menjana skop anak baharu, yang secara prototaip mewarisi daripada skop induk.
[Imej rajah skop kanak-kanak ng-include]
Menaip (katakan, "77") ke dalam kotak teks input pertama menyebabkan skop kanak-kanak mendapat skop myPrimitive baharu sifat yang menyembunyikan/melindungi sifat skop induk dengan nama yang sama.
[Imej ng-include dengan gambar rajah primitif]
Menaip (katakan, "99") ke dalam kotak teks input kedua tidak menghasilkan harta anak baru. Oleh kerana tpl2.html mengikat model kepada sifat objek, warisan prototaip bermula apabila ngModel mencari objek myObject -- ia menemuinya dalam skop induk.
[Imej ng-include dengan gambar rajah objek]
Kami boleh menulis semula templat pertama untuk menggunakan $parent, jika kami tidak mahu menukar model kami daripada primitif kepada objek:
<script type="text/ng-template">
Menaip (sebut, "22") ke dalam kotak teks input ini tidak menghasilkan sifat anak baharu. Model kini terikat pada sifat skop induk (kerana $parent ialah sifat skop anak yang merujuk skop induk).
[Imej ng-include dengan $parent diagram]
ng-suis
Warisan skop ng-switch berfungsi sama seperti ng-include. Jadi, jika anda memerlukan data 2 hala yang mengikat kepada primitif dalam skop induk, gunakan $parent, atau tukar model menjadi objek dan kemudian ikat pada sifat objek itu. Ini akan mengelakkan skop kanak-kanak menyembunyikan/membayangi sifat skop induk.
ng-repeat
Ng-repeat berfungsi sedikit berbeza. Katakan kita ada dalam pengawal kita:
childScope.aString === 'parent string' childScope.anArray[1] === 20 childScope.anObject.property1 === 'parent prop1' childScope.aFunction() === 'parent output'
Dan dalam HTML kami:
childScope.aString = 'child string'
Untuk setiap item/lelaran, ng-repeat mencipta skop baharu, yang secara prototaip diwarisi daripada induk skop, tetapi ia juga memberikan nilai item kepada sifat baharu pada skop anak baharu (sifat baharu ialah nama pembolehubah gelung). Berikut ialah kod sumber sudut untuk ng-repeat sebenarnya:
childScope.anArray[1] = '22' childScope.anObject.property1 = 'child prop1'
Jika item itu primitif (seperti dalam myArrayOfPrimitives), pada asasnya salinan nilai diberikan kepada harta skop anak baharu. Menukar nilai harta skop kanak-kanak (iaitu, menggunakan model-ng, oleh itu nombor skop kanak-kanak) tidak mengubah tatasusunan rujukan skop induk. Jadi dalam ng-ulang pertama di atas, setiap skop kanak-kanak mendapat sifat num yang bebas daripada tatasusunan myArrayOfPrimitives:
[Imej ng-ulang dengan gambar rajah primitif]
ng-ulang ini tidak akan berfungsi (seperti yang anda mahu/jangkakan). Menaip ke dalam kotak teks menukar nilai dalam kotak kelabu, yang hanya kelihatan dalam skop kanak-kanak. Apa yang kita mahukan ialah input mempengaruhi tatasusunan myArrayOfPrimitives, bukan harta primitif skop kanak-kanak. Untuk mencapainya, kita perlu menukar model menjadi tatasusunan objek.
Jadi, jika item itu objek, rujukan kepada objek asal (bukan salinan) diberikan kepada skop kanak-kanak baharu harta benda. Menukar nilai harta skop kanak-kanak (iaitu, menggunakan model ng, oleh itu obj.num) memang mengubah objek rujukan skop induk. Jadi dalam ng-repeat kedua di atas, kita ada:
[Imej ng-repeat dengan gambarajah objek]
(Saya warnakan satu garisan kelabu supaya jelas di mana ia akan berjalan.)
Ini berfungsi seperti yang diharapkan. Menaip ke dalam
Atas ialah kandungan terperinci Bagaimanakah Warisan Prototaip Berfungsi dengan Pengikatan Data Dua Hala dalam Skop AngularJS?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!