استایل‌دهی عناصر و کلاس‌های پویا

Styling Dynamic Elements and Classes

23 بهمن 1399
استایل دهی عناصر و کلاس های پویا

استایل دهی مشروط (پویا) عناصر

به فصل سوم از دوره جامع آموزش ری اکت خوش آمدید. این فصل کوتاه و مخصوص استایل دهی و مشکلات آن است. توجه داشته باشید که از این جلسه به بعد همان کدهای فصل دوم را ادامه می دهیم. اگر به پروژه نگاهی بیندازید می بینید که استایل های ساده ای وجود دارد اما آنچنان پیشرفته نیست. به طور مثال دکمه Toggle Persons یک دکمه ساده است که اگر روی آن بروید (hover) هیچ اتفاقی نمی افتد و ظاهرش تغییر نمی کند. استایل های این دکمه در یک ثابت با نام style ذخیره شده است (به شکل inline) بنابراین راهی برای استفاده از hover یا pseudo-selector های دیگر نیست. در عین حال خوبی این روش این بود که استایل ها scope دارند، یعنی مخصوص همین دکمه هستند و به صورت سراسری اعمال نمی شوند بنابراین اگر دکمه های دیگری ایجاد کنیم، این استایل ها را نمی گیرند. این یک نقطه قوت است.

از طرفی استفاده از فایل های css باعث می شود که استایل ها سراسری باشند و تمام دکمه های ما استایل های مورد نظر را بگیرند اما در عوض می توانیم از hover و تمامی امکانات css استفاده کنیم.

در این فصل در رابطه با همین مشکلات صحبت خواهیم کرد و راه حل آن را به شما نشان می دهیم. برای شروع می خواهیم عناصر را به شکل پویا استایل دهی کنیم (یعنی استایل های آن ها بر اساس موقعیت تغییر کنند). می خواهیم کاری کنیم که بر اساس نمایش افراد (اینکه Person ها نمایش داده شده اند یا مخفی هستند) استایل دکمه را تغییر دهیم.

اگر به فایل App.js نگاه کنید ثابت style را می بینید:

const style = {
      backgroundColor: 'white',
      font: 'inherit',
      border: '1px solid blue',
      padding: '8px',
      cursor: 'pointer'
};

پایین تر از آن هم شرط if را داریم:

    if (this.state.showPersons) {
      persons = (
        <div> 
// the rest of the code

اگر شرط درون if (یعنی this.state.showPersons) صحیح باشد یعنی افراد نمایش داده می شوند بنابراین رنگ دکمه در این حالت بهتر است قرمز باشد (چرا که با فشردن دکمه دیگر نمایش داده نمی شوند) در غیر این صورت دکمه را سبز می کنیم:

const style = {
      backgroundColor: 'green',
      color: 'white',
      font: 'inherit',
      border: '1px solid blue',
      padding: '8px',
      cursor: 'pointer'
};

در حال حاضر اگر به مرورگر برویم می بینیم که دکمه ما سبز شده است اما با کلیک روی آن چیزی تغییر نمی کند. برای تغییر دادن آن می توانیم از همان شرط if استفاده کنیم:

if (this.state.showPersons) {
      persons = (
        <div>
          {this.state.persons.map((person, index) => {
            return <Person
              click={() => this.deletePersonHandler(index)}
              name={person.name}
              age={person.age}
              key={person.id}
              changed={(event) => this.nameChangedHandler(event, person.id)}
            />
          })}
        </div>
      );

      style.backgroundColor = 'red';
    }

آیا متوجه تغییر شدید؟ در قسمت آخر شرط if به شیء style و خصوصیت backgroundColor دسترسی پیدا کرده ایم و آن را برابر با red گذاشته ایم. احتمالا برایتان سوال پیش بیاید که شیء style در یک const (ثابت) قرار دارد بنابراین چطور مقدار آن را تغییر داده ایم؟ در واقع ما مقدار style را تغییر نداده ایم، بلکه مقدار یکی از خصوصیت ها (property) های آن را عوض کرده ایم. این مسئله در جاوا اسکریپت به معنی تغییر دادن شیء style نیست چرا که مقدار جدیدی به آن منسوب نکرده ایم.

با همین تکه کد کوچک توانستیم استایل های خودمان را پویا کنیم. اگر به مرورگر بروید می بینید که با کلیک روی دکمه رنگ آن نیز عوض می شود. باز هم تکرار میک نم: در react همه چیز جاوا اسکریپت است! بنابراین استایل ها را همانطور تغییر می دهیم که متغیرها را تغییر می دهیم!

بر این اساس می توان گفت که نام کلاس ها نیز به صورت پویا قابل تغییر است! فرض کنید می خواهیم پارگراف دوم در div با کلاس App را تغییر دهیم:

return (
      <div className="App">
        <h1>Hi, I'm a React App</h1>
        <p>This is really working!</p>
        <button
          style={style}
          onClick={this.togglePersonsHandler}>Toggle Persons
        </button>
        {persons}
      </div>
);

منظورم پاراگرافی است که می گوید <p>This is really working!</p>

مثلا بر اساس اینکه اعضای آرایه persons (در state) سه عضو داشته باشند یا کمتر از 3 عضو داشته باشند استایل های این پاراگراف تغییر کند. برای شروع وارد فایل App.css می شویم و یک یا دو کلاس را با استایل های دلخواه تعریف می کنیم:

.red {
  color: red;
}

.bold {
  font-weight: bold;
}

می خواهم زمانی که اعضای آرایه persons دو نفر یا کمتر بودند رنگ پاراگراف قرمز شود و در صورتی که اعضا یک نفر یا کمتر بودند، متن قرمز شود و متن نیز به صورت bold نمایش داده شود.

برای انجام این کار پایین تر از بلوک if قبلی (خارج از return) یک آرایه جدید می سازیم:

let classes = ['red', 'bold'].join (' ');

با این کار دو کلاس red و bold را به صورت یک رشته به هم می چسبانیم البته به خاطر تابع join بینشان یک اسپیس (فاصله) قرار می گیرد. حتما می دانید که کلاس های HTML باید با اسپیس از هم جدا شوند. دلیل اینکه از ابتدا آن را به صورت یک رشته ننوشتیم این است که می خواهیم بعدا آرایه را به صورت پویا تغییر دهیم.

حالا می توانیم classes را به پاراگراف بدهیم:

<p className={classes}>This is really working!</p>

اگر کدها را به همین صورت ذخیره کرده و به مرورگر برویم می بینیم که هر دو کلاس روی پاراگراف ما اعمال شده اند (bold و red). اما ما می خواهیم اعمال این کلاس ها به صورت مشروط باشد بنابراین فعلا classes را روی یک آرایه خالی تنظیم کنید:

const classes = [];

من classes را بر اساس سلیقه در یک const قرار دادم شما می توانید از let هم استفاده کنید. یادتان باشد با اینکه classes از نوع const است اما هنوز می توانیم اعضایی به آن اضافه کنیم! اضافه کردن اعضا به آرایه به معنی تغییر دادن آن نیست. زمانی classes تغییر می کند که به طور کلی آن را تغییر دهیم (مثلا از آرایه به شیء برویم).

بنابراین با دو if ساده می گوییم:

const classes = [];
    
    if (this.state.persons.length <= 2) {
      classes.push('red'); // classes = ['red']
    }

    if (this.state.persons.length <= 1) {
      classes.push('bold'); // classes = ['red', 'bold']
}

این کد دو بلوک ساده if است. توجه کنید که از elseif و... استفاده نکرده ایم چون میخواهیم هر دو شرط مستقل از هم اجرا شوند. حالا به مشکلی برمی خوریم:

<p className={classes}>This is really working!</p>

کلاس های HTML و همچنین className در JSX باید به صورت رشته ای باشند اما classes یک آرایه است. حتما راه حل را می دانید... از همان join استفاده می کنیم!

<p className={classes.join(' ')}>This is really working!</p>

پارامتر داده شده به join یک رشته خالی (اسپیس) است تا در صورت نیاز بین red و bold فاصله داشته باشیم. حالا می توانیم به راحتی به مرورگر برویم و کدها را تست کنیم. اگر یکی از persons را حذف کنیم نوشته قرمز می شود و اگر یک نفر دیگر را نیز حذف کنیم (تا فقط یک نفر باقی بماند) نوشته هم قرمز و هم bold می شود.

امیدوارم هدف اصلی این جلسه را درک کرده باشید: همه چیز در react جاوااسکریپت است بنابراین مانند جاوا اسکریپت فکر کنید.

تمام فصل‌های سری ترتیبی که روکسو برای مطالعه‌ی دروس سری دوره جامع آموزش ری اکت توصیه می‌کند:
نویسنده شوید
دیدگاه‌های شما

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.