مطالب
زیرنویس فارسی ویدئوهای مقدمات AngularJS - قسمت پنجم
زیرنویس‌های فارسی قسمت پنجم را از اینجا می‌توانید دانلود کنید.
لیست سرفصل‌های قسمت پنجم به شرح زیر است:
01-Introduction to Directives
02-Demo. Creating Your First Directive
03-Demo. Domain Specific Language via Custom Elements
04-Demo. Isolating Directive Scope
05-Demo. Exploring Isolate Scope Bindings
06-Demo. Handling Events with Directives
07-Demo. Observing and Responding to Changes
08-Demo. Using Controllers within Directives
09-Demo. Sharing Directive Controllers via Require
10-Demo. Directive Priority and using Terminal
11-Demo. Using Require with Nested Directives
12-Demo. Understanding Transclusion
13-Demo. Using Compile to Transform the DOM
14-Demo. Making jQuery More Explicit with Directives
15-Summary
در این قسمت به مبحث ایجاد دایرکتیوهای سفارشی پرداخته می‌شود. دایرکتیوها در واقع مهمترین قسمت هر برنامه انگولار هستند. انگولار به صورت توکار شامل تعداد زیادی دایرکتیو می‌باشد. در واقع می‌توانیم بگوئیم دایرکتیو می‌تواند یک سینتکس جدید باشد که دارای یک رفتار مخصوص می‌باشد. برای مثال، static HTML هیچ دیدی نسبت به ایجاد و نمایش یک ویجت انتخابگر تاریخ(Date Picker) ندارد. برای اینکار باید به HTML، این سینتکس جدید را توسط دایرکتیوها آموزش دهیم.
مطالب
ساخت یک مثال Todo با MobX و React

پیشنیاز این مطلب مطالعه قسمت MobX می‌باشد. در این مثال قصد داریم  یک برنامه‌ی Todo را با استفاده از MobX و React ایجاد کنیم.


ایجاد ساختار ابتدایی پروژه

برای ساخت پروژه، به خط فرمان مراجعه کرده و با دستور زیر، یک پروژه‌ی react از نوع typescript را ایجاد می‌کنیم. 

npx create-react-app todo-mobx --template typescript 
cd todo-mobx


برای توسعه‌ی این مثال، از محیط توسعه‌ی VSCode استفاده می‌کنیم. اگر VSCode بر روی سیستم شما نصب باشد، در همان مسیری که خط فرمان باز است، دستور زیر را اجرا کنید؛ پروژه‌ی شما در VSCode باز می‌شود:

code


سپس در محیط VSCode، دکمه‌های ctrl+` را فشرده (ctrl+back-tick) و دستورات زیر را در ترمینال ظاهر شده وارد کنید:

npm install --save-dev typescript @types/node @types/react @types/react-dom @types/jest
npm install  mobx mobx-react-lite --save


در ادامه برای استایل بندی بهتر برنامه از کتابخانه‌های bootstrap و  font-awesome استفاده می‌کنیم: 

npm install bootstrap --save
npm install font-awesome --save

سپس فایل index.tsx را باز کرده و دو خط زیر را به آن اضافه می‌کنیم: 

import "bootstrap/dist/css/bootstrap.css";
import "font-awesome/css/font-awesome.css";


کتابخانه‌ی MobX، از تزئین کننده‌ها یا decorators استفاده می‌کند. بنابراین نیاز است به tsconfig پروژه مراجعه کرده و خط زیر را به آن اضافه کنیم:  

"compilerOptions": {
   .... ,
   "experimentalDecorators": true
}


ایجاد مخازن حالت MobX

در ادامه نیاز است store‌های MobX را ایجاد کنیم و بعد آن‌ها را به react اتصال دهیم. بدین منظور یک پوشه‌ی جدید را در مسیر src، به نام stores ایجاد می‌کنیم و سپس فایل جدیدی را به نام todo-item.ts در آن با محتوای زیر ایجاد می‌کنیم: 

import { observable, action } from "mobx";

export default class TodoItem {
    id = Date.now();

    @observable text: string = '';
    @observable isDone: boolean = false;

    constructor(text: string) {
        this.text = text;
    }

    @action
    toggleIsDone = () => {
        this.isDone = !this.isDone
    }

    @action
    updateText = (text: string) => {
        this.text = text;
    }
}


در همان مسیر stores، فایل دیگری را نیز به نام todo-list.ts، با محتوای زیر ایجاد می‌کنیم:

import { observable, computed, action } from "mobx";

import TodoItem from "./todo-item";

export class TodoList {
    @observable.shallow list: TodoItem[] = [];

    constructor(todos: string[]) {
        todos.forEach(this.addTodo);
    }

    @action
    addTodo = (text: string) => {
        this.list.push(new TodoItem(text));
    }

    @action
    removeTodo = (todo: TodoItem) => {
        this.list.splice(this.list.indexOf(todo), 1);
    };

    @computed
    get finishedTodos(): TodoItem[] {
        return this.list.filter(todo => todo.isDone);
    }

    @computed
    get openTodos(): TodoItem[] {
        return this.list.filter(todo => !todo.isDone);
    }
}

توضیحات:

مفهوم observable@: کل شیء state را به صورت یک شیء قابل ردیابی JavaScript ای ارائه می‌کند.

مفهوم computed@: این نوع خواص، مقدار خود را زمانیکه observable‌های وابسته‌ی به آن‌ها تغییر کنند، به روز رسانی می‌کنند.

مفهوم action@: جهت به روز رسانی state و سپس نمایش تغییرات یا نمایش نمونه‌ی دیگری در DOM می‌باشند.



برپایی Context
در این مثال از شیء Provider خود MobX استفاده نمی‌کنیم؛ بلکه از React Context استفاده می‌کنیم. به همین جهت در مسیر src، یک پوشه‌ی جدید دیگر را به نام Providers ایجاد می‌کنیم. سپس فایلی را به نام store-provider.ts ایجاد کرده و کدهای زیر را به آن اضافه می‌کنیم: 
import { createContext, useContext } from "react";
import { TodoList } from "../stores/todo-list";

export const StoreContext = createContext<TodoList>({} as TodoList);
export const StoreProvider = StoreContext.Provider;

export const useStore = (): TodoList => useContext(StoreContext);
توضیحات:
- در اینجا StoreContext را ایجاد کرده و سپس به آن یک مقدار پیش فرض از نوع یک object خالی را ارسال کرده‌ایم.
- سپس بر اساس آن، شیء StoreProvider را که از نوع ReactConxtext می‌باشد، ایجاد کردیم. 
- متد useStore که به صورت export و نوعی از useContext می‌باشد، برای دسترسی ساده‌تر به Context معرفی شده‌است که در ادامه کاربرد آن‌را خواهید دید.
- برای اعمال StoreProvider در شروع کننده‌ی برنامه React، به فایل index.tsx مراجعه کرده و آن‌را به صورت زیر ویرایش می‌کنیم: 
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';
import "bootstrap/dist/css/bootstrap.css";
import "font-awesome/css/font-awesome.css";
import { TodoList } from './stores/todo-list';
import { StoreProvider } from './providers/store-provider';


const todoList = new TodoList([
    'Read Book',
    'Do exercise',
    'Watch Walking dead series'
]);

ReactDOM.render(
    <StoreProvider value={todoList}>
        <App />
    </StoreProvider>
    , document.getElementById('root'));

// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.unregister();
توضیحات:  StoreProvider ای را که در فایل store-provider.ts ایجاد کردیم، در اینجا به شروع کننده‌ی React معرفی می‌کنیم و سه مقدار پیش فرض را نیز به آن اعمال می‌کنیم.

افزودن کامپوننت‌های برنامه
برای نمایش لیست Todo‌ها و عملیات حذف، اضافه و ویرایش، نیاز به سه کامپوننت تابعی را داریم: 

اضافه کردن کامپوننت TodoNew
در مسیر src، یک پوشه‌ی جدید را به نام components ایجاد می‌کنیم. سپس فایلی را در آن به نام TodoNew.tsx ایجاد کرده و کدهای زیر را به آن اضافه می‌کنیم: 
import React, { useState } from 'react';
import { useStore } from '../providers/store-provider';

export const TodoNew = () => {
    const [newTodo, setTodo] = useState('');
    const todoList = useStore();

    const addTodo = () => {
        todoList.addTodo(newTodo);
        setTodo('');
    };

    return (

        <div className="input-group mb-3">
            <input type="text" className="form-control" placeholder="Add To do" value={newTodo} onChange={(e) => setTodo(e.target.value)} />
            <div className="input-group-append">
                <button className="btn btn-success" type="submit" onClick={addTodo}>Add Todo</button>
            </div>
        </div>
    )
};
توضیحات: 
- useStore ای را که در مرحله‌ی قبل ایجاد کردیم، در اینجا برای دسترسی به state‌های MobX استفاده می‌کنیم.
- در input و رویداد onChange آن، مقدار ورودی کاربر را به متد newTodo اعمال می‌کنیم و بعد از اینکه کاربر دکمه‌ی Add Todo را زد، مقدار newTodo را به تابع addTodo که در useStore می‌باشد، اعمال می‌کنیم.

افزودن کامپوننت نمایش لیست کارها: TodoList
در مسیر src و پوشه‌ی components آن، فایل جدیدی را به نام TodoList.tsx ایجاد کرده و کدهای زیر را به آن اضافه می‌کنیم: 
import React from 'react';

import { TodoItem } from "./TodoItem";
import { useObserver } from "mobx-react-lite";
import { useStore } from '../providers/store-provider';

export const TodoList = () => {
    const todoList = useStore();

    return useObserver(() => (
        <div>
            <h1>Open Todos</h1>
            <table className="table">
                <thead className="thead-dark">
                    <tr>
                        <th>Name</th>
                        <th className="text-left">Do It?</th>
                        <th>Actions</th>
                    </tr>
                </thead>
                <tbody>
                    {
                        todoList.openTodos.map(todo =>
                            <tr key={`${todo.id}-${todo.text}`}>
                                <TodoItem todo={todo} />
                            </tr>)
                    }

                </tbody>
            </table>

            <h1>Finished Todos</h1>
            <table className="table">
                <thead className="thead-light">
                    <tr>
                        <th>Name</th>
                        <th className="text-left">Do It?</th>
                        <th>Actions</th>
                    </tr>
                </thead>
                <tbody>
                    {
                        todoList.finishedTodos.map(todo =>
                            <tr key={`${todo.id}-${todo.text}`}>
                                <TodoItem todo={todo} />
                            </tr>)
                    }

                </tbody>
            </table>
        </div>
    ));
};
توضیحات:
- useStore را به ثابت todoList انتساب می‌دهیم.
- سپس برای نمایش Todo ‌ها، یک جدول را طراحی می‌کنیم و همچنین برای نمایش کارهای تکمیل شده (Finish Todo) جدول دیگری را ایجاد می‌کنیم.
- در کلاس TodoList، که پیشتر آن‌را ایجاد کردیم، از دو خاصیت openTodos و finishedTodos از نوع get که با Decorator از نوع computed@ هستند، برای نمایش Open Todos و Finished Todos استفاده می‌کنیم. خروجی این خواص، لیستی از نوع TodoItem می‌باشند که با کمک متد map، به فیلد‌های TodoItem آن‌ها دسترسی پیدا می‌کنیم.

برای منظم کردن کدها، کامپوننت دیگری را در مسیر src/components به نام TodoItem.tsx ایجاد کرده و کدهای زیر را به آن اضافه می‌کنیم: 
import React, { useState } from 'react';
import TodoItemClass from "../stores/todo-item";


import { useStore } from '../providers/store-provider';

interface Props {
    todo: TodoItemClass;
}

export const TodoItem = ({ todo }: Props) => {
    const todoList = useStore();
    const [newText, setText] = useState('');
    const [isEditing, setEdit] = useState(false);

    const saveText = () => {
        todo.updateText(newText);
        setEdit(false);
        setText('');
    };

    return (
        <React.Fragment>
            {
                isEditing ?
                    <React.Fragment>
                        <td>
                            <input className="form-control" placeholder={todo.text} type="text" onChange={(e) => setText(e.target.value)} />
                        </td>
                        <td></td>
                        <td>
                            <button className="btn btn-xs btn-success " onClick={saveText}>Save</button>
                        </td>
                    </React.Fragment>
                    :
                    <React.Fragment>
                        <td>
                            {todo.text}
                        </td>

                        <td className="text-left">
                            <input className="form-check-input" type="checkbox" onChange={todo.toggleIsDone} defaultChecked={todo.isDone}></input>
                        </td>
                        <td>
                            <button className="btn btn-xs btn-warning " onClick={() => setEdit(true)}>
                                <i className="fa fa-edit"></i>
                            </button>
                            <button className="btn btn-xs btn-danger ml-2" onClick={() => todoList.removeTodo(todo)}>
                                <i className="fa fa-remove"></i>
                            </button>
                        </td>
                    </React.Fragment>
            }

        </React.Fragment>

    )
};
توضیحات:
- در کامپوننت قبلی TodoList.tsx، متدهای TodoItem را به کامپوننت TodoItem.tsx پاس داده و آن را در دو حالت ویرایش و نمایش، نشان می‌دهیم.
- در جدول، امکان ویرایش، حذف و ثبت رکوردها را قرار داده‌ایم. برای ویرایش، مقدار input وارد شده را به متد (todo.updateText(newText پاس می‌دهیم و برای حذف، (todoList.removeTodo(todo را فراخوانی می‌کنیم.
 
کدهای کامل این قسمت را از اینجا می‌توانید دریافت کنید  Github
اشتراک‌ها
ILSpy 8.0 منتشر شد

New Language Features
C# 10: record structs
C# 11: Required members
C# 11: ref fields
C# 10: Support DefaultInterpolatedStringHandler
Output attributes on lambda expressions
Updated pattern detection for Roslyn 4.4.0
 

ILSpy 8.0 منتشر شد
اشتراک‌ها
راهنمای کامل عملکرد Angular Runtime

In this guide, we will describe how to meet the expectations of performance-sensitive applications, explain the relevant parts of Angular change detection, and highlight potential pitfalls along the way. 

راهنمای کامل عملکرد Angular Runtime
اشتراک‌ها
Postsharp نسخه 4 منتشر شد

4x runtime performance enhancement on our NotifyPropertyChanged aspect.
Improved reliability and scope of our deadlock detection policy.
Dynamic advices: see IAdviceProvider, IntroduceInterface, ImportLocation, ImportMethod, IntroduceMethod.
Aspect Repository and Late Validation.
OnInstanceConstructed advice.
Faster advice state lookup: see DeclarationIdentifier.

Postsharp نسخه 4 منتشر شد