هنوز چند بایت مونده که پیدا کنم...

چرا نباید از انگولار (AngularJS) استفاده کرد؟

زمان زیادی هست که از ظهور انگولار گذشته و الان اینترنت پر شده از مطالب و پست های مربوط به انگولار که مدحش رو میگن یا نقدش میکنن. امیدوارم به زودی این فریم ورک از صنعت نرم افزار حذف شه (هر چند بعیده! چون تاریخ میگه گوگل با استفاده تبلیغات و پول تونسته آشعال ترین گزینه های هر بخش رو زنده نگه داره و پاپ کنه! اندروید و کروم مصادیق بارز جنس جور کردن گوگل هستش). نمیدونم چرا اما تو صنعت نرم افزار خیلی از این موارد انقلابی ظهور کردن کلی سر و صدا کردن و بعد از مدتی فراموش شدن. یه توسعه دهنده باهوش باید توانایی تشخیص و تمیز بین این هجمه فریم ورک ها رو داشته باشه و بدونه فرق تکنولوژی جدید با تکنولوژی جاری (زنده) و قابل اعتماد چیه. من خیلی پست های برنامه نویس ها، معماران و مهندسین نرم افزار مطرح رو در این زمینه خوندم و با توجه به تجربه کاریم به این نتایج رسیدم و دارم با شما به اشتراک میذارم.

انگولار آمدش و به قول خارجیا یه تاثیر "واو" (و من میگم وااااویلااااا) گذاشت روی همه! وقتی بار اول میبینیش: "واویلااااااا ! من نوشتم ng-repeat و منطق برنامه رو فقط با تگ ها پیاده سازیش کردم، خودش آپدیت میشه لامصب!"، اما به محض اینکه شروع میکنید اپلیکیشن واقعی رو پیاده کنید –نه یه TODO-Listدیگه یا پروژه های آزمایشگاهی - میفهمین چقدر مزخرف پیش میره همه چیز و چقدر نا امید کننده است. اینو گفتم که بدونید من به این فریم ورک مسلط هستم :) نزدیک به 18 ماهه دارم ازش استفاده میکنم. خوب مشکلش چیه ؟

جواب قطعی ندارم براتون، یه لیست دارم از اشکالاتش که برداشت من رو از پروژه شکل میده. به قول دوستی "انگولار نتیجه معماری بده".

 

مقید سازی دوطرفه (Two-Way data-binding) 

(برای درک پایه ای از این مفهوم مراجعه کنید به مطلب مرتبطی که قبلا نوشتم همینجا)

یه اصل برنامه نویسی میگه همیشه صراحت بهتر از تلویح هست (Explicit is always better than implicit).

در اصل  تمام این $watch هایی که میذاریم تو انگولار فراخوانی event handler  ها به صورت تلویحی هستش. در واقعیت، رویدادها (events) زمان محاوره کاربر با واسط کاربری اتفاق میفته، مثلا کلیک کردن یه دکمه یا تایپ یک کاراکتر و ...، نه اینکه وقتی مدل ما (منظور از مدل همون موجودیت،Entity یا هر اسمی که خودتون برای این مفهوم شی گرا متصور شدید؛ هست) عوض میشه، پس وقتی دارید انگولار مینویسید باید اینطور فکر کنید :

"کاربر کلیدی را کلیک کرده و مدل تغییر کرده، حالا ما باید گوش بدیم به تغییرات این مدل و هندلر رویداد رو فراخوانی کنیم"  در صورتی که مفهوم واقعی اداره رویداد ها (event handling) اینه : "کاربر کلیدی را کلیک کرده هندلر رویداد رو فراخوانی کن".

به صورت مشابه همین اتفاق وقتی که شما داده ها رو از پایگاه داده (از این لغت خیلی لذت میبرم چون حداقل توی 23 کشور دنیا نمیتونن اینو تلفظش کنن – همون دیتابیس) میکشید بیرون و میخواین بنویسین تو مدل میفته، یعنی با کوچکترین تغییر این هندلر ها فراخوانی میشن. غیر منطقی نیست؟! حتی تو جاوا که هیچ تابع (function)  ناشناسی (anonymous) نداره – تا زمانی که من باش کار میکردم – callback ها با کلاس های ناشناش پیاده میشدن. چون این صریحه و چون این مفهمومیه که شرایط واقعی رو پوشش میده. حتی ورژن بعدی Ember هم دیگه Two-Way Binding رو پشتیبانی نمیکنه.

بایندینگ دو طرفه به این معنیه که اپ شما صدها تغییر رو داره چک میکنه. کنـــــــــــــــده! مخصوصا وقتی واسه موبایل دارین کد مینویسن (بر خلاف ادعای انگولار) و یکم اپ پیچیده تر بشه این کند بودن ملموس تره. و جالبه این قسمت اساسی فریم ورک هست. انگولار حتی محدودیت هایی برای نوشتن UI اعمال میکنه. و جالبتر اینکه فقط 2000 تا watcher میتونید داشته باشید. پس تکلیف پروژه های بزرگتر چی میشه؟ اینجاست که مجبورین با فریم ورک سرشاخ بشین :)

انگولار آمده یه امکان One Way Binding  هم ارائه داده که مشکل راندمان رو حل کنه؛ اول مشکل ایجاد کنید بعد با یه هک حلش کنید! خنده داره... (اینه که میگن معماری افتضاح). نگاهی به لینک های زیر بندازید و ببینید ملت چقدر با راندمان انگولار مشکل دارن:

http://blog.scalyr.com/2013/10/angularjs-1200ms-to-35ms

https://www.airpair.com/angularjs/posts/angularjs-performance-large-applications

http://bahmutov.calepin.co/improving-angular-web-app-performance-example.html

http://www.binpress.com/tutorial/speeding-up-angular-js-with-simple-optimizations/135

http://tech.small-improvements.com/2013/09/10/angularjs-performance-with-large-lists/

http://code.mendhak.com/angular-performance/

http://www.williambrownstreet.net/blog/2013/07/angularjs-my-solution-to-the-ng-repeat-performance-problem/

http://stackoverflow.com/questions/17656397/angular-js-scaling-performance

http://stackoverflow.com/questions/16114946/ways-to-improve-angularjs-performance-even-with-large-number-of-dom-elements

http://stackoverflow.com/questions/17348058/how-to-improve-performance-of-ngrepeat-over-a-huge-dataset-angular-js

 

اصلا اینو گوگل کنید angular performance مقالات بی شماری برای بهبود پرفورمنس انگولار و سریع کردنش لیست میشه. بازم فکر میکنید اینا کافی نیست برای اینکه قبول کنیم انگولار پرفورمنس خوبی نداره؟

یه نکته دیگه، برخی مواقع شاید دیده باشید که شما مقید سازی دو طرفه رو نیاز دارید، اما UI با تاخیر لود میشه. مثلا وقتی کاربر صفحه رو لود میکنه میبینه یه عبارتی بین جفت آکولاد نوشته شده {{firstName}}. نه این باگ نیست! این ویژگیه انگولاره. که تو این حالت مجبور بودیم UI رو مخفی کنیم که کاربر نبینه این عبارت های (از نظر کاربر) عجیب و تخیلی رو بعد از اتمام بایندینگ دوباره نمایشش بدیم که الان انگولار برای این مشکل دو تا رهنمون (directive) ارائه داده : ngCloack و ngBind. انگولار همچنان داره مشکلاتی ایجاد میکنه و برای حلشون هک هایی ارائه میده که برای بار سوم باید بگم آرشیتکت معلول.  و حالا اگر یک فریم ورک مسائل این چنینی داشته باشه با توسعه پذیری، به این معنی نمی تونه باشه که یه جای کار میلنگه اونم در سطح پایه ای و اساسی؟ اینم یه قانونه تکنولوژی هایی که موجز و خوب نوشته شده باشن به خوبی هم گسترش پیدا میکنن.

 

تزریق وابستگی (dependency injection)

انگولار وابستگی ها رو با اسم آرگومان ها انجام میده ببینید :

function MyController($scope, $window) { // … }

اینجا انگولار .toString() رو فراخوانی میکنه، اسم آرگومان ها رو بدست میاره و بعد تو لیست وابستگی ها موجود میگرده دنبالشون. جستجوی اسم متغیر صحیح اما مشکل اینجاست که وقتی کدتون رو کمینه کنید (minify) دیگه کار نمیکنه :| چرا ؟ چون متغیر ها با اسمشون تزریق شدن. که مجبورین یکی از نحو های زیر رو استفاده کنید :

someModule.controller(‘MyController’, [‘$scope’, function($scope) { }]);

یا

MyController.$inject = [‘$scope’, ‘$window’];

ولی این نامفهومه که چرا راه های زیادی برای انجام یک کار مشترک وجود داره، و گنگ تر اینه که چرا لازم بوده که یه راه دست و پا شکسته ارائه بشه که بعد مجبور شن هک بدن براش. معلومه معماری داغون. نکته بعدی روشی هست که شما باید وابستگی ها رو تعریف کنید:

injector.register(name, factoryFn);

که name اسم وابستگی (dependency یا همون مثلا کتابخانه ها و کلاس های پیش نیاز این کلاس هست) و factoryFn تابعی که وابستگی رو راه اندازی میکنه (initialize). همین. حالا ببنید انگولار چی پیشنهاد میده. انگولار 5 موجودیت جدید رو معرفی میکنه : provider, service, factory, value, constant (بازم آرشیتکت ناشیانه). و هر کدومشون با هم فرق دارن، اما اساسا یکی هستن :| جالب اینه که همشون میتونن با یه متد واحد و ساده که نوشتم بالا جایگزین بشن. اما ظاهرا رفقای ما که انگولار رو آرشیتکت کردن پیش خودشون فکر کردن که این خیلی راحته بذار مردم رو بیشتر عذاب بدیم !

خطا یابی (debugging)

آقا قبول دارم که خطایابی خودش مصیبت عظمی است! سخته به ذات، اما سختیش کافی نیست، باید پیچیده تر و سخت تر بشه! انگولار به هر چه بیشتر شکنجه شدن شما کمک میکنه. خطا در بایندینگ ها کلا نادیده گرفته میشود!

باور کن! مثلا این تکه کد:

<div ng-repeat=”phone in user.phones”> {{ phone }} </div>

اگر user تعریف نشده باشه خطایی بوجود نخواهد آمد (آرشیتکت زاغارت). در ضمن break point هم نمیشه گذاشت بین عبارات محصور در {{}} چون جاوا اسکریپت نیستن. بریم جلو، خطا های جاوا اسکریپتی اجازه خروج از انگولار رو ندارن! (یعنی هر چیزی اتفاق میفته توی خود انگولار اتفاق میفته و تمام به بیرون درز نمیکنه!). شما باید فلگ Pause On Caught Exceptions رو فعال کنید که دیباگر به سر همه خطاها و نه تنها خطاهای هندل نشده بایسته ،(در صورتی که خطاهای هندل نشده ارزش بررسی دارن) به این دلیله که باید وقت راه اندازی انگولار تمام خطاهای داخلی رو چک کنید و تنها تو این حالت میتونید خطای واقعی رو ببینید ! خنده داره اما واقعیته . بازم معماری بد. تازه یه پشته از خطا ها میبینید که باید باهشون کنار بیاین این تصور رو ببنید :

 

 

خطا داره از روند digest بروز میکنه و این یعنی میتونه با تغییر هر متغیر در کل اپ بوجود آمده باشه. عمرا بتونید تشخیص بدین از کجا داره خطا صادر میشه. (معماری مریض)

 

وارثت دامنه (scope inheritance)

شک ندارم این معمول ترین خطایی هست که انگولار کارا مواجه میشن باهاش. برای مثال این کد زیری رو در نظر داشته باشین:

<div ng-init="phone = 02"> {{ phone }} </div>
<div ng-if="true">
    <button ng-click=”phone = 911">change phone</button>
</div>

با کلیک روی دکمه phone متغیر عوض نمیشه در حالی که تو این کد:

<div ng-init="phone = {value: 02}"> {{ phone.value }} </div>
<div ng-if="true">
    <button ng-click=”phone.value = 911">change phone</button>
</div>

همه چیز طبق انتظار کار میکنه. یا برای مثال تو تکه کد بعدی رفتار انگولار خیلی مطابق با چیزی که میبینید نیست:

<div ng-app="MyApp" ng-controller="MyCtrl">

    <label> Type here first, and both will share their ng-model</label>    

    <input ng-model="obj.prop" type="text" /><br />    

    <div ng-if="true">    

        <label>Type here first, and their ng-models will be distinct</label>        

        <input ng-model="obj.prop" type="text" /><br />        

    </div>    

</div>

تازه یه فرم جدید تعریف متغیر در کنترلر وجود داره که از this استفاده میکنه که این مشکل رو حل میکنه.(معماری غلط). بدیهیه که این رفتا لازم نیست و خیلی هم خطرناکه:

  • اگر بنای منطق برنامه رو بر اساس scope inheritance بذارید خوب خیلی سخت میشه تستش کرد ( مجبور میشین کنترلر والد رو هم initialize کنید)
  • منطق برنامه (logic) پیچیده میشه و به سمت تلویحی شدن میره (متغیری استفاده میکنید که تو ماژول فعلی تعریف نشده)
  • وارثت متغیر مثل تعریف متغیر سراسری هست. و همه میدونن که متغیر سراسری فاجعه است.
  • باید میزان دانش تئوریتون هم ببرید بالا با این روش که خودش داستانیه و البته هیچ جای دیگه هم به درد نمیخوره.

حجم سوالات ملت رو تو stackoverflow.com و یا مقالاتی که روی اینترنت منتشر شدن ببنید اونوقت متوجه میشید این مساله چقدر گیج کننده و پیچیده میتونه باشه در صورتی که نیازی نیست واقعا:

http://stackoverflow.com/questions/14049480/what-are-the-nuances-of-scope-prototypal-prototypical-inheritance-in-angularjs

http://stackoverflow.com/questions/11605917/this-vs-scope-in-angularjs-controllers

http://jonathancreamer.com/adding-clarity-to-scope-inheritance-in-angular/

http://nathanleclaire.com/blog/2014/04/19/5-angularjs-antipatterns-and-pitfalls/

http://jimhoskins.com/2012/12/14/nested-scopes-in-angularjs.html

http://www.youtube.com/watch?v=Kx5J7PzRiis

http://www.undefinednull.com/2014/02/11/mastering-the-scope-of-a-directive-in-angularjs/

http://blog.mgechev.com/2013/12/18/inheritance-services-controllers-in-angularjs/

http://codetunnel.io/angularjs-controller-as-or-scope/

http://www.bennadel.com/blog/2424-setting-prototype-properties-using-inherited-scope-methods-in-angularjs.htm

http://www.dnasir.com/2013/11/04/scope-inheritance-in-angularjs/

http://www.michaeldausmann.com/2013/01/angularjs-scope-vs-controller.html

http://www.codeproject.com/Tips/856909/Controller-Inheritance-in-angularjs-and-How-to-Avo

http://blog.carbonfive.com/2014/02/11/angularjs-scopes-an-introduction/

https://groups.google.com/forum/#!topic/angular/NXyZHRTAnLA

https://github.com/ericdouglas/angular-scope-inheritance

https://andywalpole.me/#!/blog/140067/using-prototypal-inheritance-angularjs-controllers-services

http://www.dotnet-tricks.com/Tutorial/angularjs/cXFL291214-Understanding-scope-inheritance-in-AngularJS.html

https://github.com/angular/angular.js/wiki/Understanding-Scopes#angular-scope-inheritance

http://onehungrymind.com/angularjs-sticky-notes-pt-2-isolated-scope/

http://www.ivanturkovic.com/2014/11/26/angularjs-nginclude-directive-scope/

http://blog.dwaynecrooks.com/post/98460779842/angularjs-scope-inheritance-gotcha

http://fdietz.github.io/recipes-with-angular-js/controllers/sharing-models-between-nested-controllers.html

http://chris.59north.com/post/2014/02/12/A-simple-introduction-to-AngularJS-Part-4-%E2%80%93-%E2%80%9CScope-inheritance%E2%80%9D.aspx

http://www.tutorialspoint.com/angularjs/angularjs_scopes.htm

http://www.c-sharpcorner.com/UploadFile/cd7c2e/scope-inheritance-in-controller-method-of-angularjs/

https://cfdeepak.wordpress.com/2014/10/18/playing-with-scope-inheritance-in-angular/

http://jsfiddle.net/AntrikshPatel/ye6DQ/

http://www.btskyrise.com/blog/2013/06/17/understanding-scopes-in-angularjs-the-nuances-of-prototypal-inheritance/

http://blog.pushtech.com/how-angularjs-manages-inheritance-in-controllers-scopes/

http://gon.to/2013/05/01/sharing-data-state-on-angularjs-alternatives-comparison-and-my-solution/

http://www.cubicleman.com/2013/03/14/angularjs-and-a-js-prototypal-inheritance-gotcha/

 

به هر حال میشه گفت تقریبا توصیه همه عدم استفاده از این روش (scope inheritance) هستش. طی این مدت کار کردن با انگولار نتونستم مورد استفاده ای براش پیدا کنم منظورم اینه که جایی به دردم بخوره از دامنه والد بخوام دسترسی داشته باشم به متغیر های فرزند(جز رهنمون هایی مثل ng-repeat که به عنوان کاربر فریم ورک برام مهم نیست این مساله اما اگر میخواستم فریم ورک انگولار رو پیاده کنم آره...) جالبتر اینکه میشه از این رفتار جلوگیری کرد به سادگی اینطوری که یک wrapper برای آبجکت های جاوا اسکریپت ایجاد کنیم.

 به عنوان یک قانون، فریم ورک ها باید نقایص بستر اجرایی رو مخفی کنن و در API های خودشون منطق و شفافیت بیشتری در رفتار نشون بدن. که نمیدونم چرا انگولار با این اصل هم مشکل داره و در ستیزه!

 

رهنمون ها (directives)

خوب این جذاب ترین قسمت کاره. رهنمون ها شاهکار انگولار هستن (البته بهتر بگم قوز بالا قوزش). همه روانی شدن ازشون. اما من واقع بینانه درموردشون قضاوت میکنم. این لینک روش تعریف پیچیده رهنمون ها هست. برای درک این نحو (syntax) و اینکه اصلا چرا نیاز دارین بهش، واقعا باید وقت بذارید. جای اینکه ببیند چکار کنید باید ببینید چطوری باید انجامش داد. اعصاب خوردکن بودنش اینه که سخته اما بی استفاده است. هیچ دلیل عقلانی نیست که تایید کنه ما باید منطق رو به سه متد (compile, link, controller) تقسیم کنیم، همه اینا راحت میشد توی یک متد پیاده سازی بشن. ببینید باز چقدر مشکل بوجود آورده :

تازه در نظر داشته باشید که برخی از توابع فقط یکبار استفاده میشن، بعضی هر بار در سیکل $digest ، و هر رهنمون اولویت داره. حتی اگر بخواید مثلا یه تکه کد جی کوئری میون کد انگولار بنویسید باید براش رهنمون تعریف کنید و من میگم قنداقش کنید با رهنمون. دلیلش هم اینه که نباید کاری کرد که برنامه نویسا راحت راه حل پیدا کنن برا هر کاری! باید عذاب بیشتری متحمل بشن! (این فلسفه انگورلاره)

 

مشکل با ملت

اول چون بیش از حد و بیهوده پیچیده هست توسعه دهنده های حرفه ای زیادی وجود نداره. دوم اینکه برنامه نویس های back-end هیچ فهمی از این کدای مسخره ندارن و نمیدونن چی داره تو سطح front-end میگذره و این عیب بزرگیه که یه جعبه سیاه تو پروژه داشته باشی که فقط یک یا چند نفر ازش سر در میارن، اگر انگولار کار پروژه رفتش چی؟ آیا آسونه جایگزن کردنش؟ تو این فاصله که نفر بعد بیاد واقعا نمیتونید از باقی برنامه نویسا توقع داشته باشید کد رو نگهداری کنن. اگر نیازه واقعا به این سطح از پیچیدگی در سطح front-end خوب پس استفاده کنید ( هرچند نوشتن GUI با ExtJs خیلی سخت تره از انگولار اما سختیه ExtJs دلیل داره و منطقیه)، نه بذارین دوباره ببینم!، نه انگولار سخت تره چون عمدا نوشتن واسه سخت بودن و هدف دار بوده سختیش. مقایسه کنید با ReactJs یا jQuery که هر برنامه نویس back-end میتونه بفهمتش.

 

عدم وجود قابلیت ایجادی (render) سمت سرور

اگر دارین تلاش میکنید که صفحه رو سمت سرور رندر کنید به منظور افزایش سرعت یا اهداف SEO یا هردو با انگولار موفق نخواهیــــــــد شد! چون رندر سمت سرور منطق رو به کد اچ تی ام ال شما اضافه میکنه و انگولار لاجیک رو در اچ تی ام ال مینویسه یعنی جدا نشده درست که کدوم logic هستش و کدوم view! یه جورایی اسپاگتیه (spaghetti) در صورتی که انتظار میره رویولی (ravioli ) باشه. انگولار تو تخیلش هم نبوده که یه موقع برنامه نویس ها در یه سطحی نیاز دارن رو سرعت پروژه کار کنن. کش سرور استفاده کنن یا روی سئو کار کنن، اصلا برا این کارا ساخته نشده! (بیشتر بدرد اپ های اینترانتی میخوره). آره شما میتونید از ابزارهایی استفاده کنید که (مثل prerender.io) اپ های تک صفحه ای (SPA) شما رو به صورت اچ تی ام ال رندر میکنه که بدید تحول کراولرها، اما باز این یه هکه! راهکار برای مشکل نیست.

 

انگولار 2

به زودی نسخه نهایی انگولار دو (الان در این لحظه نسخه بتا هستش) منتشر میشه که کلا سازگاری با ورژن قبلی اصلا نداره (backward compatibility). یعنی کلا آمدن فریم ورک رو از نو نوشتن از صفر تا صد! یعنی اگر شما الان پروژه ای دارین که با انگولار 1 هست خوب دمتون گرم همین چا بذاریدش و محکومین که تا ابد از همین استفاده کنید. نمیتونید به راحتی و کم هزینه آپدیت کنید. کلاهتون رو بکنید قاضی! اگر فریم ورکه داغون نبود از نو مینوشتنش؟

 

نکات دیگر

همیشه اینطوریه که اگر یه توسعه دهنده یا برنامه نویس کد بدی بنویسه همه جا این کارو کرده !

من سعی کردم چیزایی که تو ذهنم آمد رو بنویسم، طبق اون اصلی که الان ذکر کردم وقتی این مشکلات رو داره میتونه مشکلات دیگه و بیشتری هم داشته باشه که در محدوده دانش من نبوده. پس اگر میخواید باهاش کد بنویسین آماده باشین:

  • مستند وحشتناک، اگر چیزی لازم داشتید باید خیلی گوگل کنید.
  • هنوز رهنمونی واسه درگ دراپ نیست (زمانی که من کار میکردم). این مشکل بزرگی نیست اما نشون دهنده عدم توجه طراحان فریم ورک به جزئیاته و به کیفیت بده فریم ورک بر میگرده.
  • وقتی انگولار مینویسین منطق رو توی مارک آپ (کد اچ تی ام ال) میذارین (ng-repeat, ng-show, ng-class, ng-model, ng-init, ng-click, ng-switch, ng-if). این به ذات بد نیست البته به این بدی نیست که نمی تونید دیباگ کنید یا یونیت تست بنویسید برا لاجیک. چون خطایی از مارک آپ در نمیاد.

 

نتیجه:

تمام مسائلی رو که گفتم من تونستم حل کنم نهایتا (چون نمیشد پروژه ای که خودم نوشتم رو تنها بذارم و پشتیبانی نکنم! منصف باشید) . اما مثل اینکه بتونی یه ماشین خوب و قابل اطمینان سوار شی اما بیای یه ماشین غراضه سوار شی که دائم نگران باشی داخلش سرد نیست؟ صندلیا کثیف نیست؟ تو سرعت بالا صدای موتور روانیت نمیکنه؟ ترمز داره؟ پخش موسیقی داره؟ اووووه کاست میخوره؟! و اگر خراب شد چند تا مکانیک براش هست؟ انگولار 1 همون ماشین قراضه هست. کار میده! اما مشکلاتش بیش از استفاده اش هست. این واقعیت که میشه مشکلات رو حل کرد به این معنی نیست که مساله ای وجود نداره! تنها مزیتش اینه که برنامه نویس رو مجبور میکنه که لاجیک رو بشکنه تو ماژول های مختلف، پس کد توچینی بهتری داره، مزیت دیگه ای دیدن ازش به منم بگین. البته همین مزیت رو ReactJs فیسبوک هم ارائه میده (من مشکلاتی که گفتم رو توش ندیدم) یا هرچی دیگه مثلا Backbone یا Knockout (البته با مسئولیت خودتون من خیلی بازخوردهای بدی شنیدم ازشون البته با knockout مدتها کار میکنم اصلا قابل مقایسه نیست با انگولار) . نمی دونم چرا انگولار اینقدر معروف شده هرچی هست به دلیل کیفیت خوبش نمی تونه باشه.

امیدوارم اینا کمکتون کنه تو پروژه بعدی انتخاب درست تری داشته باشید.

 

نکته آخر : من همه اینها رو در مورد انگولار 1 تجربه کردم و گفتم و هیچ ایده ای خوب یا بد در مورد ورژن دو ندارم!

واینکه تا اینجا من فکر میکنم انگولار خر است :)

نویسنده : محمد ملک مکان
ﺳﻪشنبه 24 فروردین 1395
+ 171 -

ایده ها، نظرات و سوالات دوستان ما

مهمون کدجیک
ﺳﻪشنبه 18 خرداد 1400
الان نظرتون راجب انگولار چیه؟
+ 10 -
مهمون کدجیک
دوشنبه 3 آذر 1399
من هم از انگولار خوشم نیومد . فقط جی کوئری!
+ 00 -
مهمون کدجیک
یکشنبه 9 خرداد 1395
انگولار خر است ها ها ها
+ 70 -
مهمون کدجیک
یکشنبه 9 خرداد 1395
خیلی خوب بود
+ 00 -
مهمون کدجیک
دوشنبه 13 ارديبهشت 1395
ممنون از اطلاعت مفیدی که گذاشتین
+ 30 -

خوشحال میشیم نظرتُ بدونیم