اشتراکها
اشتراکها
مجموعه آیکن های وب با کیفیت بالا
اشتراکها
ارائه ReactJS Native
React Native for Android has been released by Facebook, providing Android developers with a way to create apps in JavaScript.
اشتراکها
نگاهی به Telerik NativeScript
مطالب
خواندنیهای 19 خرداد
توسعه وب
دات نت فریم ورک
متفرقه
مشکل:
و فراخوانی این فایل را در انتهای قسمت body فایل index.html یا Host.cshtml_ بصورت زیر قرار میدهیم:
و حالا که پروژه را اجرا کنید، رویداد کلیک بر روی دکمهی toggle کار نمیکند!
در مثال بالا من دستورات را داخل یک تابع به نام initilizeNiceAdminJs قرار دادم. سپس در فایل index.razor این تابع را در رویداد OnAfterRenderAsync فراخوانی مینماییم:
ممکن است بخواهید در برنامههای Blazor از یک قطعه کد آماده استفاده نمایید که در آن از دستورات Javascript استفاده شده باشد و تعدادی رویداد برای المانهای صفحه تعریف کرده باشند؛ به عنوان مثال من از قالب آماده Nice Admin استفاده میکنم که در آن برای تمام قالب، از یک فایل به نام main.js استفاده شدهاست و در آن برای مخفی و ظاهر نمودن منو، از یک دکمه toggle استفاده کردهاست. برای این عملیات، یک رویداد کلیک در این فایل تعریف شده:
/** * Template Name: NiceAdmin - v2.1.0 * Template URL: https://bootstrapmade.com/nice-admin-bootstrap-admin-html-template/ * Author: BootstrapMade.com * License: https://bootstrapmade.com/license/ */ (function() { "use strict"; /** * Easy selector helper function */ const select = (el, all = false) => { el = el.trim() if (all) { return [...document.querySelectorAll(el)] } else { return document.querySelector(el) } } /** * Easy event listener function */ const on = (type, el, listener, all = false) => { if (all) { select(el, all).forEach(e => e.addEventListener(type, listener)) } else { select(el, all).addEventListener(type, listener) } } /** * Easy on scroll event listener */ const onscroll = (el, listener) => { el.addEventListener('scroll', listener) } /** * Sidebar toggle */ if (select('.toggle-sidebar-btn')) { on('click', '.toggle-sidebar-btn', function(e) { select('body').classList.toggle('toggle-sidebar') }) } /** * Search bar toggle */ if (select('.search-bar-toggle')) { on('click', '.search-bar-toggle', function(e) { select('.search-bar').classList.toggle('search-bar-show') }) } . . . })();
<!DOCTYPE html> <html dir="rtl"> . . . <body> <div id="app">Loading...</div> <div id="blazor-error-ui"> An unhandled error has occurred. <a href="">Reload</a> <a>🗙</a> </div> <script src="_framework/blazor.webassembly.js"></script> <!-- Vendor JS Files --> <script src="assets/vendor/bootstrap/js/bootstrap.bundle.js"></script> <script src="assets/vendor/php-email-form/validate.js"></script> <script src="assets/vendor/quill/quill.min.js"></script> <script src="assets/vendor/tinymce/tinymce.min.js"></script> <script src="assets/vendor/simple-datatables/simple-datatables.js"></script> <script src="assets/vendor/chart.js/chart.min.js"></script> <script src="assets/vendor/apexcharts/apexcharts.min.js"></script> <script src="assets/vendor/echarts/echarts.min.js"></script> <!-- Template Main JS File --> <script src="assets/js/main.js"></script> </body> </html>
دلیل:
مشکل به این دلیل میباشد که کدهای جاوا اسکریپتی، بلافاصله با دانلود فایل اجرا میشوند؛ در حالیکه بارگذاری صفحه هنوز توسط blazor به اتمام نرسیدهاست. در نتیجه المانهایی که در این فایل به آنها اشاره شدهاست، هنوز قابل دسترسی نیستند و رویدادهای تعریف شدهی برای آنها، اجرا نمیشوند.
راه حل:
باید اجرای کدهای جاوا اسکریپتی را تا بارگذاری کامل صفحه به تعویق بیاندازیم. برای همین منظور ابتدا کدهای تعریف شدهی در فایل main.js را بجای اینکه مستقیما اجرا شوند، در یک تابع قرار میدهیم:
/** * Template Name: NiceAdmin - v2.1.0 * Template URL: https://bootstrapmade.com/nice-admin-bootstrap-admin-html-template/ * Author: BootstrapMade.com * License: https://bootstrapmade.com/license/ */ function initilizeNiceAdminJs() { "use strict"; /** * Easy selector helper function */ const select = (el, all = false) => { el = el.trim() if (all) { return [...document.querySelectorAll(el)] } else { return document.querySelector(el) } } /** * Easy event listener function */ const on = (type, el, listener, all = false) => { if (all) { select(el, all).forEach(e => e.addEventListener(type, listener)) } else { select(el, all).addEventListener(type, listener) } } /** * Easy on scroll event listener */ const onscroll = (el, listener) => { el.addEventListener('scroll', listener) } /** * Sidebar toggle */ if (select('.toggle-sidebar-btn')) { on('click', '.toggle-sidebar-btn', function(e) { select('body').classList.toggle('toggle-sidebar') }) } /** * Search bar toggle */ if (select('.search-bar-toggle')) { on('click', '.search-bar-toggle', function(e) { select('.search-bar').classList.toggle('search-bar-show') }) } . . . }
@page "/" @inject IJSRuntime JSRuntime <div> this is index page </div> @code { protected override async Task OnAfterRenderAsync(bool firstRender) { if (firstRender) { await JSRuntime.InvokeVoidAsync("initilizeNiceAdminJs");// Initialize main.js after site completely loaded } } }
در قسمت 6، تمرینی را جهت پیاده سازی نمایش لیست یک سری فیلم، انجام دادیم. در اینجا قصد داریم این تمرین را جهت دریافت امتیاز و Like از کاربر، به ازای هر ردیف نمایش داده شده، تکمیل کنیم.
بررسی ساختار کامپوننت Like
در پوشهی components، ابتدا پوشهی جدید common را ایجاد میکنید. در اینجا تمام کامپوننتهای عمومی برنامه را که منحصر به دومین آن برنامه نیستند، قرار میدهیم. کامپوننتهایی را که اگر آنها را به برنامههای دیگری نیز کپی کردیم، بدون هیچ مشکلی قابلیت استفادهی مجدد را داشته باشند و متصل به سرویسها و زیرساخت برنامهی جاری نباشند. سپس در پوشهی common، فایل جدید src\components\common\like.jsx را ایجاد میکنیم و داخل آن توسط میانبرهای imrc و cc در VSCode، ساختار ابتدایی کامپوننت Like را ایجاد میکنیم.
ساختار کلی این کامپوننت به صورت زیر است:
- ورودی این کامپوننت به این صورت است که در آن مشخص شده آیا یک فیلم، مورد علاقه واقع شده یا خیر؛ مانند خاصیت liked که یک boolean است. اگر true باشد، یک آیکن قلب توپر را نمایش میدهد و برعکس.
- خروجی این کامپوننت نیز به صورت یک رخداد است. هر زمانیکه بر روی آیکن قلب آن کلیک میشود، این کامپوننت یک رخداد onClick را سبب خواهد شد. اکنون هر کامپوننت دیگری که در حال استفادهی از آن است، مطلع شده و خاصیت liked شیء مرتبط را تغییر میدهد.
فعلا ساختار ابتدایی آنرا به رندر یک قلب خالی که توسط قلم آیکنهای font-awesome تامین میشود، تنظیم میکنیم:
نمایش ابتدایی کامپوننت Like در جدول لیست فیلمها
فعلا مهم نیست که این کامپوننت کار خاصی را انجام نمیدهد. فقط قصد داریم آنرا در UI برنامه نمایش دهیم. به همین جهت ابتدا یک ستون جدید را مخصوص آن، در جدول فعلی نمایش لیست فیلمها، ایجاد کرده و المان آنرا درج میکنیم. برای این منظور به فایل movies.jsx مراجعه کرده و ابتدا این کامپوننت را import میکنیم:
سپس در سرستونهای جدول، یک th جدید را تعریف میکنیم تا ستونی برای درج آن ایجاد شود. همچنین در قسمت بدنهی جدول، پیش از دکمهی حذف، یک td مخصوص درج المان </Like> را اضافه میکنیم:
تا اینجا ستون جدید Like را مشاهده میکنید که کار رندر کامپوننتهای Like در آن انجام شدهاست.
واکنش نشان دادن به ورودیها، در کامپوننت Like
در ادامه باید این کامپوننت بر اساس مقدار Boolean ای که از والد خود دریافت میکند، یک آیکن قلب توپر و یا خالی را نمایش دهد. برای این منظور فعلا در کامپوننت movies، جائیکه المان کامپوننت Like درج شدهاست، ویژگی جدید liked را به مقدار ثابت true تنظیم میکنیم </Like liked={true}> تا بتوان قسمت props این کامپوننت را تکمیل کرد.
در کامپوننت Like، تفاوت بین آیکن قلب توپر و خالی در یک o- در انتهای کلاسهای font-awesome است:
در اینجا اگر بر اساس مقدار ورودی this.props.liked، یک مقدار false را دریافت کردیم، به classes یک o- را اضافه میکنیم تا یک آیکن قلب خالی را رندر کند. سپس این classes را به خاصیت className انتساب دادهایم.
پس از این تغییرات اگر برنامه را ذخیره کرده و مجددا در مرورگر بارگذاری کنیم، با توجه به تنظیم liked={true} در کامپوننت movies، ستون like آن با آیکنهای قلب توپر نمایش داده میشود که بیانگر واکنش نشان دادن صحیح به ورودیها در کامپوننت Like است:
پویا سازی مقدار پیشفرض ویژگی liked در کامپوننت movies
برای پویاسازی نمایش مقدار liked در کامپوننت movies، از آنجائیکه هر ردیف بیانگر یک شیء movie است، میتوان به این صورت عمل کرد:
البته اگر به فایل fakeMovieService.js مراجعه کنید، خاصیت liked در ساختار اشیاء فیلمها وجود ندارد که فعلا آنرا برای اولین شیء تعریف شده، اضافه میکنیم:
پس از این تغییرات، اکنون خروجی برنامه در مرورگر به صورت زیر تغییر کرده که اولین آیتم آن بر اساس مقدار تنظیم شدهی فوق، با آیکن قلب توپر نمایش داده شدهاست:
افزودن رخداد کلیک به کامپوننت Like
برای اینکه کامپوننت Like، رویداد کلیک بر روی آیکن قلب را به والد خود گزارش دهد، ابتدا ویژگی جدید onClick را بر روی تعریف المان آن در کامپوننت movies اضافه میکنیم:
که به متد handleLike در همان کامپوننت متصل خواهد شد:
سپس در کامپوننت Like، این ویژگی onClick را از طریق خاصیت props دریافت کرده و به رویداد onClick المان نمایش آیکن، متصل میکنیم:
اینبار اگر بر روی المان نمایش آیکن کلیک شود، سبب فراخوانی متد handleLike والد متصل به آن خواهد شد.
در اینجا همچنین style این المان نیز جهت نمایش cursor با آیکن pointer، توسط یک شیء از نوع inline style تنظیم شدهاست.
یک نکته: کامپوننت Like تا اینجا یک controlled component است؛ دارای state نیست و همچنین تمام اطلاعات خودش را از طریق props تامین میکند و تنها دارای یک متد render است. بنابراین اگر علاقمند بودید میتوان این کامپوننت را به یک «Stateless Functional Component» که در قسمت 8 معرفی شد نیز تبدیل کرد.
تغییر حالت کامپوننت Like جهت نمایش تغییرات
تا اینجا کامپوننت Like ما میتواند ورودی true/false را به آیکنهای متناظری تبدیل کند. همچنین اگر بر روی این آیکن کلیک شود، آنرا توسط رخدادی به والد خود اطلاع رسانی میکند. اکنون میخواهیم با تکمیل متد handleLike، خاصیت like اشیاء انتخابی (آیکنهایی که بر روی آنها کلیک شدهاند) را از true به false و برعکس تبدیل کرده و سپس UI را نیز به روز رسانی کنیم:
با یک چنین مثالی که در آن cloning اشیاء و آرایهها صورت میگیرد، پیشتر آشنا شدهاید. هدف از cloning، قطع ارتباط شیء، یا آرایهی ایجاد شده، از شیء، یا آرایهی اصلی است تا با اعمال تغییرات بر روی شیء clone شده، تغییری در شیء اصلی صورت نگیرد؛ چون در React مجاز به تغییر مستقیم اشیاء state نیستیم.
پس از این تغییرات اگر برنامه را اجرا کنیم، با کلیک بر روی هر آیکن، عکس آن آیکن نمایش داده میشود؛ برای مثال آیکن قلب توپر، تبدیل به آیکن قلب توخالی خواهد شد.
کدهای کامل این قسمت را از اینجا میتوانید دریافت کنید: sample-10.zip
بررسی ساختار کامپوننت Like
در پوشهی components، ابتدا پوشهی جدید common را ایجاد میکنید. در اینجا تمام کامپوننتهای عمومی برنامه را که منحصر به دومین آن برنامه نیستند، قرار میدهیم. کامپوننتهایی را که اگر آنها را به برنامههای دیگری نیز کپی کردیم، بدون هیچ مشکلی قابلیت استفادهی مجدد را داشته باشند و متصل به سرویسها و زیرساخت برنامهی جاری نباشند. سپس در پوشهی common، فایل جدید src\components\common\like.jsx را ایجاد میکنیم و داخل آن توسط میانبرهای imrc و cc در VSCode، ساختار ابتدایی کامپوننت Like را ایجاد میکنیم.
ساختار کلی این کامپوننت به صورت زیر است:
- ورودی این کامپوننت به این صورت است که در آن مشخص شده آیا یک فیلم، مورد علاقه واقع شده یا خیر؛ مانند خاصیت liked که یک boolean است. اگر true باشد، یک آیکن قلب توپر را نمایش میدهد و برعکس.
- خروجی این کامپوننت نیز به صورت یک رخداد است. هر زمانیکه بر روی آیکن قلب آن کلیک میشود، این کامپوننت یک رخداد onClick را سبب خواهد شد. اکنون هر کامپوننت دیگری که در حال استفادهی از آن است، مطلع شده و خاصیت liked شیء مرتبط را تغییر میدهد.
بنابراین این کامپوننت اطلاعی از ساختار یک شیء movie ندارد. تنها یک DOM کامپوننت ساده است که کارش نمایش یک آیکن قلب توپر یا خالی میباشد و اگر بر روی این آیکن قلب کلیک شد، به والد خود اطلاع رسانی میکند.
فعلا ساختار ابتدایی آنرا به رندر یک قلب خالی که توسط قلم آیکنهای font-awesome تامین میشود، تنظیم میکنیم:
import React, { Component } from "react"; class Like extends Component { render() { return <i className="fa fa-heart-o" aria-hidden="true"></i>; } } export default Like;
نمایش ابتدایی کامپوننت Like در جدول لیست فیلمها
فعلا مهم نیست که این کامپوننت کار خاصی را انجام نمیدهد. فقط قصد داریم آنرا در UI برنامه نمایش دهیم. به همین جهت ابتدا یک ستون جدید را مخصوص آن، در جدول فعلی نمایش لیست فیلمها، ایجاد کرده و المان آنرا درج میکنیم. برای این منظور به فایل movies.jsx مراجعه کرده و ابتدا این کامپوننت را import میکنیم:
import Like from "./common/like";
سپس در سرستونهای جدول، یک th جدید را تعریف میکنیم تا ستونی برای درج آن ایجاد شود. همچنین در قسمت بدنهی جدول، پیش از دکمهی حذف، یک td مخصوص درج المان </Like> را اضافه میکنیم:
تا اینجا ستون جدید Like را مشاهده میکنید که کار رندر کامپوننتهای Like در آن انجام شدهاست.
واکنش نشان دادن به ورودیها، در کامپوننت Like
در ادامه باید این کامپوننت بر اساس مقدار Boolean ای که از والد خود دریافت میکند، یک آیکن قلب توپر و یا خالی را نمایش دهد. برای این منظور فعلا در کامپوننت movies، جائیکه المان کامپوننت Like درج شدهاست، ویژگی جدید liked را به مقدار ثابت true تنظیم میکنیم </Like liked={true}> تا بتوان قسمت props این کامپوننت را تکمیل کرد.
در کامپوننت Like، تفاوت بین آیکن قلب توپر و خالی در یک o- در انتهای کلاسهای font-awesome است:
import React, { Component } from "react"; class Like extends Component { render() { let classes = "fa fa-heart"; if (!this.props.liked) { classes += "-o"; } return <i className={classes} aria-hidden="true"></i>; } } export default Like;
پس از این تغییرات اگر برنامه را ذخیره کرده و مجددا در مرورگر بارگذاری کنیم، با توجه به تنظیم liked={true} در کامپوننت movies، ستون like آن با آیکنهای قلب توپر نمایش داده میشود که بیانگر واکنش نشان دادن صحیح به ورودیها در کامپوننت Like است:
پویا سازی مقدار پیشفرض ویژگی liked در کامپوننت movies
برای پویاسازی نمایش مقدار liked در کامپوننت movies، از آنجائیکه هر ردیف بیانگر یک شیء movie است، میتوان به این صورت عمل کرد:
<Like liked={movie.liked} />
const movies = [ { _id: "5b21ca3eeb7f6fbccd471815", title: "Terminator", genre: { _id: "5b21ca3eeb7f6fbccd471818", name: "Action" }, numberInStock: 6, dailyRentalRate: 2.5, publishDate: "2018-01-03T19:04:28.809Z", liked: true },
افزودن رخداد کلیک به کامپوننت Like
برای اینکه کامپوننت Like، رویداد کلیک بر روی آیکن قلب را به والد خود گزارش دهد، ابتدا ویژگی جدید onClick را بر روی تعریف المان آن در کامپوننت movies اضافه میکنیم:
<Like liked={movie.liked} onClick={() => this.handleLike(movie)} />
handleLike = movie => { console.log("handleLike", movie); };
return ( <i className={classes} onClick={this.props.onClick} aria-hidden="true" style={{ cursor: "pointer" }} ></i> );
در اینجا همچنین style این المان نیز جهت نمایش cursor با آیکن pointer، توسط یک شیء از نوع inline style تنظیم شدهاست.
یک نکته: کامپوننت Like تا اینجا یک controlled component است؛ دارای state نیست و همچنین تمام اطلاعات خودش را از طریق props تامین میکند و تنها دارای یک متد render است. بنابراین اگر علاقمند بودید میتوان این کامپوننت را به یک «Stateless Functional Component» که در قسمت 8 معرفی شد نیز تبدیل کرد.
تغییر حالت کامپوننت Like جهت نمایش تغییرات
تا اینجا کامپوننت Like ما میتواند ورودی true/false را به آیکنهای متناظری تبدیل کند. همچنین اگر بر روی این آیکن کلیک شود، آنرا توسط رخدادی به والد خود اطلاع رسانی میکند. اکنون میخواهیم با تکمیل متد handleLike، خاصیت like اشیاء انتخابی (آیکنهایی که بر روی آنها کلیک شدهاند) را از true به false و برعکس تبدیل کرده و سپس UI را نیز به روز رسانی کنیم:
handleLike = movie => { console.log("handleLike", movie); const movies = [...this.state.movies]; // cloning an array const index = movies.indexOf(movie); movies[index] = { ...movies[index] }; // cloning an object movies[index].liked = !movies[index].liked; this.setState({ movies }); };
پس از این تغییرات اگر برنامه را اجرا کنیم، با کلیک بر روی هر آیکن، عکس آن آیکن نمایش داده میشود؛ برای مثال آیکن قلب توپر، تبدیل به آیکن قلب توخالی خواهد شد.
کدهای کامل این قسمت را از اینجا میتوانید دریافت کنید: sample-10.zip
LINQPad یک برنامهی نیمه رایگان است. به این معنا که دریافت آن رایگان است، استفاده از آن هیچ محدودیتی ندارد. فقط هنگام نوشتن کوئریها intellisense ظاهر نخواهد شد. این یک مورد رایگان نیست و برای فعال شدن آن باید مقداری هزینه کنید. کیفیت intellisense آن هم قابل مقایسه است با VS.NET و بسیار مطلوب است.
LINQPad برای تست کردن سریع عبارات LINQ فوق العاده است. با استفاده از آن بدون نیاز به VS.NET خیلی سریع و در عرض چند ثانیه میتونید عبارات LINQ خودتون رو نوشته و تست کنید. این LINQ میتونه LINQ to Objects باشه یا LINQ to SQL یا LINQ to Entities و غیره.
خلاصه چیزی شبیه به management studio مخصوص SQL Server را تصور کنید که اینبار بجای SQL نویسی، LINQ مینویسید، حاصل را نمایش میدهد؛ علاوه بر آن خروجی SQL تولیدی و حتی IL نهایی را هم نمایش میدهد که برای دیباگ بسیار مفید است.
به همراه آن یک سری مثال هم وجود دارد که جهت فراگیری LINQ یا حتی استفاده از آنها به عنوان مرجع بینظیر است.
LINQPad برای تست کردن سریع عبارات LINQ فوق العاده است. با استفاده از آن بدون نیاز به VS.NET خیلی سریع و در عرض چند ثانیه میتونید عبارات LINQ خودتون رو نوشته و تست کنید. این LINQ میتونه LINQ to Objects باشه یا LINQ to SQL یا LINQ to Entities و غیره.
خلاصه چیزی شبیه به management studio مخصوص SQL Server را تصور کنید که اینبار بجای SQL نویسی، LINQ مینویسید، حاصل را نمایش میدهد؛ علاوه بر آن خروجی SQL تولیدی و حتی IL نهایی را هم نمایش میدهد که برای دیباگ بسیار مفید است.
به همراه آن یک سری مثال هم وجود دارد که جهت فراگیری LINQ یا حتی استفاده از آنها به عنوان مرجع بینظیر است.
نظرات اشتراکها
شرکت Syncfusion ایران را تحریم کرد
فکر کنم تنها نگرانی ایشان قسمت کتابهای آن سایت هست؛ نه کامپوننتهای آن.