AngularJS1.2から1.4ぞの移行、パヌト1

バヌゞョン1.2からアップグレヌドする利点に぀いおは、倚くの蚘事が曞かれおいたす。 ただし、統蚈によるず、45以䞊のサむトが匕き続きバヌゞョン1.2を䜿甚しおおり、新しい1.3に切り替えたのは31のみで、1.4を䜿甚しおいるのは5のみです。



そしお、これは宇宙船が宇宙の広がりを耕すずきです。バヌゞョン1.2.0はほが2幎前にリリヌスされ、バヌゞョン1.3.0-1幎前、バヌゞョン1.4.0-この春、そしお1.5.0はすでにベヌタ版です。







原則ずしお、移行からの倧芏暡なプロゞェクトは、このプロセスの䞍透明性ずこのトピックに関する資料の䞍足を劚げたす。

公匏ガむドでは、発生する可胜性のあるすべおの問題のほんの䞀郚を芋぀けるこずができたす。たた、ブログでは、原則ずしお、それを再確認するだけです。



この蚘事では、新しいバヌゞョンぞの移行時に発生する可胜性のある問題に぀いお説明し、最も問題のある堎所を分析したす。



残念ながら、投皿が倧きすぎたため、このパヌトではこの移行の重倧な倉曎に焊点を圓お、次のパヌトで機胜ず利点に぀いお説明したす。 しかし、移行の䞻な利点は、䜜業速床の倧幅な向䞊ず修正されたバグのリストです結局、1.2の最新の修正は1幎前の1.2.28でした。



この投皿を2぀の郚分に分けたした。 そのうちの1぀は、2぀のプロゞェクトを新しいバヌゞョンに倉換した個人的な経隓ですネタバレの䞋に隠したした。2぀目は、発芋された問題のリストです。



移行のストヌリヌ
1.2から1.3ぞの移行を必芁ずする最初の比范的倧きなプロゞェクトは、12,000行を超えるコヌド䞻にディレクティブにもかかわらず、問題が発生しないEラヌニングプラットフォヌムでした。



2番目のプロゞェクトでは、バヌゞョン1.2.16から1.4.4ぞの移行が必芁で、かなり倧きく玔粋な角床の玄75,000行、補品アカりンティングの詳现が耇雑な関係、倚くの圢態、避けられない問題を暗瀺しおいたしたが、以前の経隓は勇気づけられたした。



移行の最初の結果は、コン゜ヌルに倚数の゚ラヌを含む砎損したアプリケヌションを取埗するこずが予想されおいたしたが、アプリケヌションは起動し、問題はありたせんでした。 それは非垞に奇劙だったので、私は公匏ガむドを通しお旅を始めたしたが、説明された問題はどれも再珟されたせんでした。 ゞョブが完了したず刀断したので、QAず自動テストにタスクを割り圓おたした。



そしお翌日、私は9個のバグを受け取り、さらに9個のバグを受け取りたした。 芋぀かったすべおの゚ラヌのcさは、アプリケヌションを壊すこずではなく、動䜜を感知できないほど倉曎するこずです。



ここで、 倉曎ログずそこに芋぀かったコミット内の議論は、理由を探しお友ず仲間になりたした。



最初のステップずしお、サヌバヌ偎の非同期チェックが倱敗したした。これはステヌタスではなく、「OK」などのテキストプリミティブの圢匏の回答で機胜したした。 これに぀いお通知されるブレヌクの倉曎は1぀ではありたせんが、察応するバグ修正がありたした。



ヒント XHRリク゚ストで䜜業を確認しおください。 サヌバヌがオブゞェクトを送信せず、ヘッダヌ「application / json」を持぀プリミティブがある堎合、問題が発生したす。



次に、ポップアップにネストされたスピナヌが萜ち、芪の幅を正しく決定するために停止したした。 問題は2぀ありたした。 たず、スピナヌはng-showにありたした 。これは、芪コンテナが衚瀺される前に初期化されたこずを意味したす。 第二に、スピナヌは$ observeを介しお属性に続いお/ hid を衚瀺したした 。 䜕らかの理由で、叀いバヌゞョンでは、芪がvisibleになっおから属性が倉曎され、新しい属性ではその逆になりたす。



ヒント

  1. ng-show / ng-hideで初期化する際に重芁な動的ディレクティブを保存しないでください。これにはng-ifを䜿甚しおください。 このヒントはバヌゞョン1.2でも有効です。
  2. 他のデヌタDOMたたは$スコヌプぞの倖郚の倉曎を監芖する堎合は、 $ observeを䜿甚しお属性を远跡しないでください。 これには$ watchfunction{}、function{}を䜿甚したす。 さらに、どちらのオプションもりォヌタヌマヌクをダヌティチェックに远加したすが、唯䞀の違いはコヌルバック呌び出し条件です。




この問題は、 $ eval内の匏の条件にも圱響したした。いく぀かのブロックが消え始めたした。 しかし、問題は別のバグ修正であるこずが刀明し、すでにハブでカバヌされおいたした



ヒントフレヌムワヌクの文曞化されおいない機胜を䜿甚しないでください。 $スコヌプの次の倀をチェックするずきに䜿甚するコヌドを調べおください 'f' 、 '0' 、 'false' 、 'no' 、 'n' 、 '[]' 。



発生した䞻な問題は怜蚌です。 バヌゞョン1.3から、フォヌムをチェックするための新しい方法が角床から登堎し、新しい萜ずし穎がありたした。 ただし、新しい怜蚌を䜿甚する予定がない堎合でも、問題が発生する可胜性がありたす。 これらは、 maxlength / minlengthディレクティブず、フォヌムを氞続的に無効にする恐れがある$ setValidityの新しいロゞックですこれは私たちに起こったこずです。



新しいバヌゞョンでは有効条件の1぀がngModelCtrlの空のハッシュであるため、 ngModelCtrl 。



ヒント公匏のAPIで指定されおいない$で始たるプロパティを入力しないでください。



ng-maxlength / ng-minlengthディレクティブず䞊行しおマスク電話、契玄番号などを䜿甚する入力で別の問題が発生したした。



これらのディレクティブは䞡方ずも、 ngModelCtrl。$ ModelValueの代わりにngModelCtrl。$ ViewValueをチェックしたす。これは、倀 "xx-xx"の最倧長が4ではなく5 "-"文字を考慮であるこずを意味したす。 アプリケヌション党䜓で数癟の怜蚌ルヌルを曞き盎さなければならないので、すべおのng-maxlengthをカスタムmodel-maxlengthに眮き換えお、モデルの再チェックのみを行うこずにしたした。 そしお、その決定はひどいものでした Angularはmaxlength制限属性を自分甚に予玄したした。぀たり、入力する文字数を制限できなくなりたした。 その結果、マスクシンボルを考慮しお、すべおのルヌルを新しいルヌルに倉曎するこずが決定されたした。 ただし、カスタムmodel-minlengthディレクティブは、事前定矩された文字たずえば、電話の "+7"があるディレクティブでアプリケヌションを芋぀けたため、 ngModelCtrl。$ ViewValueで蚭定されたプレフィックスなしでモデルのみをチェックできたす。



ヒントマスクを䜿甚する堎合、たたはngModelCtrl。$ ViewValueの倀を操䜜する堎合は、マスクの文字に基づいおチェックを倉曎したす。 ng-minlengthチェックを䜿甚しお入力の事前定矩倀にプレヌスホルダヌ属性を䜿甚するか、チェックをカスタムチェックに眮き換えたす。 このようなディレクティブの䜜業コヌドは、ブレヌク倉曎リストにありたす。



問題の2番目の波は、怜蚌を新しいものさようなら、 $フォヌマッタヌ 、および$パヌサヌ に移行した埌に発生したした。 倚くのフォヌムが再び氞久に無効になったずいう事実に盎面しおいたす。



同期怜蚌 $ validators を䜿甚するず、問題がすぐに明らかになりたした。 それは、フォヌムに怜蚌チェック付きのng-showで隠されたフィヌルドがあるずいう事実にありたした。 叀いバヌゞョン $フォヌマッタヌず$パヌサヌ  の䜜業の性質により、これらのフィヌルドはフォヌム怜蚌に含たれおいたせんでしたが、新しいバヌゞョン $バリデヌタヌ では非衚瀺の無効なフィヌルドが衚瀺されたす。



ヒント非衚瀺の動的フィヌルドを持぀フォヌムがある堎合、これらのフィヌルドを非衚瀺にするか 、 ng-ifで衚瀺したす。ng-show/ ng-hideは䜿甚しないでください。



備考非同期バリデヌタヌの仕組み
非同期バリデヌタヌはngModelCtrl。$ AsyncValidatorsコレクションに保存され、 Promiseを返す関数です。 Promiseはさたざたなサヌビスたずえば、$ timeoutや$ httpを返し、特別なサヌビス$ qによっおも生成されたす。 フィヌルドの有効性は、返されたプロミスの解決たたは拒吊に䟝存したす。 非同期怜蚌は、すべおの同期怜蚌が有効になった埌にのみ開始されたす。 バリデヌタヌが呌び出されるずき、その劥圓性 $ setValidity は未定矩になり、期埅されるバリデヌタヌの名前がngModelCtrl。$ Pendingに衚瀺されたす。 promiseの解決が発生するずすぐに、その有効性はnullに蚭定されたす 。



怜蚌関数を数回呌び出すず、最埌の玄束は前のものを消去したす。 ぀たり、フィヌルドが2回怜蚌され、最初のプロミスが解決され、2番目のプロミスが拒吊された堎合、フィヌルドは無効になりたす。



APIドキュメントの䟋

ngModel.$asyncValidators.uniqueUsername = function(modelValue, viewValue) { var value = modelValue || viewValue; // Lookup user by username return $http.get('/api/users/' + value). then(function resolved() { //username exists, this means validation fails return $q.reject('exists'); }, function rejected() { //username does not exist, therefore this validation passes return true; }); };
      
      







非同期怜蚌はより困難であるこずが刀明したした。フォヌムは無効でしたが、゚ラヌは含たれおいたせんでした。



ここでは、マスクの機胜により $ formattersおよび$ parsersを介しお、同期怜蚌が完了する前に非同期怜蚌が呌び出され、1぀の倉曎された文字に察しお数回呌び出されたした。 これにより、耇数の玄束の䜜成バグが発生し、最埌の玄束が解決たたは拒吊されなかったずいう事実に至りたした。 したがっお、入力は無期限に保留され、フォヌムぱラヌなしで無効になりたした。



そのような堎合のバリデヌタヌを構築する䟋
  var pendingPromise; ngModelCtrl.$asyncValidators.checkPhoneUnique = function (modelValue) { if (pendingPromise) { return pendingPromise; } var deferred = $q.defer(); if (modelValue) { pendingPromise = deferred.promise; $http.post('/', {value: modelValue}) .success(function (response) { if (response.Result === '   ') { deferred.resolve(); } else { deferred.reject(); } }).error(function () { deferred.reject(); }).finally(function () { pendingPromise = null; }); } else { deferred.resolve(); } return deferred.promise; };
      
      







ヒント非同期バリデヌタヌの動䜜をテストしたす。返されたプロミスが垞に解決たたは拒吊されるこずを確認したす。



怜蚌の最も奇劙な問題は、金額を入力するためのカスタムディレクティブでしたルヌブルずセントの2぀の入力のように芋え、ngModelにこれらの数倀を連結した既補の結果を䞎えたす。 圌女は無効であるだけでなく、フレヌムワヌクの奥からコン゜ヌルに゚ラヌを䌝えたした。



問題に費やされた時間はかなり良かった、問題は再びng-maxlengthであり、解決策は簡単だった$ formatValuesディレクティブの文字列に$ viewValue倀を远加したした。



しかし、なぜ問題が発生したのでしょうか それを理解したしょう



それはすべお$コンパむルの䜜業に関するものです。メむンディレクティブの動䜜は内郚に蚘述されおいたす。 たずえば、 inputおよびtextareaの堎合、 inputDirectiveコントロヌルが呌び出されたす 。これはattr.typeを受け取り、それに基づいおinputTypeコレクションの関数の1぀を呌び出したす。 テキストタむプの堎合、これはtextInputTypeです。 次に、圌はコントロヌルをstringBasedInputType関数にスロヌしたす。この関数は、倀を$ formattersの文字列に倉換するためのコヌドを远加したす。



したがっお、 ngModelが inputなどの既存の基本芁玠に関連付けられおいないが、たずえば単玔な歌姫たたはカスタムディレクティブこの堎合、金額を入力するためのディレクティブでハングしおいる堎合、デヌタは「 そのたた 」 $ viewModelにロヌルされたす。これにより、maxlengthなどのフィルタヌディレクティブで゚ラヌが発生したす。maxlengthは、数倀にない.lengthプロパティを䜿甚したす。



Plunkerの実䟋 。



ヒント数倀で機胜するすべおのカスタムディレクティブには、数倀を文字列に倉換するための適切なフォヌマッタヌが必芁です。



結果



その結果、テストの玄6回の反埩が実行され、54の問題が芋぀かりたしたが、それらのほずんどは同様の性質を備えおいたした。 問題の䞀郚がたったくなかった可胜性がありたす。䜜業のバグや文曞化されおいない機胜のために䞀郚のコヌドセクションを䜿甚しないでください。 リファクタリングず新しい怜蚌ぞの切り替えを考慮しお、合蚈56のコミットず1人あたり3週間の䜜業時間が移行に費やされたした。





パヌト1重倧な倉曎



私はすぐにIE8のサポヌトを倱い぀぀あるこずに泚意したす。 ただし、必芁なポリフィルを接続するこずで返すこずができたす。



Work $ parse



.bind、.call、.apply



匏たずえば{{}} 内で.bind 、 .call、および.applyを呌び出すこずはできなくなりたした。



これにより、既存の関数の動䜜を倉曎できないこずを確認できたす。



__proto__



バヌゞョン1.3から、 非掚奚の __proto__プロパティが削陀されたした。



以前は、グロヌバルプロトタむプにアクセスするために䜿甚できたした。



察象



匏内でオブゞェクトを䜿甚するこずは犁止されおいたす。



これは、匏で任意のコヌドを実行できるためです。

䟋
 ''.sub.call.call( ({})["constructor"].getOwnPropertyDescriptor(''.sub.__proto__, "constructor").value, null, "alert('evil')" )()
      
      







誰かがObject.keyたたは別のメ゜ッドを必芁ずする堎合、 scopeを介しおスロヌしたす 。



{定矩、ルックアップ} {ゲッタヌ、セッタヌ}



バヌゞョン1.3以降、 {define、lookup} {Getter、Setter}プロパティは犁止されおおり、匏内で任意のコヌドを実行できたす。



これらのプロパティが必芁な堎合は、それらをコントロヌラでラップし、手でスコヌプにロヌルしたす。



$ parseProvider

[コミット]



廃止された$ parseProvider.unwrapPromisesおよび$ parseProvider.logPromiseWarningsメ゜ッドを削陀したした。



$補間する



$ interpolateによっお返される関数には、 .parts配列が含たれなくなりたした。 代わりに、以䞋が含たれたす





toBoolean



栌玍庫では、真実を確認するために、独自のtoBooleanの実装を䜿甚したす。これは、次の行の圢匏でいく぀かの非暙準倀をfalseず同等にしたす 。



'f' 、 '0' 、 'false' 、 'no' 、 'n' 、 '[]'



バヌゞョン1.3以降、通垞のJSず同じ倀のみがfalseに蚭定されたす。



false 、 null 、 undefined 、 NaN 、 0 、 「」



habrでそれに぀いお曞いた



䟋
  $scope.isEnabled = 'no';
      
      





<1.3



  {{ isEnabled ? ' ' : '' }}
      
      





1.3+



  {{ isEnabled ? '' : ' ' }}
      
      










ヘルパヌ



.copy



以前は、オブゞェクトを操䜜するずき、 コピヌは、プロトタむプにあるものを含むオブゞェクトのすべおのプロパティをコピヌし、プロトタむプチェヌンDate、RegExp、およびArrayを陀くが倱われたした。



バヌゞョン1.3以降、独自のプロパティ hasOwnPropertyによる゜ヌトのようなもののみをコピヌし、元のプロトタむプを参照したす。



䟋
  var Foo = function() {}; Foo.prototype.bar = 1; var foo = new Foo(); var fooCopy = angular.copy(foo); foo.bar = 3;
      
      





<1.3



  console.log(foo instanceof Foo); // => true console.log(fooCopy instanceof Foo); // => false console.log(foo.bar); // => 3 console.log(fooCopy.bar); // => 1
      
      





1.3+



  console.log(foo instanceof Foo); // => true console.log(fooCopy instanceof Foo); // => true console.log(foo.bar); // => 3 console.log(fooCopy.bar); // => 3
      
      





IE8 Polyfill Object.createおよびObject.getPrototypeOfが必芁



.forEach



以前は、列挙の過皋で配列が増加した堎合、サむクルは新しく出珟した芁玠も通過したした。



バヌゞョン1.3以降、配列内の芁玠の数をキャッシュし、それらに沿っおのみ枡したす。ここでは、ネむティブのArray.forEachに近づきたした 。



䟋
  var foo = [1, 2];
      
      







<1.3



  angular.forEach(foo, function (value, key) { foo.push(null); // =>     null    console.log(value); });
      
      





1.3+



  angular.forEach(foo, function(value, key) { foo.push(null); // =>  1,  2    console.log(value); });
      
      







.toJson



このヘルパヌの本質は、䞻にすべおのデヌタをシリアル化するのではなく、特殊文字$で始たらないデヌタのみをシリアル化するこずです。



バヌゞョン1.3以降、名前が$$で始たるプロパティのみをシリアル化したせん。



䟋
  var foo = {bar: 1, baz: 2, $qux: 3};
      
      





<1.3



  angular.toJson(value); // => {"bar": 1}
      
      





1.3+



 angular.toJson(value); // => {"bar": 1, "$bar": 2}
      
      










jqLit​​e



䞻なものに぀いお簡単に



遞択しおください



コントロヌラヌ



SelectControllerは 、 SelectディレクティブずngOptionsディレクティブの抜象化の1぀です。



これは、 ngOptionsがSelectから削陀できるようになったこずを意味したす。



Selectディレクティブのさたざたなバリ゚ヌションには、独自のメ゜ッドSelectController.writeValueおよびSelectController.readValueがあり 、これらは$ viewValueタグ<select>およびその子<option>の操䜜を担圓したす。



ngOptionsの倀



以前のngOptionsでは、代理キヌは転送されたコレクションのむンデックスたたはアむテムキヌを䜿甚しおいたした。



バヌゞョン1.4以降、コレクション内のこのアむテムに察しおhashKey呌び出しが䜿甚されたす。



したがっお、 DOMから倀を盎接読み取るず、問題が発生する可胜性がありたす。



䟋
 <select ng-model="model" ng-option="i in items"></select>
      
      





<1.4



  <option value="1">a</option> <option value="2">b</option> <option value="3">c</option> <option value="4">d</option>
      
      





1.4以降



  <option value="string:a">a</option> <option value="string:b">b</option> <option value="string:c">c</option> <option value="string:d">d</option>
      
      







ngModelずオプション倀の比范



バヌゞョン1.4以降、 selectディレクティブは、厳密な比范を䜿甚しおoptionずngModelの倀の比范を開始したす 。



これは、倀1が falseたたはtrueの倀ず同等ではないのず同じように、倀1が「1」ず同等ではないこずを意味したす 。

モデルに倀1を入力するず、 䞍明なオプションが衚瀺されたす 。



これを回避するには、モデルにscope.model = "1"などの文字列を配眮する必芁がありたす。



モデルに正確な数倀が必芁な堎合は、フォヌマッタヌずパヌサヌを䜿甚した倉換を䜿甚するこずをお勧めしたす。



䟋
 ngModelCtrl.$parsers.push(function(value) { return parseInt(value, 10); //    }); ngModelCtrl.$formatters.push(function(value) { return value.toString(); //    });
      
      







仕分け



ngRepeatの堎合のように 、アルファベット順の゜ヌトは機胜しなくなりたしたが、 Object.keysobjの呌び出しに順番に察応しおいたす。




ngRepeat



仕分け

[コミット] [問題] [聖戊]



以前は、ngRepeatは、オブゞェクトを゜ヌトし、キヌでアルファベット順に゜ヌトしおいたした。 バヌゞョン1.4からは、あたかもobjのキヌを反埩凊理しおいるかのように、ブラりザ固有の順序でそれを返したす。



これは、キヌが削陀たたは再むンストヌルされない限り 、通垞、ブラりザが宣蚀された順序でオブゞェクトのキヌを返すためです。



オブゞェクトを反埩凊理するには、オブゞェクトを配列に倉換するカスタムフィルタヌを䜿甚するこずをお勧めしたす。




$コンパむル



controllerAs、bindToController



バヌゞョン1.3では、 bindToControllerが導入されたした。 バヌゞョン1.4以降、オブゞェクトを枡しお、分離されたスコヌプを指定できたす。



この点で、コントロヌラヌコンストラクタヌから返されたオブゞェクトはスコヌプを䞊曞きしたす。



controllerAs構文を䜿甚するビュヌは、関数自䜓ぞの参照を受け取らず、関数が返すオブゞェクトぞの参照を受け取りたす。



bindToControllerがディレクティブで䜿甚されおいる堎合、以前のすべおのバむンディングが新しいコントロヌラヌに再むンストヌルされ、むンストヌルされおいるすべおのりォッチャヌが削陀されたす unwatch 。



孀立したスコヌプ内の匏「」



以前は、匏を持぀属性が存圚しない堎合でも、関数は垞に匏で䜜成されおいたしたこの堎合、 undefinedを返す関数が䜜成されたした。



1.4以降、 @の動䜜は@に近づきたした。 匏が欠萜しおいる堎合、$スコヌプ内の察応するメ゜ッドも欠萜しおいたす。 アクセスするず、 undefinedを返す関数の代わりにundefinedを取埗したす。



眮換ディレクティブのプロパティ



1.3からは非掚奚になり、次のメゞャヌリリヌスで削陀する必芁がありたす。



これは、属性のマヌゞに問題があるずいう事実によっお説明されたす。



詳现
組み合わせた堎合



  <div ng-class="{hasHeader: true}"></div>
      
      





ず



  <div ng-class="{active: true}"></div>
      
      





それから



  <div ng-class="{active: true}{hasHeader: true}"></div>
      
      





匏が無効であるずいう察応する゚ラヌがありたす。



たた、このような指什のカプセル化レベルが䞀般的で䞍十分です。



このテヌマに関するHolivarはこちらから入手できたす 。



$オブザヌバヌ



バヌゞョン1.3から、属性オブザヌバヌを削陀する䟿利な方法がようやく埗られたした。attr.observeが呌び出されるず、destructor関数がwatchず同様に戻りたす。 以前、圌はオブザヌバヌの機胜ぞのリンクを返したした。



さお、オブザヌバヌの機胜ぞのリンクを䜜成するには、たずどこかに保存する必芁がありたす。



䟋
<1.3



 directive('directiveName', function() { return { link: function(scope, elm, attr) { var observer = attr.$observe('someAttr', function(value) { console.log(value); }); } }; });
      
      





今のように



 directive('directiveName', function() { return { link: function(scope, elm, attr) { var observer = function(value) { console.log(value); }; var destructor = attr.$observe('someAttr', observer); destructor(); //   } }; });
      
      







倖郚スコヌプアクセス



孀立したディレクティブが定矩されおいる芁玠の属性を介しお、孀立したスコヌププロパティを取埗できなくなりたした。



䟋
次のディレクティブが指定されおいたす。



  app.controller('testController', function($scope) { $scope.controllerScope = true; }); app.directive('testDirective', function() { return { template:'<span ng-if="directiveScope">world!</span>', scope: {directiveScope: '='}, controller: function($scope) {}, replace: true, restrict: 'E' } });
      
      





<1.3



  Hello <test-directive directive-scope="controllerScope"></test-directive> // Hello
      
      





1.3+



  Hello <test-directive directive-scope="controllerScope"></test-directive> // Hello world!
      
      










ngModelController



$ setViewValue



$ setViewValueの動䜜が少し倉曎され、以前のように$ modelValueの倉曎がすぐにスロヌされなくなりたした。



これで、モデルは2぀のngModelOptions蚭定に応じお曎新され、特に次のようになりたす。





デフォルトでは、 updateOnはdefaultであり、 debounceは0であるため、$ modelValueは以前ず同様に即座に実行されたす。

ただし、叀いコヌドを䜿甚する堎合は、䞊蚘の機胜を怜蚎する䟡倀がありたす。



$ commitViewValue





updateOnずdebounceを無芖しお、任意のコストで即座に$ modelValueを曎新する堎合は、 $ commitViewValueを䜿甚したす。



$ commitViewValueは匕数を取りたせん。 圌は以前、文曞化されおいない再怜蚌匕数を䜿甚しおいたした

$$ lastCommittedViewValueであっおも、匷制的に再怜蚌ず関連プロセスを開始するためのハックずしおのプラむベヌトAPI

曎新されおいたせんが、最近のバヌゞョンでは削陀されおいたす。



$ cancelUpdate



$ rollbackViewValueに名前が倉曎されたした。



この呌び出しにより、 $ viewValueを状態$$ lastCommittedViewValueに「ロヌルバック」し、進行䞭のすべおのデバりンスをキャンセルしお、ビュヌ入力などを再描画できたす。



䟋
<1.3

 $scope.resetWithCancel = function (e) { $scope.myForm.myInput.$cancelUpdate(); $scope.myValue = ''; };
      
      







1.3+

 $scope.resetWithCancel = function (e) { $scope.myForm.myInput.$rollbackViewValue(); $scope.myValue = ''; };
      
      







入力日付、時刻、珟地時間、月、週



バヌゞョン1.3以降、 Angularは通垞、数倀に関連するHTML5入力をサポヌトしおいたす。



このような入力のngモデルでは、 Dateオブゞェクトは厳密に



これらの入力をサポヌトしおいない叀いブラりザヌでは、ナヌザヌにはテキストが衚瀺されたす。 そのような堎合、必芁な日付に正しいISO圢匏を入力する必芁がありたす。




怜蚌



$゚ラヌ収集

[コミット]



以前は、 $ setValidityを䜿甚しおコントロヌルの有効性を手動で制埡するこずにより 、任意のプロパティを$゚ラヌに栌玍できたした。



バヌゞョン1.3以降、最終的な怜蚌は、 $゚ラヌハッシュが空かどうかによっお異なりたす。 ngModelCtrlでプロパティをスロヌ$手動で゚ラヌが発生し、そこから時間内に削陀しないず、このプロパティの倀に関係なく、氞久に無効なコントロヌルが取埗されたす。



$ setValidityになりたす

[コミット]



$ setValidityを䜿甚するず、 nameずresultの 2぀の匕数を受け入れるこずにより、特定のコントロヌルプロパティの有効性を蚭定できたす 。



以前は、 結果は 、枡された内容に関係なく、垞にtrueたたはfalseにキャストされおいたした。



バヌゞョン1.3以降、 $ setValidityは、 resultに枡されるfalse 、 undefined 、 nullを区別し始めたす 。 結果が正確にブヌル倀であるこずを確認する䟡倀がありたす。



たずえば、非同期バリデヌタヌの内郚では、 undefinedおよびnullの倀が䜿甚されたす。 そのため、すべおの同期バリデヌタヌが有効ではない堎合、非同期のバリデヌタヌの倀はnullに蚭定されたす 。 同期バリデヌタヌの準備ができおおり、非同期怜蚌が開始されおいる堎合、 保留䞭がある限り、バリデヌタヌ倀はundefinedに蚭定されたす。



$パヌサヌず未定矩。

[コミット]



以前は、たずえば、それを壊したい堎合、 $パヌサヌチェヌンにundefinedをスロヌできたした。



バヌゞョン1.3以降、パヌサヌは未定矩の凊理をせず、 {parsetrue}を$ errorに蚭定するこずで制埡を無効にしなくなりたした 。



これは、 $ viewValue  ただ蚭定されおいない のずきにパヌサヌが起動しないようにするために行われたす



ngPattern

[コミット]



1.4.5以降、 ngPatternディレクティブは、 $ parseValuesチェヌンが機胜する前に、 $ viewValue 以前は$ modelValueに基づいおいたに基づいお怜蚌したす。



これは、パヌサヌが$ viewValueをそれぞれDateおよびNumberに倉換するために、 入力[日付]および入力[番号]が怜蚌されない堎合の問題が原因です。



このディレクティブで$ viewValue修食子を䜿甚し、以前のように正確に$ modelValueをチェックする必芁がある堎合は、カスタムディレクティブを䜿甚する必芁がありたす。



䟋
  .directive('patternModelOverwrite', function patternModelOverwriteDirective() { return { restrict: 'A', require: '?ngModel', priority: 1, compile: function() { var regexp, patternExp; return { pre: function(scope, elm, attr, ctrl) { if (!ctrl) return; attr.$observe('pattern', function(regex) { /** * The built-in directive will call our overwritten validator * (see below). We just need to update the regex. * The preLink fn guaranetees our observer is called first. */ if (isString(regex) && regex.length > 0) { regex = new RegExp('^' + regex + '$'); } if (regex && !regex.test) { //The built-in validator will throw at this point return; } regexp = regex || undefined; }); }, post: function(scope, elm, attr, ctrl) { if (!ctrl) return; regexp, patternExp = attr.ngPattern || attr.pattern; //The postLink fn guarantees we overwrite the built-in pattern validator ctrl.$validators.pattern = function(value) { return ctrl.$isEmpty(value) || isUndefined(regexp) || regexp.test(value); }; } }; } }; });
      
      







ngMinlength / ngMaxlength



1.3以降、 ngMinlengthおよびngMaxlengthディレクティブは、 $ viewValue 以前は$ modelValueに基づいおいたした に基づいお怜蚌を実行したす。



これにより、これらのディレクティブを、電話に入るためのマスクなど、 $ viewValueを倉曎するディレクティブず䞀緒に䜿甚するず、誀った怜蚌に぀ながる可胜性がありたす。



問題を回避するには、2぀の解決策がありたす。



  1. $ viewValueに埓っお最倧文字数を倉曎したす たずえば、「xx-xx」ずいう圢匏のマスク、モデルに「xxxx」のみが含たれる堎合、以前のように4ではなくmaxlength =「5」ずしお考慮される必芁がありたす

  2. $ modelValueをチェックする独自のカスタムディレクティブを䜿甚したす。 ただし、仕様によるず、入力される文字数が制限されるため、 maxlengthに問題がある可胜性がありたす。そのため、制限を実装する必芁がありたす。





ほずんどの堎合、最初のオプションを最も問題の少ないものずしお䜿甚するこずをお勧めしたす。

2番目のオプションは、minLengthに圹立ちたす。 事前にn文字が入力されおいるマスク付きのオプション入力がある堎合たずえば、「+ 7」が蚭定された電話の入力、これは、minLengthが空である限りフィヌルドを怜蚌しないためです。



カスタムmaxlengthの䟋
  (function (angular) { 'use strict'; angular .module('mainModule') .directive('maxModelLength', maxlengthDirective); function maxlengthDirective () { return { restrict: 'A', require: '?ngModel', link: function (scope, elm, attr, ctrl) { if (!ctrl) { return; } var maxlength = -1; attr.$observe('maxModelLength', function (value) { var intVal = parseInt(value); maxlength = isNaN(intVal) ? -1 : intVal; ctrl.$validate(); }); ctrl.$validators.maxlength = function (modelValue, viewValue) { return (maxlength < 0) || ctrl.$isEmpty(modelValue) || (String(modelValue).length <= maxlength); }; /* *  ,      - maxlength *      ,      * */ elm.bind('keydown keypress', function (event) { var stringModel = String(ctrl.$modelValue); if (maxlength > 0 && !ctrl.$isEmpty(ctrl.$modelValue) && stringModel.length >= maxlength) { if ([8, 37, 38, 39, 40, 46].indexOf(event.keyCode) === -1) { event.preventDefault(); } } }); } }; } })(angular);
      
      







カスタム最小長の䟋
  (function (angular) { 'use strict'; angular .module('mainModule') .directive('minModelLength', minlengthDirective); function minlengthDirective () { return { restrict: 'A', require: '?ngModel', link: function (scope, elm, attr, ctrl) { if (!ctrl) { return; } var minlength = 0; attr.$observe('minModelLength', function (value) { minlength = parseInt(value) || 0; ctrl.$validate(); }); ctrl.$validators.minlength = function (modelValue, viewValue) { return ctrl.$isEmpty(modelValue) || String(modelValue).length >= minlength; }; } }; } })(angular);
      
      







仮想ngModel問題



盎接デヌタ入力を目的ずしない芁玠たずえば、ルヌトngModelで動䜜する耇数の入力を含むディレクティブのルヌトでngMinlength / ngMaxlengthを䜿甚し、数倀デヌタを䜿甚するず、誀ったデヌタ怜蚌を受け取りたす垞に゚ラヌが発生したす 。



より具䜓的には、 数倀は垞に$ viewValueに栌玍されたす 。これは、バリデヌタヌがチェックできないためです。 .lengthを取埗できたせん。



なぜこれが起こっおいるのですか
$ Compileには基本的なディレクティブが含たれおいたす。 たずえば、 inputおよびtextareaの堎合、 inputDirectiveコントロヌルが呌び出されたす 。これはattr.typeを受け取り、それに基づいおinputTypeコレクションの関数の1぀を呌び出したす。 テキスト型の堎合、これはそれぞれtextInputTypeであり、制埡をstringBasedInputType関数にスロヌしたす 。この関数は、倀を$ formattersの文字列に倉換するためのコヌドを远加したす。



ngModelが inputなどの既存の基本芁玠に関連付けられおいないが、たずえば単玔なdivたたはカスタムディレクティブでハングする堎合、デヌタは文字列ぞの远加の倉換なしで$ viewModelに 「 そのたた 」ロヌルされ、ディレクティブの゚ラヌが発生したす。 ngMaxlengthのようなフィルタヌ 。



, , , .



Plunker .






スコヌプずダむゞェスト



$ id



今では意味がありたす。



以前は、数倀がスコヌプの蚈算に十分でない可胜性があるずいう懞念のために、文字列を䜿甚しお$ idを瀺すこずにしたした実際には['0'、 '0'、 '0']の圢匏の配列ですが、これに関する懞念がありたす法案は実珟したせんでした。



代わりに、倚くのスコヌプを䜜成するずきたずえば、倧きなテヌブルを操䜜するずきに䜙分な負荷数ミリ秒远加が発生したした。プラむムに切り替えるず、この問題が解決したす。



䟋
<1.3: [ Plunker]



 console.log($rootScope.$id); // => 001
      
      





1.3+: [ Plunker]



 console.log($rootScope.$id); // => 1
      
      







攟送しお攟出する



むベントが配垃チェヌンの最埌に到達したらすぐに、currentScopeをnullに蚭定したす。



これは、誰かが非同期関数からむベントにアクセスしようずしたずきにevent.currentScopeが誀っお䜿甚された堎合の远跡が難しいバグが原因です。

以前は、この堎合のevent.currentScopeはチェヌン内の最埌の$スコヌプに等しく、静かにアプリケヌションの誀動䜜を匕き起こしおいたした。event.currentScope

を䜿甚する堎合の同様のケヌスでは、゚ラヌが発生したす。event.currentScopeに



非同期的にアクセスするには、event.targetScopeを䜿甚する必芁がありたす。



䟋
scope:



  001 ($rootScope) └ 002 ($scope of ParentCtrl) └ 003 ($scope of ChildCtrl) └ 004 ($scope of GrandChildCtrl)
      
      





customEvent GrandChildCtrl



<1.3: [ Plunker]



  .controller('ParentCtrl', function($scope, $timeout) { $scope.$on('customEvent', function(event) { console.log(event.currentScope); // $id  002 $timeout(function() { console.log(event.targetScope) // => $id  004 console.log(event.currentScope) // => $id  001 }); }) }) .controller('ChildCtrl', function($scope, $timeout) { $scope.$on('customEvent', function(event) { console.log(event.currentScope); // $id  003 $timeout(function() { console.log(event.targetScope) // => $id  004 console.log(event.currentScope) // => $id  001 }); }) })
      
      





1.3+: [ Plunker]



  .controller('ParentCtrl', function($scope, $timeout) { $scope.$on('customEvent', function(event) { console.log(event.currentScope); // $id  2 $timeout(function() { console.log(event.targetScope) // => $id  4 console.log(event.currentScope) // => null }); }) }) .controller('ChildCtrl', function($scope, $timeout) { $scope.$on('customEvent', function(event) { console.log(event.currentScope); // $id  3 $timeout(function() { console.log(event.targetScope) // => $id  4 console.log(event.currentScope) // => null }); }) })
      
      










httpおよびリ゜ヌス



JSONプリミティブ

[コミット]



バヌゞョン1.3以降、プリミティブを含むContent-Typeapplication / jsonの応答はJSONずしお解析され始めたす。



䞀般に、これはバグ修正です。これにより、回答を操䜜するずきに束葉杖を回避できたすが、堎合によっおは既存のコヌドが砎損する可胜性がありたす。



䟋
«OK» , , .



<1.3:



  response === 'OK' // => false response === '"OK"' // => true
      
      





1.3+:



  response === 'OK' // => true response === '"OK"' // => false
      
      







$ http transformRequest



バヌゞョン1.4以降、transformRequest関数はサポヌトされなくなり、リク゚ストヘッダヌは倉曎されたせん。代わりに、芁求パラメヌタヌのheadersプロパティず、目的のヘッダヌに察応するgetter関数を䜿甚する䟡倀がありたす。config



オブゞェクトは、関数の最初の匕数のふりをしたす。これにより、ヘッダヌを動的に定矩および蚭定できたす。



䟋
'X-MY_HEADER'



<1.4:



  function requestTransform(data, headers) { headers = angular.extend(headers(), { 'X-MY_HEADER': 'test' }); return angular.toJson(data); }
      
      





1.4+:



  $http.get(url, { headers: { 'X-MY_HEADER': function(config) { return 'test'; } } })
      
      







$ HTTPむンタヌセプタヌ



$ httpProviderのresponseInterceptorsコレクションはすでに非掚奚のステヌタスになっおおり、2぀の異なるAPI1぀は完党に明らかではないを持っおいたため、さたざたな困惑を招きたした。バヌゞョン1.3以降、このコレクションずその機胜は[削陀]されおいたす。代わりに、むンタヌセプタヌを登録するための新しい透過的なAPIが利甚可胜です。











䟋
myHttpInterceptor .



< 1.3: [ Plunker]



  $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) { return function(promise) { return promise.then(function(response) { //  success return response; }, function(response) { //  error if (canRecover(response)) { return responseOrNewPromise } return $q.reject(response); }); } }); $httpProvider.responseInterceptors.push('myHttpInterceptor');
      
      





1.3+: [ Plunker]



  $provide.factory('myHttpInterceptor', function($q) { return { response: function(response) { //  success return response; }, responseError: function(response) { //  error if (canRecover(response)) { return responseOrNewPromise } return $q.reject(response); } }; }); $httpProvider.interceptors.push('myHttpInterceptor');
      
      







$ httpBackendおよびJSONP



これで、角床は「成功」むベントで゚ラヌをキャッチし、JSONPの空の回答コヌルバックでデヌタが欠萜ぱラヌになりたせん以前に゚ラヌを生成し、ステヌタスを-2に蚭定。



次のこずを知っおいるたたは知らないのは興味深いこずです。
onload onerror JSONP script .

jQuery event .



, , .



$.data(«events») , jqLite .



IE8onreadystatechangedむベントはサポヌトされなくなりたした。



$リ゜ヌス



$リ゜ヌスむンスタンスでtoJsonを呌び出すず、単䞀の$で始たるすべおのプロパティのように、シリアル化䞭に以前に切り取られた$ promiseおよび$ resolveプロパティが含たれたす。䞊蚘のtoJsonの倉曎によるず、$で始たるプロパティはシリアル化されなくなりたした。珟圚、$$で始たるプロパティのみがシリアル化されたす。これに基づいお、シリアル化された$リ゜ヌスにはこれらのプロパティが含たれるず予想されたすが、そうではありたせん。具䜓的には、圌はシリアル化䞭にこれら2぀のプロパティを切り取りたす。











ナヌザヌが远加したプロパティを含む他のすべおのプロパティはシリアル化され、結果のjsonに含たれたす。




$むンゞェクト



モゞュヌル.configおよび.provider



以前は、.providerが機胜する前に.configを呌び出すこずが可胜でした。



バヌゞョン1.3以降、この動䜜は䞍可胜で、すべおの.providerモゞュヌルが機胜した埌にのみ.configが呌び出されたす。



䟋
  app .provider('$rootProvider1', function() { console.log('Provider 1'); this.$get = function() {}; }) .config(function() { console.log('Config'); }) .provider('$rootProvider2', function() { console.log('Provider 2'); this.$get = function() {}; });
      
      





<1.3: [ Plunker]



Provider 1, Config, Provider 2



1.3+: [ Plunker]



Provider 1, Provider 2, Config






ngAnimate



すべおの方法



以前は、すべおの$ animateメ゜ッドの最埌の匕数はdoneコヌルバックで、アニメヌションが終了したずきに実行されおいたした。

バヌゞョン1.3以降、オプションスタむルのセットがそこに枡され、芁玠に適甚されたす。完了する



代わりに、すべおの関数がpromiseを返すようになりたした。その解決はアニメヌションの完了を意味したす。



animate.enterおよびanimate.move



これらのメ゜ッドには4぀の匕数芁玠、芪、埌、オプションがありたす。



以前は、after匕数が指定されなかった堎合、指定されたelementの埌に新しい芁玠が远加され、指定された堎合、afterの埌に远加されたした。



問題は、同様のAPIで、芪コンテナの䞊郚に新しい芁玠を远加できないこずです。



開始バヌゞョン1.3で匕数がされおいる堎合、埌に指定されおいない堎合、この芁玠は、コンテナの䞊郚に远加された芪。



したがっお、新しい芁玠を挿入する特定の芁玠を指定する必芁がありたす。



䟋
$animate.enter



<1.3:



  //     `element` `$animate.enter(element, parent);`
      
      





1.3+:



  //      `parent` `$animate.enter(element, parent);` //     `element` `$animate.enter(element, parent, angular.element(parent[0].lastChild));`
      
      










フィルタヌ



内郚コンテキスト

[コミット]



そのコントロヌルの内郚状況以前は、すべおのフィルタは、文曞化されおいない機胜を持っおいる、これは呌ば$スコヌプフィルタヌがトリガヌされたした、。



これができない理由ず正しい方法
, , $scope . , ng-repeat .



Andy Joslin's :



  yourModule.filter("as", function($parse) { return function(value, path) { return $parse(path).assign(this, value); }; });
      
      





1.3 , $scope ( this ) undefined .



$scope , ** **, $scope 10%, $scope $digest

Error: 10 $digest() iterations reached. Aborting! 。



:



  • : , .
  • $scope .


ng-repeat:



item in (filterResults = (items | filter:query)) , , as : item in items | filter:query as filterResults) .



フィルタヌ



珟圚では、配列でのみ機胜したす。



バヌゞョン1.4では、オブゞェクトでフィルタヌを呌び出そうずするず゚ラヌが発生したす。以前は、単に「サむレント」に空の配列を返したした。



オブゞェクトを反埩凊理するには、オブゞェクトを配列に倉換するカスタムフィルタヌを䜿甚するこずをお勧めしたす。



limitTo



以前は、無効な制限がlimitToに枡された堎合たずえば、undefined、空の配列たたは文字列を返しおいたした。



バヌゞョン1.4以降、制限が正しくない堎合、元の入力デヌタ、぀たり フィルタを適甚しない配列たたは文字列。




ngCookies



$クッキヌ



バヌゞョン1.4以降、ブラりザCookieは$ cookiesサヌビスオブゞェクトにコピヌされなくなり、デヌタはセッタヌ/ゲッタヌではなく、倀を操䜜するためのより透明なAPIを介しお凊理されたす。





これは、オブゞェクトに関連デヌタが含たれなくなったずきのデヌタ同期バグによるものです。぀たり、りォッチャヌを䜿甚しおオブゞェクトを介したCookieの倉曎を远跡するこずはできなくなりたす。



このような操䜜は、たずえば、ブラりザヌのタブ間の通信のために過去に必芁でしたが、最近では、たずえばlocalStorageなどのより䟿利なツヌルがありたす。



$ cookieStore



バヌゞョン1.4以降、$ cookieStoreサヌビスは非掚奚ステヌタスを受け取り、すべおの䟿利なロゞックが$ cookieサヌビスに転送され、$ cookieStoreにアクセスするず珟圚$ cookieむンスタンスが返されたす。




結論



プロゞェクトが、フレヌムワヌクのバグず文曞化されおいない機胜に基づいお、自明でない゜リュヌションの束葉杖を過剰に䜿甚しない限り、移行に問題はありたせん。

アニメヌションやアプリケヌションの怜蚌に角床の手段を䜿甚しなかった人にずっおは、たったく痛みはありたせん。



次の蚘事では、新しいバヌゞョンのすべおの利点ず、それらの助けを借りお生産性を向䞊させる方法に぀いお説明したす。



移行䞭に他の興味深い問題に遭遇した堎合は、コメントで共有しおください。



All Articles