طراحی یک تقویم ساده با Moment ،CSS و Vue — راهنمای مقدماتی

۲۷۲ بازدید
آخرین به‌روزرسانی: ۱۲ شهریور ۱۴۰۲
زمان مطالعه: ۴ دقیقه
طراحی یک تقویم ساده با Moment ،CSS و Vue — راهنمای مقدماتی

در برخی موارد به دلایلی مانند نوع طراحی یک وب‌سایت و یا دلایل دیگر، نیاز هست که یک کامپوننت با طراحی کاملاً ساده داشته باشیم. طراحی چنین کامپوننتی با استفاده از grid در CSS کاملاً سرراست است. ما در این مقاله به توضیح این فرایند می‌پردازیم و آن را به صورت دینامیک درمی‌آوریم تا بتوان تاریخ‌های مختلف را در آن انتخاب کرد. قبل از هر کار باید اطمینان یابیم عنصری داریم که می‌توانیم اپلیکیشن Vue را روی آن راه‌اندازی کنیم. به این منظور از یک عنصر <main> با id به صورت «calendar» استفاده می‌کنیم.

برای یادگیری استفاده از Grid در CSS ، مطالعه مقاله زیر پیشنهاد می‌شود:

اسکریپت Vue.js (+) را به پروژه اضافه کرده و یک اپلیکیشن ساده راه‌اندازی می‌کنیم:

1const app = new Vue({
2  el: '#calendar',
3  data() {
4    return {
5      days: []
6    }
7  },
8  mounted() {
9    // load days
10  }
11})

اینک moment (+) را در پروژه خود می‌گنجانیم و کد ()mounted مورد نیاز برای پر کردن روزهای ماه را می‌نویسیم. به این منظور از چند تابع moment همراه با منطق ES6 استفاده می‌کنیم. تابع ()mounted چنین است:

1let monthDate = moment().startOf('month')
2this.days = [...Array(monthDate.daysInMonth())].map((_, i) => {
3  return monthDate.clone().add(i, 'day')
4})

ابتدا روز ابتدای ماه را با استفاده از تابع startOf (+) به دست می‌آوریم. سپس از تابع daysInMonth به عنوان یک آرایه جدید موقتی استفاده می‌کنیم که به صورت آرایه‌ای بسط می‌یابد که با طول روزهای ماه برابر می‌شود. سپس از این آرایه برای نگاشت روزها با استفاده از اندیس iterator به همراه متد clone در moment بهره می‌گیریم و به ترتیب روزهای ماه را یک به یک افزایش می‌دهیم.

اکنون که آرایه روزهای ماه را در اختیار داریم، می‌توانیم قالب HTML را طوری بسط دهیم که شامل برخی رندرینگ های لیست (list rendering) در Vue باشد. کافی است کد زیر را به کانتینر اپلیکیشن خود بیفزایید:

1<div v-for="(day, index) in days">
2  {{ day.format('D') }}
3</div>

اکنون فهرستی از روزها در view خود می‌بینید که برابر با تعداد روزهای ماه جاری است. در ادامه مقداری کدهای ساده CSS به آن اضافه می‌کنیم تا طرح کلی‌اش را مشخص سازیم. ما قصد داریم این تقویم کاملاً در میانه صفحه قرار گیرد و با یک فونت sans-serif نمایش یابد.

1html, body{
2  height: 100%;
3  width: 100%;
4}
5body{
6  align-items: center;
7  box-sizing: border-box;
8  display: flex;
9  font: calc(2vh) "Helvetica", sans-serif;
10  justify-content: "center";
11  padding: 2em;
12}

در مرحله بعدی grid خود را برای ساخت 7 ستون روی فضای موجود تکرار می‌کنیم تا اندازه آن روی صفحه‌های بزرگ نیز متناسب باشد.

همچنین هر یک از آیتم‌های grid را طوری تنظیم می‌کنیم که اعدادشان در مرکز قرار گیرد. در نهایت یک استایل before:: اضافه می‌کنیم تا آیتم‌هایمان مرتب بمانند.

1#calendar{
2  display: grid;
3  grid-template-columns: repeat(7, 1fr);
4  max-width: 1024px;
5  width: 100%;
6}
7#calendar > *{
8  align-items: center;
9  display: flex;
10  justify-content: center;
11}
12#calendar > *::before{
13  content: "";
14  display: inline-block;
15  height: 0;
16  padding-bottom: 100%;
17  width: 1px;
18}

اینک یک طرح‌بندی زیبا از روزها داریم؛ اما این احتمال هست که روزها از ستون نادرستی آغاز شوند. دلیل این امر آن است که باید روز ابتدایی ماه را برای ستون خاصی تعیین کنیم و باقی روزها بر همین مبنا تنظیم شوند. این کار به سادگی با افزودن مشخصه grid-column با اندیس مورد نیاز به div نخست ممکن است. در ادامه از قدرت یک استایل Vue به نام bindings استفاده می‌کنیم تا این مسئله را مدیریت کنیم. ابتدا یک استایل bindings به لیست خود اضافه کنید:

1<div v-for="(day, index) in days" :style="{ gridColumn: column(index) }">
2  {{ day.format('D') }}
3</div>

بدین ترتیب متدی به نام column را فراخوانی می‌کنیم که اندیس روز رندر شده را ارسال می‌کند. سپس بررسی می‌کنیم که آیا این روز، همان روز نخست ماه است یا نه و اگر چنین باشد از moment برای بازگرداندن روز نخست هفته (day of the week) بهره می‌گیریم. دقت کنید که این متد مقادیری از 0 تا 6 بازگشت می‌دهد و از این رو باید یک واحد به آن اضافه کنیم تا بتوانیم روی سیستم grid خود استفاده نماییم. این متد را درون شیء methods روی اپلیکیشن Vue اضافه می‌کنیم.

1column(index) {
2  if (index == 0) {
3    return this.days[0].day() + 1
4  }
5}

همچنین بهتر است روز کنونی ماه جاری را در تقویم مشخص کنیم. بدین منظور رندر لیست روزها را باز می‌کنیم تا یک binding کلاس در Vue را نیز در آن بگنجانیم.

1<div v-for="(day, index) in days" :style="{ gridColumn: column(index) }" :class="{ today: today(day) }">
2  {{ day.format('D') }}
3</div>

این binding کلاس به کلاس CSS شیء «today» اتصال می‌یابد و مقدار true بازگشت می‌دهد. با استفاده از متد isSame در moment بررسی می‌کنیم که آیا روز رندر شده همان today یعنی امروز است یا نه. در این مورد نیز از شیء متد استفاده می‌کنیم:

1today(day) {
2  return moment().isSame(day, 'day')
3}

همچنین می‌توانید CSS را طوری بسط دهید که شامل یک استایل متفاوت برای تاریخ امروز باشد. ما قصد داریم یک حاشیه دایره‌ای را با تعیین میزان لبه و شعاع پیرامون آن درج کنیم.

1#calendar > *.today{
2  border: 0.1em solid black;
3  border-radius: 100%;
4}

در نهایت به صورت دستی هفت آیتم دیگر شبکه را برای هر روز هفته به تقویم اضافه می‌کنیم تا شبکه CSS آن‌ها را به طور خودکار در جای خود قرار دهد. بدین ترتیب یک تقویم بسیار ساده به دست می‌آوریم که با استفاده از امکان Grid در CSS و همچنین moment و Vue طراحی شده است.

Simple Calendar Layout with CSS Grid

در نهایت شکل و شمایل تقویمی که طراحی کرده‌ایم چنین خواهد بود.

اگر این مطلب برای شما مفید بوده است، آموزش‌های زیر نیز به شما پیشنهاد می‌شوند:

==

بر اساس رای ۰ نفر
آیا این مطلب برای شما مفید بود؟
اگر بازخوردی درباره این مطلب دارید یا پرسشی دارید که بدون پاسخ مانده است، آن را از طریق بخش نظرات مطرح کنید.
منابع:
leemartin
نظر شما چیست؟

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *