بیایید با هم گوشه های جاوا اسکریپت رو کشف کنیم !
Angular.js یک فریمورک MV* جاوااسکریپت هست، *MV به معنی (مدل – نما – هر چیزی که لازم داریم) هست. که پشتش به گوگل گرمه و از برترین فریمورکها برای ایجاد اپلیکیشنهای تحت وب تک صفحهای یا SPA به شمار میاد و نمونه های موفق زیادی داره (با آی پی ایران قابل دسترسی نیست).
SPA از زبون ویکیپدیا اینطور تعریف میشه که :
برنامه تک صفحهای (SAP)
برنامهای تکصفحهای که آن را به اختصار از Single-page application نیز SPA میخوانند به برنامههای تحتوب و یا وبگاهایی گفته میشود که تنها دارای یک صفحه هستند. به واقع در این روش تمامی کدهای مورد نیاز (سمت-کاربر) در یک صفحه نوشته میشود. در این برنامهها دیگر نیازی به بارگذاری مجدد برای انجام برخی امور نیست و کدهای مورد نیاز یا در بارگذاری اولیه و یا در زمان نیاز با استفاده از ایجکس بارگذاری میشوند.
برای مثال در وبسایتی پس از کلیک کردن بر روی یک گزینه (“ارتباط با ما”)، یوآرال به شکلی شبیه به یوآرال زیر در میآید:
webapp.tld/#contact
یعنی در واقع contact# به انتهای آن اضافه میشود و بدون بارگذاری مجدد صفحه محتوای جدید نمایش داده میشود.
از معروفترین مثال های SPA میشه به نسخه وب جیمیل و امثال اون اشاره کرد. خب حالا که متوجه شدیم با چه فریمورک شریف یا به قول بعضی ها “جادوگر” اپلیکیشنهای کلاسیک وب روبرو هستیم، من میتونم تمام روز وقتم رو صرف این کنم که با دلایل خیلی ساده و البته کاربردی به شما اهمیت استفاده از angular.js رو در پروژههاتون شرح بدم ولی پیشنهادم این هست که ابتدا به معرفی توانایی های angular.js بپردازیم و بعد در چند تا مثال ساده اون محک بزنیم.
ارتباطات و دریافت اطلاعات و ورودی ها
اولین سوالی که ممکنه ذهن رو مشغول کنه این هست که رفتار AngularJs با دادهها به چه صورت هست؟ به یک مثال ساده توجه کنید :
<html> <head> <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.0.4/angular.js"> </script> </head> <body ng-app> <p>Enter your name: <input type="text" ng-model="name"></input></p> <p>Hello {{name}}!</p> </body> </html>
این بخش کوچکی از یک اپلیکیشن هست. با کمی تامل روی کد متوجه میشین که ما عبارت name رو در دو جای متفاوت به کار بردیم. بله، کاملا درست متوجه شدید. میتونید به صورت مستقیم و بدون واسطه اعمال زیادی روی دادهها انجام بدید. یکی از سادهترین حالتها، همین نمایش زنده فعالیت کاربر داخل تگ input هست که توسط $scope انجام میشه. به این معنی که همزمان با تایپ کاربر، آنگولار خودش دیتاها و ویو رو آپدیت میکنه.
اعمال دیگه ای مثل شرط ها ، حلقه ها ، فیلترینگ و … به سادگی قابل پیاده سازی هستند.
Model مخزن اسرار شماست :
اگر شما قصد داشته باشید یک کامنت رو ثبت کنید، یک محصول رو به سبد خرید اضافه کنید، به مطلبی امتیاز بدید روش معمول کار شما چیزی جز این نیست :
بعد از انجام فعالیتهای کاربر (ثبت کامنت ،لایک،خرید محصول و . . .) دیتای موجود رو در سرور ثبت میکنید. بعد دست به کار میشین تا DOM رو هم تغییر بدید و شما میمونید و دست و پنجه نرم کردن با مشکلاتش از قبیل پیدا کردن آبجکت مورد نظر، بهروزرسانیها و سایر موارد که پیش روی شماست. ولی خب همه موارد و مشکلات بالا زمانی هست که شما از آنگولار استفاده نکنید.چون آنگولار قدرت فوق العادهای در بهروزرسانی دو طرفه Model و DOM داره و این کارها با آرامش و لذت انجام میشه نه سختی و مشقت.
پشتیبانی از قالب ها (templates) :
اگر نیاز داشته باشید برای آنگولار قالب تهیه کنید، یا اگر بخواهید از ذوق و سلیقه خودتون در قالب استفاده کنید فقط کافی هست در HTML و CSS مهارت داشته باشید و بقیه امور رو به انگولار بسپارید. تبدیل قالب HTML شما به DOM و رندر کردن دایرکتیوها با اطلاعات Model شما و ارائه به مرورگر از وظایف معمول انگولار هست. شک نکنید که انگولار برای شما دستیار قابل اعتمادی در این زمینه هست.
دایرکتیو ها :
برای من بارها پیش اومده که نیاز داشتم آبجکت جدیدی داخل HTML داشته باشم که خودم براش رفتار تعریف کرده باشم. اجازه بدید با یک مثال ادامه بدیم، مشتری من نیاز داره تا اطلاعات رو روی نمودار ها بهش نشون بدم.
قدم اول HTML :
<body> <div id="chart"></div> </body>
خب حالا قراره من از این div#chart در قسمتهای مختلفی از برنامه به عنوان نمودار استفاده کنم، پس نیاز هست که از جاوااسکریپت کمک بگیرم :
$('#chart').pieChart({ ... });
تا اینجا مشکل خاصی نیست. اما اگر قرار باشه از نمودار در جاهای مختلف با اطلاعات مختلف استفاده بشه چی؟ این یعنی یک کار خسته کننده و کسالت آور! خب همین پروژه رو با انگولار انجام میدیم :
قدم اول HTML :
<body> <pie-chart width="400" height="400" data="data"></pie-chart> </body>
قدم دوم در کار نیست. در عمل شما یک بار المنتهای جدید رو با رفتارهای مد نظرتون تعریف میکنید و میتونید همه جا در کنار انگولار از اون استفاده کنید. المنتها بسیار انعطافپذر هستند. توی مثال ما عرض و ارتفاع و ورودی داده رو برای ساخت نمودار به خود المنت دادیم. میتونید برای مشاهده نمونه به اینجا مراجعه کنید.
دایرکتیوهای تو کار :
انگولار دارای دایرکتیوهای تو کار فراوانی هست. یعنی المنتها و رفتارهای سفارشی شده که در خود انگولار موجود هست و فقط کافیه شما اونها رو صدا بزنید. به یک مثال ساده توجه کنید :
<html> <head> <style> html, body { background-color: #ecf0f1; margin: 20px auto; display: block; max-width: 600px; height: 100%; text-align: center; } body { padding: 20px; position: relative; } h2, a, p, *:before,h1 { font-family: "Helvetica Neue", sans-serif; font-weight: 300; } h1 { color: #3498db; } h2 { color: #2980b9; margin-bottom: 9px; margin-top: 0; font-size: 20px; background-color: white; /*width: 100px;*/ text-align: center; padding: 16px; z-index: 15; border-radius: 4px; transition: all 2s ease-out; } p { display: block; width: 100%; color: #2c3e50; clear: both; } .description { margin-bottom: 70px; } button { border: 0; background-color: #3498db; color: white; border-radius: 4px; padding: 5px 10px; transition: background-color 0.2s ease-out; cursor: pointer; } button:hover { background-color: #2980b9; } button:active, button:hover { outline: none; } a { color: #2c3e50; transition: color 0.2s ease-out; /*padding: 5px 10px;*/ margin-right: 16px; } a:hover { color: #2ecc71; } .wrapper { border: 1px dashed #95a5a6; height: 56px; margin-top: 16px; border-radius: 4px; position: relative; font-size: 12px; } .wrapper p { line-height: 31px; } </style> </head> <body> <div ng-app=""> <h1>Ng-show & ng-hide</h1> <p class="description">Click on the "show"-link to see the content.</p> <a href="" ng-click="showme=true">Show</a> <button ng-click="showme=false">Hide</button> <div class="wrapper"> <p ng-hide="showme">It will appear here!</p> <h2 ng-show="showme">This is mah content, yo!</h2> </div> </div> </body> </html>
یکی از پرکاربرد ترین دایرکتیو ها ng-repeat هست :
<body ng-controller="ctrl"> <h2>{{rows.length}} Friend{{plural(rows)}} <span ng-show="temp">?<small class="muted"><em > (only {{rows.length-1}} actually....)</em></small></span></h2> <form class="form-horizontal"> <span ng-class="{'input-append':addName}"> <input id="add" type="text" placeholder="Another one ?" ng-model="addName" ng-change="addTemp()"/> <input type="submit" class="btn btn-primary" ng-click="addRow()" ng-show="addName" value="+ add"/> </span> <span class="search input-prepend" ng-class="{'input-append':search}"> <span class="add-on"><i class="icon-search"></i></span> <input type="text" class="span2" placeholder="Search" ng-model="search"> <button type="submit" class="btn btn-inverse" ng-click="search=''" ng-show="search" value="+ add"><i class="icon-remove icon-white"></i></button> </span> </form> <table class="table table-striped"> <tr ng-repeat="row in rows | filter : search" ng-class="{'muted':isTemp($index)}"> <td>{{$index+1}}</td> <td>{{row}}</td> <td> <button class="btn btn-danger btn-mini" ng-click="deleteRow(row)" ng-hide="isTemp($index)"><i class="icon-trash icon-white"></i></button> </td> </tr> </table> </body>
Dependency Injection یا تامین وابستگی ها :
نیاز دارید توسط انگولار از یک URL اطلاعات دریافت کنید یا به اون اطلاعات ارسال کنید؟ شاید هم بخواهید پارامترهایی که توسط کاربر ارسال میشن رو دریافت کنین. و دهها شاید دیگه، کلید تمام این شایدها در دست انگولار هست. کافیه شما در کنترلر به انگولار بگین که به چه چیزی نیاز دارین و فراهم کردن امکانات رو به انگولار بسپارید.
<div ng-app="" ng-controller="customersController"> <ul> <li ng-repeat="x in names"> {{ x.Name + ', ' + x.Country }} </li> </ul> </div> <script> function customersController($scope,$http) { $http.get("http://www.w3schools.com/website/Customers_JSON.php") .success(function(response) {$scope.names = response;}); } </script>
کنترلر ها
ما در اول از MVC صحبت کردیم. با Modelها و همگامسازی دوطرفه اون آشنا شدیم و همچنین کار با view هم به لطف directive برامون لذت بخش خواهد بود. حالا نوبت مهره اصلی یعنی Controller هست. ما میتونیم برای نظم بیشتر، سهولت انجام کار، توسعه سریعتر و … از کنترلرها استفاده کنیم. پیشنهاد میکنم به جای اینکه توضیح بدم، یک قطعه کد رو نمایش بدم:
var phonecatControllers = angular.module('phonecatControllers', []); phonecatControllers.controller('PhoneListCtrl', ['$scope', '$http', function ($scope, $http) { $http.get('phones/phones.json').success(function(data) { $scope.phones = data; }); $scope.orderProp = 'age'; }]); phonecatControllers.controller('PhoneDetailCtrl', ['$scope', '$routeParams', function($scope, $routeParams) { $scope.phoneId = $routeParams.phoneId; }]);
خب برای اینکه بتونیم به راحتی به کنترلرها دسترسی داشته باشیم باید از Routing بهره ببریم. مسیریابی در انگولار بسیار لذت بخش هست :
phonecatApp.config(['$routeProvider', function($routeProvider) { $routeProvider. when('/phones', { templateUrl: 'partials/phone-list.html', controller: 'PhoneListCtrl' }). when('/phones/:phoneId', { templateUrl: 'partials/phone-detail.html', controller: 'PhoneDetailCtrl' }). otherwise({ redirectTo: '/phones' }); }]);
موارد اصلی انگولار رو بیان کردیم و تنها به ذکر بعضی ویژگی های انگولار مثل کار با REST api انیمیشن ها، مدیریت رخدادها و . . . بسنده میکنیم و توضیح اون ها رو به زمان دیگری موکول میکنیم. در پایان دعوت میکنم به یک کار قشنگ که توسط برنامهنویسان ایرانی و با استفاده از انگولار انجام شده توجه کنید :