ããã«ã¡ã¯ãhabrachelovekiã
ãã®èšäºã§ã¯ã
AngularJSã
Knockoutãªã©ã®ãã¬ãŒã ã¯ãŒã¯ã§ã®ç§ã®çµéšãå
±æããããšæããŸãã
ãã®èšäºã¯ãJavaScriptã«ç²ŸéããŠãããèšåããããã¬ãŒã ã¯ãŒã¯ã®å°ãªããšã1ã€ã«ã€ããŠã¢ã€ãã¢ãæã¡ãåœç¶ãªããèŠéãåºããã人ã«ãšã£ãŠè峿·±ããã®ã«ãªããŸãã
埩ç¿
AngularJSãšKnockoutã®ã€ããªãã®ãŒã¯éåžžã«äŒŒãŠããŸãã ãããã¯åçWebã¢ããªã±ãŒã·ã§ã³ã®ãã¬ãŒã ã¯ãŒã¯ã§ãããHTMLããã³ãã¬ãŒããšããŠäœ¿çšããŸãã ã¢ããªã±ãŒã·ã§ã³ã®ã³ã³ããŒãã³ããããæç¢ºãã€ç°¡æœã«èšè¿°ããããã«ãHTMLæ§æãæ¡åŒµã§ããŸãã ããã«ãmodel-view-controller.AngularJSãšKnockoutã®éä¿¡ãå®è£
ããããã«ä»¥åã«äœæãããã³ãŒããèšè¿°ããå¿
èŠããªããªããŸã-ããã¯ãçŸä»£ã®Webã¢ããªã±ãŒã·ã§ã³ãäœæããããã«èšèšãããå Žåãåºæ¬çã«HTMLãšJavaScriptã§ãã HTMLã¯ãéçããã¥ã¡ã³ãçšã®åªãã宣èšåèšèªã§ãã ããããæ®å¿µãªãããææ°ã®Webã¢ããªã±ãŒã·ã§ã³ãäœæããããã«å¿
èŠãªãã®ã¯ããŸããããŸããã
ç¹åŸŽ
- ããŒã¿ãã€ã³ãã£ã³ã°ïŒUIãšããŒã¿ã¢ãã«ããªã³ã¯ããããã®ã·ã³ãã«ã§åªããæ¹æ³ã
- éçºè
åãã®åŒ·åãªããŒã«ã»ããïŒç¹ã«AngularJSã§ã¯ãKnockoutã®ã»ããã¯ããªã貧匱ã§ãïŒ
- ç°¡åã«æ¡åŒµå¯èœãªããŒã«ããã
ã¢ããªã±ãŒã·ã§ã³ã¢ãŒããã¯ãã£
ããã¥ã¡ã³ãã«ãããšãAngularã¯ã¢ããªã±ãŒã·ã§ã³ãã¢ãžã¥ãŒã«ã«åå²ããŠæ§é åããããšãææ¡ããŠããŸãã åã¢ãžã¥ãŒã«ã®æ§æã¯æ¬¡ã®ãšããã§ãã
- ã¢ãžã¥ãŒã«ãæ§æããæ©èœ-ã¢ãžã¥ãŒã«ãããŒãããçŽåŸã«éå§ããŸãã
- ã³ã³ãããŒã©ãŒ
- ãµãŒãã¹;
- ãã£ã¬ã¯ãã£ãã
Angularã®çè§£ã«ãããã³ã³ãããŒã©ãŒã¯ãããŒã¿ã¢ãã«ãæ§ç¯ãã颿°ã§ãã $ã¹ã³ãŒããµãŒãã¹ã¯ãã¢ãã«ã®äœæã«äœ¿çšãããŸãããããã«ã€ããŠããå°ã詳ãã説æããŸãã ãã£ã¬ã¯ãã£ãã¯HTMLã®æ¡åŒµæ©èœã§ãã
é çªã«ãKnockoutã¯ã¢ããªã±ãŒã·ã§ã³ãæ§ç¯ããModelViewã«åå²ããŸããModelViewã¯ãã¢ãã«ãšã³ã³ãããŒã©ãŒã®æ··åã§ãã ko.bindingHandlersãªããžã§ã¯ãå
ã«ã¯ãAngularãã£ã¬ã¯ãã£ãã«é¡äŒŒããããŒã¿ãã€ã³ãã£ã³ã°ããããŸãã ObservableãšobservableArrayã¯ãã¢ãã«ãšãã®è¡šçŸã®éã®é¢ä¿ãæ§ç¯ããããã«äœ¿çšãããŸãã
ã¢ãžã¥ãŒã«æ§ã«ã€ããŠèšãã°ãAMDãã³ãã¬ãŒã-éåæã¢ãžã¥ãŒã«å®çŸ©ãæãåºããŸããã AngularãšKnockoutã«ã¯ãç¬èªã®AMDãã³ãã¬ãŒãå®è£
ããããŸããã
RequireJSã©ã€ãã©ãªã䜿çšããããšããå§ãããŸãã 圌女ã¯ãAngularãšKnockoutã®äž¡æ¹ãšã®äºææ§ã«é¢ããŠéåžžã«ãã蚌æãããŠããŸãã ããã«é¢ããããè峿·±ãæ
å ±ã¯ã
http ïŒ
//www.kendoui.cââom/blogs/teamblog/posts/13-05-08/requirejs-fundamentals.aspxããã³
http://habrahabr.ru/post/152833/ã«ãããŸãã
ãã³ãã¬ãŒãäœæ
ïŒAngularJSéçºè
ã®ãã®ãããªçŸããåçã«æè¬ããŸãïŒçŸæç¹ã§ã¯ããã§ã«èšå€§ãªæ°ã®ãã³ãã¬ãŒããšã³ãžã³ããããŸãã ããšãã°ãjQueryãã³ãã¬ãŒãïŒæ®å¿µãªããããµããŒããããªããªããŸããïŒã ãããã®ã»ãšãã©ã¯ãéçãã³ãã¬ãŒããæååãšããŠåãåããããŒã¿ãšæ··åããæ°ããè¡ãäœæããinnerHTMLããããã£ã䜿çšããŠç®çã®DOMèŠçŽ ã«çµæã®æååã貌ãä»ããŸãã ãã®ãããªã¢ãããŒããšã¯ãããŒã¿ã倿ŽãããåŸã«æ¯åãã³ãã¬ãŒããåã¬ã³ããªã³ã°ããããšãæå³ããŸãã ãã®ã¢ãããŒãã«ã¯å€ãã®æ¢ç¥ã®åé¡ããããŸããããšãã°ããŠãŒã¶ãŒå
¥åã®èªã¿åããšã¢ãã«ãžã®æ¥ç¶ãäžæžãã«ãããŠãŒã¶ãŒããŒã¿ã®æå€±ãããŒã¿ããã¬ãŒã³ããŒã·ã§ã³ã®æŽæ°ããã»ã¹å
šäœã®ç®¡çãªã©ã§ãã ããã«ãç§ã®èãã§ã¯ããã®ã¢ãããŒãã¯çç£æ§ã«æªåœ±é¿ãåãŒããŸãã
AngularãšKnockoutã¯ç°ãªãã¢ãããŒããåããŸãã ããªãã¡ãåæ¹åãã€ã³ãã£ã³ã°ã ãã®ã¢ãããŒãã®ç¹åŸŽã¯ãããŒãžèŠçŽ ãšã¢ãã«èŠçŽ ã®åæ¹åéä¿¡ã®äœæã§ãã ãã®ã¢ãããŒãã«ãããããªãå®å®ããDOMãååŸã§ããŸãã Knockoutã§ã¯ãobservableããã³observableArray颿°ã䜿çšããŠåæ¹åéä¿¡ãå®è£
ãããŸãã ãã³ãã¬ãŒããåæããããã«ãjQuery HTMLããŒãµãŒã䜿çšãããŸãïŒæ¥ç¶ãããŠããå Žåããã以å€ã¯åæ§ã®ãã€ãã£ãããŒãµãŒïŒã äžèšã®é¢æ°ã®çµæã¯ãã¢ãã«èŠçŽ ã®çŸåšã®ç¶æ
ãã«ãã»ã«åããåæ¹åãã€ã³ãã£ã³ã°ãæ
åœãã颿°ã§ãã ç§ã®æèŠã§ã¯ããã®å®è£
ã¯ãã¢ãã«ã®ç¶æ
ã®ã³ããŒã«é¢é£ããåé¡ããããããããŸã䟿å©ã§ã¯ãããŸããã颿°ã¹ã³ãŒãã¯ã³ããŒãããªããããæåã«ã¢ãã«èŠçŽ ããããŒã¿ãååŸããå¿
èŠããããããã颿°ãšããŠåç
§ããŠããçµæãè€è£œããã ãã§ãã
Angularã§ã¯ãåæ¹åéä¿¡ã¯ã³ã³ãã€ã©ïŒ$ã³ã³ãã€ã«ãµãŒãã¹ïŒã«ãã£ãŠçŽæ¥æ§ç¯ãããŸãã éçºè
ã¯ãobservableãªã©ã®é¢æ°ã䜿çšããå¿
èŠã¯ãããŸããã ç§ã®æèŠã§ã¯ã远å ã®èšèšã䜿çšããå¿
èŠããªããã¢ãã«èŠçŽ ã®ç¶æ
ãã³ããŒãããšãã«åé¡ããªããããããã¯ã¯ããã«äŸ¿å©ã§ãã
AngularãšKnockoutã§ã®ãã³ãã¬ãŒããšã³ãžã³ã®å®è£
ã®äž»ãªéãã¯ãèŠçŽ ã®ã¬ã³ããªã³ã°æ¹æ³ã§ããAngularã¯DOMèŠçŽ ãçæããããã䜿çšããŸãã Knockout-æååãšinnerHTML-itãçæããŸãã ãããã£ãŠã倿°ã®èŠçŽ ãçæããã«ã¯ãKnockoutã®æéãããããŸãïŒè¯ãäŸã¯å°ãäœããªããŸãïŒã
ããŒã¿ã¢ãã«
Angularã®ããŒã¿ã¢ãã«ã«ã€ããŠèšãã°ã$ã¹ã³ãŒããµãŒãã¹ã§ééããªã忢ããå¿
èŠããããŸãã ãã®ãµãŒãã¹ã«ã¯ãããŒã¿ã¢ãã«ãžã®ãªã³ã¯ãå«ãŸããŠããŸãã Angularã¯ããªãè€éãªã¢ããªã±ãŒã·ã§ã³ã¢ãŒããã¯ãã£ãæ³å®ããŠããããã$ã¹ã³ãŒããããè€éãªæ§é ã«ãªã£ãŠããŸãã
åã¢ãžã¥ãŒã«å
ã§ã$ rootScopeã®åå«ã§ãã$ scopeã®æ°ããã€ã³ã¹ã¿ã³ã¹ãäœæãããŸãã ããã°ã©ã ã«ãããæ¢åã®ã€ã³ã¹ã¿ã³ã¹ãã$ scopeã®æ°ããã€ã³ã¹ã¿ã³ã¹ãäœæããããšãã§ããŸãã ãã®å Žåãäœæãããã€ã³ã¹ã¿ã³ã¹ã¯ããããäœæããã$ã¹ã³ãŒãã®çžç¶äººã«ãªããŸãã JavaScriptãçç¥ããŠãã人ãªããAngularã§$ã¹ã³ãŒãéå±€ãæ±ãã®ã¯ç°¡åã§ãã ãã®æ©èœã¯ããããã¢ãããªã©ã®ããŸããŸãªãŠã£ãžã§ãããäœæããå¿
èŠãããå Žåã«éåžžã«äŸ¿å©ã§ãã
ããŒã¿ãã€ã³ãã£ã³ã°
Knockoutã®ãã€ã³ãã£ã³ã°ãAngularã®ãã£ã¬ã¯ãã£ãã¯ãHTMLæ§æãæ¡åŒµãããããã€ãŸããã©ãŠã¶ãŒã«æ°ããããªãã¯ãæããããã«äœ¿çšãããŸãã ããŒã¿ãã€ã³ãã£ã³ã°ãšãã£ã¬ã¯ãã£ãã®æŠå¿µã«ã€ããŠã¯è©³ããåæããŸããã Knockoutã§ããŒã¿ãšãã¬ãŒã³ããŒã·ã§ã³ãšã®æ¥ç¶ã衚瀺ããã«ã¯ãããŒã¿ãã€ã³ãã£ã³ã°ãå¯äžã®æ¹æ³ã§ããããšã«æ³šæããŠãã ããã
ãã®åé¡ã«ã€ããŠã¯ãèšäºã§è©³ãã説æããŠããŸãã
AngularJSïŒ
http ://habrahabr.ru/post/164493/ãhttpïŒ//habrahabr.ru/post/179755/ãhttpïŒ
//habrahabr.ru/post/180365/KnockoutJSïŒ
http :
//www.knockmeout.net/2011/07/another-look-at-custom-bindings-for.htmlãŸããAngularã®ãã£ã«ã¿ãŒã®ååšã«ã€ããŠãèšåããããšæããŸãã ãã£ã«ã¿ã¯ãç»é¢ã«è¡šç€ºãããããŒã¿ããã©ãŒãããããããã«äœ¿çšãããŸãã æ®å¿µãªãããKnockoutã¯ãã¹ãŠã«ãã€ã³ãã£ã³ã°ã䜿çšããŸãã
äŸ
ãã§ãŒãã€ã³ã¢ãã¡ãŒã·ã§ã³
AngularJSïŒ http : //jsfiddle.net/yVEqU/var ocUtils = angular.module("ocUtils", []); ocUtils.directive('ocFadeIn', [function () { return { restrict: 'A', link: function(scope, element, attrs) { $(element).fadeIn("slow"); } }; }]); function MyCtrl($scope) { this.$scope = $scope; $scope.items = []; $scope.add = function () { $scope.items.push('new one'); } $scope.pop = function () { $scope.items.pop(); } }
ããã¯ã¢ãŠãïŒ http : //jsfiddle.net/fH3TY/ var MyViewModel = { items: ko.observableArray([]), fadeIn: function (element) { console.log(element); $(element[1]).fadeIn(); }, add: function () { this.items.push("fade me in aoutomatically"); }, pop: function () { this.items.pop(); } }; ko.applyBindings(MyViewModel, $("#knockout")['0']);
ãã®äŸãããç°¡åãªãã®ãèŠã€ããã®ã¯é£ãããšæããŸãããã¬ãŒã ã¯ãŒã¯ã®æ§æãå®å
šã«ç€ºããŠããŸãã
ãã§ãŒãã¢ãŠãã¢ãã¡ãŒã·ã§ã³
AngularJSïŒ http : //jsfiddle.net/SGvej/ var FADE_OUT_TIMEOUT = 500; var ocUtils = angular.module("ocUtils", []); ocUtils.directive('ocFadeOut', [function () { return { restrict: 'A', link: function(scope, element, attrs) { scope.$watch(attrs["ocFadeOut"], function (value) { if (value) { $(element).fadeOut(FADE_OUT_TIMEOUT); } }); } }; }]); function MyCtrl($scope, $timeout) { this.$scope = $scope; $scope.items = []; $scope.add = function () { $scope.items.push({removed: false}); } $scope.pop = function () { $scope.items[$scope.items.length - 1].removed = true; $timeout(function () { $scope.items.pop(); console.log($scope.items.length); }, FADE_OUT_TIMEOUT); } }
ããã¯ã¢ãŠãïŒ http : //jsfiddle.net/Bzb7f/1/ var MyViewModel = { items: ko.observableArray([]), fadeOut: function (element) { console.log(element); if (element.nodeType === 3) { return; } $(element).fadeOut(function () { $(this).remove(); }); }, add: function () { this.items.push("fade me in aoutomatically"); }, pop: function () { this.items.pop(); } }; ko.applyBindings(MyViewModel, $("#knockout")['0']);
ãã®äŸã¯åã®äŸã»ã©è€éã§ã¯ãããŸããããããã€ãã®ãã¥ã¢ã³ã¹ããããŸãã
Angularã®å ŽåãDOMèŠçŽ ã¯ãã®ã¢ãã«èŠçŽ ã«é¢é£ä»ããããŠãããèŠçŽ ãåé€ããããšããã«åé€ããããããèŠçŽ ãåé€ããåã«fadeOutãå®è¡ããå¿
èŠããããŸãã ãŸããé
åããã¢ãã«èŠçŽ ãåé€ããã«ã¯ã$ã¿ã€ã ã¢ãŠããµãŒãã¹ã䜿çšããå¿
èŠãããããšã«æ³šæããããšãéèŠã§ãã ãã®ãµãŒãã¹ã¯ãæ¬è³ªçã«setTimeout颿°ã®ã©ãããŒã§ãããããŒã¿ã¢ãã«ã®æŽåæ§ãä¿èšŒããŸãã
ããã¯ã¢ãŠãã«ã¯å¥ã®åé¡ããããŸãã fadeOut颿°ã¯ãæåã®åŒæ°ãšããŠããã®ã¢ãã«èŠçŽ ã«é¢é£ããDOMèŠçŽ ã®é
åãåãåããŸãã å¥åŠãªç¶æ³äžã§ã¯ãã¬ã³ããªã³ã°ããã»ã¹äžã«ãã³ãã¬ãŒããäœæãããããšããããŸãããããã£ãŠãçµæã®é
åã«ãã³ãã¬ãŒããååšãããããfadeOutãå®è¡ããåã«èŠçŽ ã確èªããå¿
èŠããããŸãã ãŸããfadeOutããã»ã¹ã®æåŸã«ãDOMèŠçŽ ãåé€ããããšãå¿ããªãã§ãã ããïŒãããã¯èªåçã«åé€ãããŸããïŒã
ãããã¢ãã
AngularJSïŒ http ://jsfiddle.net/vmuha/EvvY7/ãhttpïŒ //angular-ui.imtqy.com/bootstrap/ ïŒ2çªç®ã®ãªã³ã¯ã§ã¯ãå€ãã®åªããæçšãªãœãªã¥ãŒã·ã§ã³ãèŠã€ãããŸãïŒ
var ocUtils = angular.module("ocUtils", []); function MyCtrl($scope, $compile) { var me = this; this.$scope = $scope; $scope.open = function (data) { var popupScope = $scope.$new(); popupScope.data = data; me.popup = $("<div class=\"popup\">{{data}}<br /><a href=\"#\" ng-click=\"close($event)\"> Close me</a></div>"); $compile(me.popup)(popupScope); $("body").append(me.popup); } $scope.close = function () { if (me.popup) { me.popup.fadeOut(function () { $(this).remove(); }); } } }
ããã¯ã¢ãŠãïŒ http : //jsfiddle.net/vmuha/uwezZ/ãhttp ïŒ //jsfiddle.net/vmuha/HbVPp/ var jQueryWidget = function(element, valueAccessor, name, constructor) { var options = ko.utils.unwrapObservable(valueAccessor()); var $element = $(element); setTimeout(function() { constructor($element, options) }, 0); //$element.data(name, $widget); }; ko.bindingHandlers.dialog = { init: function(element, valueAccessor, allBindingsAccessor, viewModel) { console.log("init"); jQueryWidget(element, valueAccessor, 'dialog', function($element, options) { console.log("Creating dialog on " + $element); return $element.dialog(options); }); } }; ko.bindingHandlers.dialogcmd = { init: function(element, valueAccessor, allBindingsAccessor, viewModel) { $(element).button().click(function() { var options = ko.utils.unwrapObservable(valueAccessor()); $('#' + options.id).dialog(options.cmd || 'open'); }); } }; var viewModel = { label: ko.observable('dialog test') }; ko.applyBindings(viewModel);
ãããã¢ãããå®è£
ããã«ã¯å€ãã®æ¹æ³ããããŸãã ãã£ã¬ã¯ãã£ããŸãã¯ãã€ã³ãã£ã³ã°ãéããŠãViewModelãŸãã¯ã¢ãžã¥ãŒã«ã®äžéšãšããŠã
Angularã§ã¯ãäžèšã§èª¬æããããã«ããããã¢ããã¯$ã¹ã³ãŒãã®æ°ããã€ã³ã¹ã¿ã³ã¹ãäœæãã$ã³ã³ãã€ã«ãµãŒãã¹ã䜿çšããŠãã³ãã¬ãŒããã³ã³ãã€ã«ããå¿
èŠããããŸãã
Knockoutã§ã¯ãæ°ããModelViewãäœæããapplyBindings颿°ãåŒã³åºããŠã¢ãã«ãšãã¥ãŒãæ¥ç¶ããå¿
èŠããããŸãããããã¢ããçšã®æ°ããããŒã¿ã¢ãã«ãäœæãããšãKnockoutããããã¢ãããã³ãã¬ãŒããã$ rootModelã«ã¢ã¯ã»ã¹ããéã«åé¡ãçºçããããšã«æ³šæããŠãã ããã Knockoutã®ããŒã¿ã¢ãã«ã®éå±€ã¯ããããDOMèŠçŽ äžã«æ§ç¯ãããŸãããããã¢ããã³ã³ãããŒãã¢ããªã±ãŒã·ã§ã³ã®ã³ã³ãããŒã®å€åŽã«ããå Žåããããã¢ããã¯$ rootModelã«ã¢ã¯ã»ã¹ã§ããŸããã
äŸ¡æ Œã®ãã©ãŒããã
AngularJSïŒ http : //jsfiddle.net/vmuha/k6ztB/1/ããã¯ã¢ãŠãïŒ http : //jsfiddle.net/vmuha/6yqDw/æ§èœ
ããã©ãŒãã³ã¹ã®åé¡ã«ç®ãåããŸãã 2ã€ã®ãã¹ããå®è¡ãããŸããããHello WorldïŒãã¢ããªã±ãŒã·ã§ã³ã®ã³ãŒã«ãã¹ã¿ãŒããš1000èŠçŽ ã®é
åã®ã¬ã³ããªã³ã°ã§ãã
ãã¹ãŠã®ãã€ã¢ã°ã©ã ã§ãåçŽæ¹å-ããªç§ãæ°Žå¹³æ¹åã«å®éšã®æ°ã

ããã§ã¯ãKnockoutã®ã³ãŒã«ãã¹ã¿ãŒããAngularã®ã³ãŒã«ãã¹ã¿ãŒããããã¯ããã«éãããšãæç¢ºã«ããããŸãã

ããããã¬ã³ããªã³ã°ã«é¢ããŠèšãã°ãAngularã¯æããã«ãã®åéã®ãªãŒããŒã§ãã 1000è¡ã®ã¬ã³ããªã³ã°ã§ãããããã«ãKnockoutã¯æå€§2.5ç§ããããŸãããAngularã¯ãã®ã¿ã¹ã¯ãå®äºããããã«500ããªç§æªæºã§ãã ããã«ãã¬ã³ããªã³ã°ãããèŠçŽ ããŠãŒã¶ãŒã®ç»é¢ã«è¡šç€ºããã®ã«ãããŸããŸãªæéãããããŸããAngularã§ã¯1ã3ç§ãKnockoutã§ã¯14ã20ç§ã§ãã ããã¯ãKnockoutãæååãçæããAngularãDOMèŠçŽ ãçæããããã§ãã
ãŸãšã
ç§ã«ãšã£ãŠã®äž»ãªè³ªåã¯ãAngularãšKnockoutã®ç¯å²ã決å®ããããšã§ããã ããã€ãã®ç°¡åãªå®éšã®åŸãç§ã¯æ¬¡ã®çµè«ãåºããŸããã
ããã¯ã¢ãŠãã¯ãè€éãªã¢ãŒããã¯ãã£ãè€éãªã¯ãŒã¯ãããŒãäœæããå¿
èŠããªãå Žåã«é©çšã§ããŸãã ãã®äž»ãªæ©èœã¯ãã¢ãã«ãšãã¥ãŒããªã³ã¯ããããšã§ãããããåçŽãªåäžããŒãžã®ã¢ããªã±ãŒã·ã§ã³ã«æé©ã§ãã ããšãã°ããã©ãŒã ã®è€éãã®ç°ãªãã¬ãã«ãäœæããŸãã
Angularã«é¢ããŠã¯ãRichUIã®äœæãå¿
èŠãªå Žåã«åœ¹ç«ã€ãšããçµè«ã«éããŸããã è€éãªã¢ãŒããã¯ãã£ãšè€éãªãªã³ã¯ãåããçã®å®å
šãª1ããŒãžã¢ããªã±ãŒã·ã§ã³ã
PSïŒ
ãã®èšäºãçããã«ãšã£ãŠè峿·±ããã®ã«ãªãããšãé¡ã£ãŠããŸãã ããªãã®ã³ã¡ã³ããã¬ãã¥ãŒã建èšçãªæ¹å€ãèªãã§ããããã§ãïŒ ã¿ãªããã®æ¥œããä»äºããç¥ãããŸãïŒ