اشتراک‌ها
نکات مهم نظرسنجی JavaScript در سال 2018

Here's a couple of final thoughts.

  • 3 major front end frameworks (Angular, React, and Vue)
  • React is the highest growing and highest paying front end framework
  • Express is still the dominant Node framework by far
  • TypeScript is becoming more and more popular (and it's going to take over...just my thought)
  • Tooling is making JavaScript a more evolved and appealing language
  • Options to reach almost any platform (desktop, mobile, server, web, hybrid, etc.)
  • Graphql is on the rise, especially with the rise of Gatsby.js 
نکات مهم نظرسنجی JavaScript در سال 2018
اشتراک‌ها
ReSharper Ultimate 2016.1.1 منتشر شد

ReSharper 2016.1.1. The update helps ReSharper see controllers outside of ASP.NET MVC areas and folders again (RSRP-458398, RSRP-455213); adds smart, license-aware update checks; enables bulk renaming in TypeScript (RSRP-458570); fixes Go to Everything so that it works after suspending and resuming ReSharper (RSRP-458404); improves performance in solutions with large JavaScript and JSON files (RSRP-458363); fixes pessimistic mode in value analysis (RSRP-458210); makes IL Viewer available via the Navigate To pop-up (RSRP-458323); improves details of ReactJS support (RSRP-458229, RSRP-458242, RSRP-458308). See all fixes in ReSharper 2016.1.1.  

ReSharper Ultimate 2016.1.1 منتشر شد
مطالب
نوع‌های نال نپذیر در TypeScript
تا پیش از ارائه‌ی کامپایلر TypeScript 2.0، مقادیر null و undefined، به هر نوعی قابل انتساب بودند و امکان تفکیک آن‌ها وجود نداشت که این مورد می‌تواند منشاء بروز بسیاری از خطاهای در زمان اجرا شود.
let name: string;
name = "Vahid"; // OK
name = null; // OK
name = undefined;  // OK
let age: number;
age = 24; // OK
age = null; // OK
age = undefined;  // OK
برای نمونه در اینجا یک متغیر رشته‌ای و همچنین عددی تعریف شده‌اند که انتساب null و یا undefined نیز به آن‌ها مجاز است. این مورد جهت نوع‌های ورودی و خروجی متدها، اشیاء و آرایه‌ها نیز میسر است.


نوع null در TypeScript

همانند JavaScript، نوع null تنها یک مقدار معتبر نال را می‌تواند داشته باشد و نمی‌توان برای مثال یک رشته را به آن انتساب داد. اما انتساب این مقدار به هر نوع متغیر دیگری، سبب پاک شدن مقدار آن خواهد شد. با فعالسازی strictNullChecks، این نوع را تنها به نوع‌های نال‌پذیر می‌توان انتساب داد.


نوع undefined در TypeScript

هر متغیری که مقداری به آن انتساب داده نشده باشد، با undefined مقدار دهی می‌شود. این مورد حتی جهت خروجی متدها نیز صادق است و اگر return ایی در آن‌ها فراموش شود، این خروجی نیز به undefined تفسیر می‌شود.
در اینجا نیز اگر نوع متغیری به undefined تنظیم شد، این متغیر تنها مقدار undefined را می‌تواند بپذیرد. تنها با خاموش کردن پرچم strictNullChecks می‌توان آن‌را به اعداد، رشته‌ها و غیره نیز انتساب داد.


فعالسازی نوع‌های نال نپذیر در TypeScript

برای فعالسازی این قابلیت، نیاز است پرچم strictNullChecks را در فایل تنظیمات کامپایلر به true تنظیم کرد:
{
    "compilerOptions": {
        "strictNullChecks": true
    }
}
از این پس دیگر نمی‌توان null و undefined را به هر نوعی انتساب داد و این‌ها تنها به خودشان و یا نوع any، قابل انتساب هستند. برای مثال اکنون نوع number فقط یک عدد است و دیگر قابلیت پذیرش null و یا undefined را ندارد. البته در اینجا یک استثناء هم وجود دارد: undefined را می‌توان به نوع void نیز انتساب داد.
برای مثال اگر متدی، رشته‌ای را به عنوان پارامتر قبول کند، تا پیش از TypeScript 2.0 و فعالسازی strictNullChecks آن، مشخص نبود که رشته‌ی دریافتی از آن واقعا یک رشته‌است و یا شاید null. اما اکنون یک رشته، فقط یک رشته‌است و دیگر نال پذیر نیست.
 let foo: string = null; // Error! Type 'null' is not assignable to type 'string'.
به این ترتیب دیگر به خطاهای زمان اجرایی مانند خطاهای ذیل نخواهیم رسید:
Uncaught ReferenceError: foo is not defined
Uncaught TypeError: window.foo is not a function

این مورد برای آرایه‌ها نیز صادق است:
// With strictNullChecks set to false
let d: Array<number> = [null, undefined, 10, 15]; //OK
let e: Array<string> = ["pie", null, ""];  //OK
 
 
// With strictNullChecks set to true
let d: Array<number> = [null, undefined, 10, 15]; // Error
let e: Array<string> = ["pie", null, ""]; // Error
اگر strictNullChecks فعال شود، دیگر نمی‌توان به اعضای یک آرایه مقادیر null و یا undefined را نسبت داد.


ساده سازی تعریف بررسی‌های با پرچم strict، در TypeScript 2.3

تعداد گزینه‌های قابل تنظیم در فایل tsconfig روز به روز بیشتر می‌شوند. به همین جهت برای ساده سازی فعالسازی آن‌ها، از TypeScript 2.3 به بعد، پرچم strict نیز به این تنظیمات اضافه شده‌است. کار آن فعالسازی یکجای تمام بررسی‌های strict است؛ مانند noImplicitAny، strictNullChecks و غیره.
{ 
    "compilerOptions": { 
        "strict": true  /* Enable all strict type-checking options. */ 
    } 
}
در این حالت اگر نیاز به لغو یکی از گزینه‌ها بود، می‌توان به صورت ذیل عمل کرد:
{ 
    "compilerOptions": { 
        "strict": true, 
        "noImplicitThis": false 
    } 
}
گزینه‌ی strict تمام بررسی‌های متداول را فعال می‌کند؛ اما ذکر و تنظیم صریح noImplicitThis به false، تنها این یک مورد را لغو خواهد کرد.

یک نکته: اجرای دستور tsc --init ، سبب تولید یک فایل tsconfig.json از پیش تنظیم شده، بر اساس آخرین قابلیت‌های کامپایلر TypeScript می‌شود.


اما ... اکنون چگونه یک نوع را نال‌پذیر کنیم؟

TypeScript به همراه دو نوع ویژه‌ی null و undefined نیز شده‌است که تنها دارای مقادیر null و undefined می‌توانند باشند. به این معنا که در حین تعریف نوع یک متغیر، می‌توان این دو را نیز ذکر کرد و دیگر تنها به عنوان دو مقدار مطرح نیستند. به این ترتیب می‌توان از آن‌ها یک union type را ایجاد کرد:
 let foo: string | null = null; // Okay!
اکنون تنها در این حالت است که متغیر foo می‌تواند یک رشته و یا یک null را دریافت کند و یا اگر مثال ابتدای بحث را بخواهیم اصلاح کنیم، به نمونه‌ی ذیل خواهیم رسید:
let name: string | null;
name = "Vahid"; // OK
name = null; // OK
name = undefined;  // Error
یکی دیگر از مزایای این روش، وضوح بیشتر تعریف نوع متغیرها و به نوعی «خود مستند سازی» بهتر آن‌ها است. در این حالت یا به صورت صریح مشخص می‌کنیم که متدی فقط یک رشته را می‌پذیرد و یا با ذکر string | null، به استفاده کننده اعلام می‌کنیم که ارسال null نیز به آن پیش بینی شده‌است و به نتیجه‌ی نامشخصی منتهی نخواهد شد.

یک نکته:
تا پیش از این اگر متغیری را به این صورت تعریف می‌کردیم:
let z = null;
نوع آن any درنظر گرفته می‌شد. اما اکنون، نوع آن تنها null است و تنها مقداری را هم که می‌تواند بپذیرد نال خواهد بود.


بررسی انتساب، پیش از استفاده

با فعالسازی strictNullChecks، اکنون کامپایلر برای تمام نوع‌هایی که undefined نیستند، یک مقدار اولیه را پیش از استفاده‌ی از آن‌ها درخواست می‌کند:
testAssignedBeforeUseChecking() {
    let x: number;
    console.log(x);
}
در اینجا چون x از نوع عددی است، به علت عدم مقدار دهی اولیه، قابلیت استفاده‌ی از آن وجود ندارد و کامپایلر خطای ذیل را اعلام می‌کند:
 [ts] Variable 'x' is used before being assigned.

اما در حالت ذیل، عدد z می‌تواند عدد و یا undefined باشد؛ به همین جهت کامپایلر با استفاده‌ی از آن مشکلی نخواهد داشت:
let z: number | undefined;
console.log(z);

یک نکته: خواص و پارامترهای اختیاری، به صورت خودکار دارای نوع undefined نیز هستند. برای مثال امضای متد ذیل:
method1(x?: number) {
}
با متد زیر یکی است:
method1(x?: number | undefined) {
}


اجبار به بررسی نال نبودن مقادیر، پیش از استفاده‌ی از آن‌ها در متدهای نال نپذیر

اگر پارامتر متدی یا خاصیت شیءایی نال پذیر نباشند، با ارسال مقدار نوعی به آن‌ها که می‌تواند null و یا undefined را بپذیرد، یک خطای زمان کامپایل صادر خواهد شد. در اینجا محافظ‌های نوع‌ها توسعه یافته‌اند تا اگر بررسی نال یا undefined بودن مقداری انجام شد، مشکلی در جهت استفاده‌ی از آن‌ها نباشد:
  f(x: number): string {
    return x.toString();
  }

  testTypeGuards() {
    let x: number | null | undefined;
    if (x) {
      this.f(x);  // Ok, type of x is number here
    } else {
      this.f(x);  // Error, type of x is number? here
    }
  }
در این مثال، متد f فقط یک عدد را می‌پذیرد (و نه نال و یا undefined). اما در حین کاربرد آن در متد testTypeGuards، مقدار متغیر x می‌تواند یک عدد، نال و یا undefined باشد. چون پیش از اولین استفاده‌ی از متد f در اینجا، بررسی دارای مقدار بودن این متغیر صورت گرفته‌است، فراخوانی صورت گرفته، مجاز است. اما در قسمت else این شرط، کامپایلر خطای ذیل را صادر می‌کند:
 Argument of type 'number | null | undefined' is not assignable to parameter of type 'number'.
Type 'undefined' is not assignable to type 'number'.

امکان این بررسی در مورد عبارات شرطی نیز صادق است:
getLength(s: string | null) {
   return s ? s.length : 0;
}


توسعه‌ی محافظ‌های نوع‌ها جهت کار با نوع‌های نال نپذیر

در مثال ذیل، خروجی متد isNumber دارای امضایی به همراه is است:
isNumber(n: any): n is number { // type guard
   return typeof n === "number";
}
به یک چنین متدهایی type guard گفته می‌شود که امکان بررسی یک نوع را میسر می‌کنند. از این امکان می‌توان جهت بررسی بهتر پارامترها و یا خواص اختیاری استفاده کرد:
  usedMb(usedBytes?: number): number | undefined {
    return this.isNumber(usedBytes) ? (usedBytes / (1024 * 1024)) : undefined;
  }
یک چنین بررسی، بهتر است از بررسی ذیل:
  usedMb2(usedBytes?: number): number | undefined {
    return usedBytes ? (usedBytes / (1024 * 1024)) : undefined;
  }
از این جهت که عبارت شرطی بررسی شده، مقدار صفر را نیز به صورت undefined بازگشت خواهد داد (if(0) به false تعبیر می‌شود و قسمت else این شرط فراخوانی خواهد شد).
همچنین امضای متد نیز به number | undefined تغییر یافته‌است. در غیر اینصورت، خطای زمان کامپایل Type undefined is not assignable to type number صادر خواهد شد.
در حین استفاده‌ی از یک چنین متدی، دیگر نمی‌توان به خروجی آن به صورت ذیل دسترسی یافت:
  formatUsedMb(): string {
    //ERROR: TS2531: Object is possibly undefined
    return this.usedMb(123).toFixed(0).toString();
  }
چون مقدار usedMb می‌تواند undefined باشد، باید ابتدا آن‌را بررسی کرد:
  formatUsed(): string {
    const usedMb = this.usedMb(123);
    return usedMb ? usedMb.toFixed(0).toString() : "";
  }


لغو بررسی strictNullChecks به صورت موقت

با استفاده از اپراتور ! می‌توان به کامپایلر اطمینان داد که این متغیر یا خاصیت، دارای مقدار نال نیست و نخواهد بود:
export interface User {
  name: string;
  age?: number;
}
در این اینترفیس، خاصیت age به صورت اختیاری تعریف شده‌است. برای نمایش مقدار age با فعال بودن strictNullChecks، یا باید ابتدا null نبودن آن‌را به صورت صریحی بررسی کرد:
  printUserInfo(user: User) {
    if (user.age != null) {
      console.log(`${user.name}, ${user.age.toString()}`);
    }
  }
در غیراینصورت قطعه کد ذیل با خطای 'Object is possibly 'undefined کامپایل نخواهد شد:
  printUserInfo(user: User) {
    console.log(`${user.name}, ${user.age.toString()}`);
  }

و یا می‌توان توسط اپراتور ! این بررسی را به صورت موقت خاموش کرد:
  printUserInfo(user: User) {
    console.log(`${user.name}, ${user.age!.toString()}`);
  }
البته استفاده‌ی از این اپراتور توسط tslint توصیه نمی‌شود:
 [tslint] Forbidden non null assertion (no-non-null-assertion)
چون بهتر است به کامپایلر عنوان نکنیم «قسم می‌خورم که این مقدار نال نیست»!



یک نکته‌ی تکمیلی
پس از آزمایش موفقیت آمیز نوع‌های نال نپذیر در TypeScript، مایکروسافت قصد دارد این ویژگی را به C# 8.0 نیز در مورد نوع‌های ارجاعی که می‌توانند نال پذیر باشند، اضافه کند (امکان داشتن نوع‌های ارجاعی نال‌نپذیر).
مطالب
آموزش TypeScript #1
با گسترش روز افزون زبان برنامه نویسی Javascript و استفاده هر چه بیشتر آن در تولید برنامه‌های تحت وب این زبان به یکی از قدرت‌های بزرگ در تولید برنامه‌های مبتنی بر وب تبدیل شده است. ترکیب این زبان با Css و Html5 تقریبا هر گونه نیاز برای تهیه و توسعه برنامه‌های وب را حل کرده است. جاوا اسکریپت در ابتدا برای اسکریپت نویسی سمت کلاینت برای صفحات وب ایجاد شد و برای سال‌ها به‌عنوان ابزاری برای مدیریت کردن رویدادهای صفحات وب محدود شده بود  و در نتیجه بسیاری از امکانات لازم برای برنامه‌نویسی برنامه‌های مقیاس بزرگ را به‌همراه نداشت. امروزه به قدری Javascript  توسعه داده شده است که حتی در تولید برنامه‌های Native مانند Windows Store  و برنامه‌های تحت Cloud نیز استفاده می‌شود. پیشرفت‌های صورت گرفته و اشاره شده در این حوزه موجب شد تا شاهد پیداش برنامه‌های مبتنی بر جاوا اسکریپت با سایزهای بی سابقه‌ای باشیم و این بیانگر این بود که تولید برنامه‌های مبتنی بر جاوا اسکریپت در مقیاس‌های بزرگ امر دشواری است و اینک TypeScript توسط غول نرم افزاری جهان پا به عرصه گذاشته که این فرآیند را آسان‌تر نماید. به کمک TypeScript می‌توان برنامه تحت JavaScript در مقیاس بزرگ تولید کرد به طوری با هر مرورگر و سیستم عاملی سازگار باشد. TypeScript از شی گرایی نیز پشتیبانی می‌کند و خروجی آن در نهایت به JavaScript کامپایل می‌شود. خیلی‌ها عقیده دارند که هدف اصلی مایکروسافت از تولید و توسعه این زبان رقابت با CoffeeScript است.  CoffeeScript یک زبان متن باز است که در سال 2009 توسط Jeremy Ashkenas ایجاد شده است و سورس آن در GitHub موجود می‌باشد. در آینده، بیشتر به مباحث مربوط به CoffeeScript و آموزش آن خواهم پرداخت.

در تصویر ذیل یک مقایسه کوتاه بین CoffeeScript و TypeScript را مشاهده می‌کنید.

با TypeScript چه چیزهایی به دست خواهیم آورد؟

یک نکته مهم این است که این زبان به خوبی در Visual Studio پشتیبانی می‌شود و قابلیت Intellisense نوشتن برنامه به این زبان را دلپذیرتر خواهد کرد و از طرفی دیگر به نظر من یکی از مهم‌ترین مزیت هایی که TypeScript در اختیار ما قرار می‌دهد این است که می‌توانیم به صورت Syntax آشنای شی گرایی کد نویسی کنیم و خیلی راحت‌تر کد‌های خود را سازمان دهی کرده و از نوشتن کد‌های تکراری اجتناب کنیم.

یکی دیگر از مزیت‌های مهم این زبان این است که این زبان از Static Typing به خوبی پشتیبانی می‌کند. این بدین معنی است که شما ابتدا باید متغیر‌ها را تعریف کرده و نوع آن‌ها را مشخص نمایید و هم چنین در هنگام پاس دادن مقادیر به پارامتر‌های توابع باید حتما به نوع داده ای آن‌ها دقت داشته باشید چون کامپایلر بین انواع داده ای در TypeScript تمایز قایل است و در صورت رعایت نکردن این مورد شما با خطا مواجه خواهید شد. این تمایز قایل شدن باعث می‌شود که برنامه هایی خواناتر داشته باشیم از طرفی باعث می‌شود که خطا یابی و نوشتن تست برای برنامه راحت‌تر و تمیزتر باشد. بر خلاف JavaScript، در TypeScript(به دلیل پشتیبانی از شی گرایی) می‌توانیم علاوه بر داشتن کلاس، اینترفیس نیز داشته باشیم و در حال حاضر مزایای استفاده از اینترفیس بر کسی پوشیده نیست.

به دلیل اینکه کد‌های TypeScript ابتدا کامپایل شده و بعد تبدیل به کد‌های JavaScript می‌شوند در نتیجه قبل از رسیدن به مرحله اجرای پروژه، ما از خطاهای موجود در کد خود مطلع خواهیم شد.

البته این نکته را نیز فراموش نخواهیم کرد که این زبان تازه متولد شده است(سال 2012 توسط Anders Hejlsberg) و همچنان در حال توسعه است و این در حال حاضر مهم‌ترین عیب این زبان می‌تواند باشد چون هنوز به پختگی سایر زبان‌های اسکریپتی در نیامده است.

در ذیل یک مثال کوچک به زبان TypeScript و JavaScript را برای مقایسه در خوانایی و راحتی کد نویسی قرار دادم:

TypeScript:

class Greeter {
    greeting: string;

    constructor (message: string) {
        this.greeting = message;
    }

    greet() {
        return "Hello, " + this.greeting;
    }
}
بعد از کامپایل کد بالا به کدی معادل زیر در JavaScript تبدیل خواهد شد:
var Greeter = (function () {
    function Greeter(message) {
        this.greeting = message;
    }
    Greeter.prototype.greet = function () {
        return "Hello, " + this.greeting;
    };
    return Greeter;
})();
توضیح چند واژه در TypeScript

Program : یک برنامه TypeScript مجموعه ای از یک یا چند Source File است. این Source File‌ها شامل کد‌های پیاده سازی برنامه هستند ولی در خیلی موارد برای خوانایی بیشتر برنامه می‌توان فقط تعاریف را در این فایل‌های سورس قرار داد.
Module: ماژول در TypeScript شبیه به مفاهیم فضای نام یا namespace در دات نت است و می‌تواند شامل چندین کلاس یا اینترفیس باشد.
Class : مشابه به مفاهیم کلاس در دات نت است و دقیقا همان مفهوم را دارد. یک کلاس می‌تواند شامل چندین تابع و متغیر با سطوح دسترسی متفاوت باشد. در TypeScript مجاز به استفاده از کلمات کلیدی public و private نیز می‌باشید. یک کلاس در Typescript می‌تواند یک کلاس دیگر را توسعه دهد(ارث بری در دات نت) و چندین اینترفیس را پیاده سازی نماید.
Interface: یک اینترفیس فقط شامل تعاریف است و پیاده سازی در آن انجام نخواهد گرفت. یک اینترفیس می‌تواند چندین اینترفیس دیگر را توسعه دهد.
Function: معادل متد در دات نت است. می‌تواند پارامتر ورودی داشته باشد و در صورت نیاز یک مقدار را برگشت دهد.
Scope: دقیقا تمام مفاهیم مربوط به محدوده فضای نام و کلاس و متد در دات نت در این جا نیز صادق است. 


آماده سازی Visual Studio برای شروع به کار
در ابتدا باید Template مربوطه به TypeScript را نصب کنید تا از طریف VS.Net بتوانیم به راحتی به این زبان کد نویسی کنیم. می‌توانید فایل نصب را از اینجا دانلود کنید. بعد از نصب از قسمت Template‌های موجود گزینه Html Application With TypeScript را انتخاب کنید

یا از قسمت Add  در پروژه‌های وب خود نظیر MVC گزینه TypeScript File را انتخاب نمایید.


در پست بعدی کد نویسی با این زبان را آغاز خواهیم کرد. 

اشتراک‌ها
فناوری‌هایی برای مطالعه در سال 2017

- .NET Core
- Node.js
- Docker
- Elasticsearch: A distributed and open source search engine based on Lucene. A blazing fast NoSQL database with replication capabilities, it is the most widely known component of the ELK stack, together with Kibana (for reporting and visualizations), Logstash (for data import) and Beats (for data shipping). Even Azure Search uses it behind the covers. Free but some tools are paid. Get it from http://elastic.co.
- ECMAScript 2015
- HTML5
- Kafka
- TypeScript
- MongoDB
- Git
- Nginx
- Octopus Deploy
- Azure
- Amazon Web Services
- Linux
- Visual Studio Code
- Xamarin
- Google Analytics
- SQL Server 2016
- Let’s Encrypt
- TensorFlow
- GitLab
- Redis 

فناوری‌هایی برای مطالعه در سال  2017
نظرات مطالب
بومی سازی تاریخ و اعداد در جاوا اسکریپت در سال 2020
یک نکته‌ی تکمیلی: روش سفارشی سازی خروجی نهایی تاریخ

همانطور که در متن نیز عنوان شد، خروجی تبدیل زیر
const date = new Date(Date.UTC(2020, 1, 20, 3, 0, 0, 200));
const faDate = new Intl.DateTimeFormat("fa", {
   weekday: "long",
   year: "numeric",
   month: "long",
   day: "numeric"
}).format(date);
console.log(faDate);
معادل «۱۳۹۸ اسفند ۱, پنجشنبه» است که ... آنچنان مطلوب نیست. در یک چنین حالتی برای دسترسی به اجزای خروجی این فرمت کننده‌، می‌توان از متد استاندارد formatToParts استفاده کرد:
const date = new Date(Date.UTC(2020, 1, 20, 3, 0, 0, 200));
const faDateParts = new Intl.DateTimeFormat("fa", {
  weekday: "long",
  year: "numeric",
  month: "long",
  day: "numeric"
}).formatToParts(date);
console.log(faDateParts);
که این خروجی را باز می‌گرداند:
[​
  { type: "year", value: "۱۳۹۸" },
 ​ { type: "literal", value: " " },
 ​ { type: "month", value: "اسفند" },
 ​ { type: "literal", value: " " },
 ​ { type: "day", value: "۱" },
 ​ { type: "literal", value: ", " },
 ​ { type: "weekday", value: "پنجشنبه" }​
]
که آرایه‌ای است از اشیاء type و value. اکنون با استفاده از قطعه کد زیر، این آرایه را تبدیل به یک شیء می‌کنیم که نام هر خاصیت آن، یک type است و مقدار آن value شیء متناظر:
const { year, literal, month, day, weekday } = Object.fromEntries(
  new Intl.DateTimeFormat("fa", {
    weekday: "long",
    year: "numeric",
    month: "long",
    day: "numeric"
  })
    .formatToParts(date)
    .map(item => [item.type, item.value])
);
سپس با استفاده از Objects Destructuring این شیء را به چند متغیر نسبت داده‌ایم. اکنون با دسترسی به مقادیر سال و ماه و غیره، هر طور که نیاز بود می‌توان آن‌ها را فرمت کرد. برای مثال:
const faDate = `${weekday}${literal}${day} ${month} ${year}`;
console.log(faDate);
با این خروجی:
«پنجشنبه, ۱ اسفند ۱۳۹۸»
مطالب
Angular Animation – بخش دوم

در قسمت قبل کلیات نحوه‌ی استفاده از Animation در Angular را مورد بررسی قرار دادیم. در این بخش قصد داریم نحوه‌ی اعمال Animation ‌های پیشرفته‌تری را مورد بررسی قرار دهیم. 


وضعیت void

این وضعیت به تمامی المانهایی که به view متصل نیستند، اعمال خواهد شد. این عدم اتصال به view برای یک المان می‌تواند بخاطر این باشد که این المان هنوز به صفحه وارد نشده است یا اینکه قبلا در صفحه بوده و الان در حال حذف شدن است.

درکل وضعیت void برای تعریف انیمیشنی در هنگام ورود و خروج المان به و از صفحه مورد استفاده قرار می‌گیرد. برای مثال گذار *=>void به تمامی المانهایی که view را ترک می‌کنند اعمال خواهد شد و void=>* به المانهایی که به view اضافه می‌شوند. 

قطعه کد زیر سبب تعریف انیمیشنی بر روی المنتهای ورودی و خروجی از صفحه خواهد شد: 

animations: [
  trigger('flyInOut', [
    transition('void => *', [
      style({transform: 'translateX(-100%)'}),
      animate(100)
    ]),
    transition('* => void', [
      animate(100, style({transform: 'translateX(100%)'}))
    ])
  ])
]

در این قطعه کد یک trigger به نام flyInOut تعریف شده است که در آن برای گذار ورود و خروج المنت در صفحه، انیمیشن تعریف شده است. همانطور که واضح است نیازی به تعریف حالت void، توسط تابع state وجود ندارد.

کد زیر نحوه استفاده از این trigger را نشان میدهد (با فرض اینکه لیستی از کاربران را در متغییر users داریم که با فراخوانی متد addNewUser یک آیتم به آن اضافه شده و با زدن دکمه Remove آیتم مورد نظر از لیست حذف می‌شود):

<ul>
  <li *ngFor="let user of users" [@flyInOut]>
    {{user.FirstName}}
    <button (click)="remove(user)">Remove</button>
    </li>
</ul>
<button (click)="addNewUser()">Add New User</button>

همچنین به جای void=>* در تابع transition، از :enter و به جای *=>void، از :leave می‌توان استفاده کرد. 

transition(':enter', [ ... ]); // void => *
transition(':leave', [ ... ]); // * => void

واضح است که شما می‌توانید از حالت void به هر حالت تعریف شده‌ی توسط خودتان نیز گذاری را تعریف کنید. برای مثال اگر قبلا حالت active و inactive را با استفاده از تابع state ساخته باشید، گذارهای زیر قابل تعریف خواهند بود و هیچگونه محدودیتی وجود نخواهد داشت:

transition('void => inactive', //...)

transition('inactive => void', //...)

transition('void => active', //..)

transition('active => void', //...)


کاربرد * در style

فرض کنید می‌خواهیم گذاری را تعریف کنیم که هنگام ورود المنت، در ابتدا ارتفاع المنت را به مقداری 0px تنظیم کرده و سپس همراه با یک انیمیشن، مقدار ارتفاع را به مقدار اصلی تنظیم خواهد کرد. چالشی که در اینجا وجود دارد این است که مقدار ارتفاع المنت مشخص نیست و بستگی به اندازه صفحه نمایش داشته و توسط آن css تنظیم خواهد شد. در اینجا می‌توان از * برای بدست آورن مقدار جاری یک خصوصیت از استایل استفاده کرد:

transition('void => *', [
   style({height: 0 }),
   animate(1000,style({ color: '*' }))
]),


انیمیشن چند مرحله‌ای با استفاده از Keyframes

تا اینجا تمامی انیمیشنهایی را که بررسی کردیم، یک انیمیشن یک مرحله‌ای بودند. در صورتیکه یک انیمیشن حرفه‌ای، متشکل از چند مرحله گذار خواهد بود. برای انجام اینکار از تابع Keyframes استفاده می‌کنیم. برای مثال می‌خواهیم انیمیشن ورود المنت را به صورتی در نظر بگیریم که المنت در ابتدا در نقطه -75% بالاتر از مکانی‌که در آنجا نمایش داده خواهد شد، با opacity صفر شروع  به حرکت کرده و در مرحله بعد به نقطه 35px پائین‌تر از مکان اصلی خود آمده و opacity نیم را خواهد داشت و در نهایت، با حرکت بعدی به جای اصلی خود خواهد رفت و opacity یک را پیدا می‌کند. 

animations: [
  trigger('flyInOut', [
    transition('void => *', [
      animate(300, keyframes([
        style({opacity: 0, transform: 'translateY(-75%)', offset: 0}),
        style({opacity: 0.5, transform: 'translateY(35px)',  offset: 0.3}),
        style({opacity: 1, transform: 'translateY(0)',     offset: 1.0})
      ]))
    ])    
  ])
]

تابع Keyframes آرایه‌ای از تابع style را دریافت می‌کند که هر تابع شامل خصوصیتهای انیمیشن به همراه یه خصوصیت offset است. این خصوصیت اختیاری است و مقدار صفر تا یک را قبول می‌کند و بیانگر زمان اجرای تابع style بعدی است.


رخداد شروع و پایان انیمیشن

با استفاده از @triggerName.start و @triggerName.done با شروع و پایان انیمیشن خود می‌توانید یک تابع سفارشی را نیز اجرا کنید. برای مثال کد زیر را در نظر بگیرید: 

template: `
  <ul>
    <li *ngFor="let hero of heroes"
        (@flyInOut.start)="animationStarted($event)"
        (@flyInOut.done)="animationDone($event)"
        [@flyInOut]="'in'">
      {{hero.name}}
    </li>
  </ul>
`,

در این مثال هنگام شروع انیمیشن تابع animationStarted و پس از اتمام انیمیشن، تابع animationDone اجرا خواهند شد. 

اشتراک‌ها
سوالاتی که قبل از مهاجرت به کلاد باید از خود بپرسید

Cloud Computing is currently the hot topic in the developer world these days, and it seems all anyone wants to talk about is the cloud. If you're like me you signed up for something like Windows Azure just to see what the hype was all about. There are a lot of good reasons to move an app to the cloud, but it's still not for everyone. There are some things you need to think about before taking this gamble with your app.  

سوالاتی که قبل از مهاجرت به کلاد باید از خود بپرسید
نظرات مطالب
اعتبارسنجی مبتنی بر کوکی‌ها در ASP.NET Core 2.0 بدون استفاده از سیستم Identity
- یکی برای هدرهای کوکی است و یکی برای تنظیم مشخصات توکن.
The TimeSpan after which the authentication ticket stored inside the cookie expires. 
ExpireTimeSpan is added to the current time to create the expiration time for the ticket. 
The ExpiredTimeSpan value always goes into the encrypted AuthTicket verified by the server. 
It may also go into the Set-Cookie header, but only if IsPersistent is set. 
To set IsPersistent to true, configure the AuthenticationProperties passed to SignInAsync. 
The default value of ExpireTimeSpan is 14 days.
مطالب
دریافت مناسبت‌های سال 1388 از یک فایل XML

همیشه با نزدیک شدن آخر سال، به روز کردن مناسبت‌های تقویم سال بعد ضروری می‌شود. دوستان لینوکسی ما هم در این مورد زحمت کشیده و برنامه‌ای را تهیه کرده‌اند که از آدرس زیر قابل دریافت است:
http://download.gna.org/jalali-calendar/

پس از دریافت برنامه، مناسبت‌های سال 1388 در فایل 1388.xml قابل مشاهده است (با تقدیر و تشکر از زحمات این عزیزان). فرض کنید می‌خواهیم این اطلاعات را به اس کیوال سرور منتقل کنیم.
فرمت این فایل به شکل زیر است:

<?xml version="1.0" encoding="UTF-8"?>
<cal1388>
<day>
<num>1/1</num>
<desc>عید نوروز، لحظه تحویل سال:ساعت 15 و 13 دقیقه و 39 ثانیه </desc>
</day>
</cal1388>

حداقل سه راه حل برای انجام اینکار (خواندن فایل xml توسط اس کیوال سرور) موجود است:

راه اول:

SELECT '1388' saal,
X.day.query('num').value('.', 'nVARCHAR(50)') rooz_maah,
X.day.query('desc').value('.', 'nVARCHAR(max)') tozih
FROM (
SELECT CAST(x AS XML)
FROM OPENROWSET(
BULK
'c:\1388.xml',
SINGLE_BLOB
) AS T(x)
) AS T(x)
CROSS APPLY x.nodes('cal1388/day') AS X(day);

راه دوم:

DECLARE @MyXML XML

SELECT @MyXML = CAST(x AS XML)
FROM OPENROWSET(
BULK
'c:\1388.xml',
SINGLE_BLOB
) AS T(x)

SELECT 1388 saal,
nref.value('num[1]', 'nvarchar(50)') rooz_maah,
nref.value('desc[1]', 'nvarchar(max)') tozih

FROM @MyXML.nodes('//day') AS R(nref)

راه سوم:
DECLARE @MyXML XML
DECLARE @handle INT

SELECT @MyXML = CAST(x AS XML)
FROM OPENROWSET(
BULK
'c:\1388.xml',
SINGLE_BLOB
) AS T(x)

EXEC sp_xml_preparedocument @handle OUTPUT,
@MyXML

SELECT 1388 saal,
*
FROM OPENXML(@handle, '/cal1388/day', 2) WITH
(num VARCHAR(20), [desc] NVARCHAR(MAX))

EXEC sp_xml_removedocument @handle

اکنون که می‌توانیم اطلاعات این فایل را select کنیم، Insert آن ساده است . برای مثال:
INSERT INTO tblMonasebat
(
saal,
rooz_mah,
tozih
)
SELECT '1388' saal,
nref.value('num[1]', 'nvarchar(50)') rooz_maah,
nref.value('desc[1]', 'nvarchar(max)') tozih
FROM @MyXML.nodes('//day') AS R(nref)

بدیهی است امکان مقدار دهی @MyXML به صورت یک رشته که حاوی محتویات فایل است نیز مهیا می‌باشد (بجای خواندن از فایل).

برای مطالعه‌ی بیشتر
XML Support in Microsoft SQL Server 2005
Beginning SQL Server 2005 XML Programming