بررسی جزئیات بیشتری از Slotها

Checking Out More Details of Slots

Vue.JS 2: بررسی جزئیات بیشتری از slot ها - قسمت 39

در قسمت قبل با slot ها آشنا شدیم اما باید از نحوه کامپایل شدن آن ها درک کاملی داشته باشیم تا در کدهایمان دچار خطا نشویم. برای شروع این جلسه به فایل Quote.vue رفته و در قسمت استایل ها یک استایل جدید برای h2 ایجاد کنید:

<style scoped>
div {
  border: 1px solid #ccc;
  box-shadow: 1px 1px 2px black;
  padding: 30px;
  margin: 30px auto;
  text-align: center;
}
h2 {
  color: red;
}
</style>

به نظر شما با اضافه کردن رنگ قرمز به تگ h2 آیا در برنامه ما تغییری ایجاد می شود؟ بله! H2 در بالای p قرمز می شود. نتیجه می گیریم که استایل های slot در همین کامپوننت (کامپوننتی که از تگ های <slot> در آن استفاده کرده ایم) تحت تاثیر خواهند بود. به طور مثال اگر وارد فایل App.vue شویم و این استایل را (رنگ قرمز) از Quote.vue به آن انتقال دهیم، استایل ها برایش اعمال نمی شوند.

نکته بعدی دقیقا برخلاف نحوه اعمال استایل ها است. به فایل App.vue رفته و h2 را به صورت data در این کامپوننت می نویسیم:

<script>
import Quote from "./components/Quote";
export default {
  data: function () {
    return {
      quoteTitle: "The Quote"
    }
  },
  components: {
    appQuote: Quote
  }
};
</script>

حالا به جای نوشتن رشته The Quote از همین خصوصیت در template استفاده می کنیم:

<app-quote>
  <h2>{{ quoteTitle }}</h2>
  <p>A wonderful quote</p>
</app-quote>

به نظر شما این کد کار می کند؟ بله!

نتیجه گیری کلی ما این است که برای تمام عملیات های مربوط به Vue و رندر شدن آن در مرورگر (به غیر از استایل ها) کامپوننت دارای کدهای اصلی مسئول تغییر و مدیریت کدها است. مثلا در این قسمت App.vue مسئول نمایش h2 است. از طرفی هر مسئله ای که به اعمال استایل های CSS باشد برعهده کامپوننت فرزند (Quote.vue) خواهد بود.

نکته بعد در رابطه با نمایش چندین slot در یک کامپوننت است. من به فایل Quote.vue می روم و می گویم:

<template>
  <div>
    <div class="title">
      <slot></slot>
    </div>
    <hr />
    <div>
      <slot></slot>
    </div>
  </div>
</template>

یعنی من می خواهم عنوان quote (تگ h2) درون slot اول و خود quote درون slot دوم قرار بگیرد. چرا؟ به دلیل اینکه در slot اول کلاس title را تعریف کرده ام و می خواهم title دارای استایل خاصی باشد. در همین فایل به قسمت استایل ها می روم و می گویم:

<style scoped>
div {
  border: 1px solid #ccc;
  box-shadow: 1px 1px 2px black;
  padding: 30px;
  margin: 30px auto;
  text-align: center;
}
h2 {
  color: red;
}
.title {
  font-style: italic;
}
</style>

یعنی کلاس title دارای حالت italic (مورب شدن خطوط) باشد. چطور می توانیم چنین کاری انجام بدهیم؟ اگر کدهای خود را در همین حالت ذخیره و اجرا کنیم دو بار کامپوننت خود را خواهیم دید. یک بار به صورت italic و یک بار به صورت عادی اما من چنین رفتاری را نمی خواهم. من می خواهم یک slot خودم را به دو قسمت تقسیم کنم.

ایجاد دو Slot جداگانه برای کامپوننت ها
ایجاد دو Slot جداگانه برای کامپوننت ها

برای این کار Vue قابلیتی به نام named slots دارد. شما باید خصوصیتی به نام name را به slot های خود داده و مقداری را برایشان انتخاب کنید (هر مقداری که می خواهید):

<template>
  <div>
    <div class="title">
      <slot name="title"></slot>
    </div>
    <hr />
    <div>
      <slot name="content"></slot>
    </div>
  </div>
</template>

من نام های title و content را انتخاب کرده ام. حالا به فایل App.vue می رویم و Slot مورد نظر برای هر قسمت را مشخص می کنیم:

<template>
  <div class="container">
    <div class="row">
      <div class="col-xs-12"></div>
      <app-quote>
        <h2 slot="title">{{ quoteTitle }}</h2>
        <p slot="content">A wonderful quote</p>
      </app-quote>
    </div>
  </div>
</template>

در اینجا slot مشخص کننده نام slot ما است که در فایل quote.vue تعریف کرده بودیم بنابراین باید دقیقا همان مقدار را برایش قرار دهیم. حالا اگر کدها را ذخیره کرده و به مرورگر برویم (npm run dev در حال اجرا باشد) کدهایمان به درستی به دو قسمت تقسیم شده اند.

جدا شدن دو قسمت از یک کامپوننت درون دو slot جداگانه
جدا شدن دو قسمت از یک کامپوننت درون دو slot جداگانه

نکته جالب تر این است که slot های بدون نام به عنوان slot های پیش فرض عمل می کنند. به طور مثال اگر به quote.vue برویم و name قسمت content را حذف کنیم:

<template>
  <div>
    <div class="title">
      <slot name="title"></slot>
    </div>
    <hr />
    <div>
      <slot></slot>
    </div>
  </div>
</template>

سپس به app.vue رفته و name آن را نیز حذف کنیم:

<app-quote>
  <h2 slot="title">{{ quoteTitle }}</h2>
  <p>A wonderful quote</p>
</app-quote>

Vue به صورت خودکار قسمت title را در Slot ای به نام title قرار می دهد و بقیه عناصر را در همان slot ای می گذارد که نامی ندارد. بنابراین این کد دقیقا همان نتیجه قبلی را به ما می دهد.

حالا فرض کنید می خواهیم در فایل Quote.vue یک Span نیز داشته باشیم. فرض این است که این Span بعضی از اوقات حضور دارد و بعضی از اوقات به ما پاس داده نمی شود بنابراین مطمئن نیستیم که آن را دریافت خواهیم کرد یا خیر:

<template>
  <div>
    <div class="title">
      <slot name="title"></slot>
      <span>
        <slot name="subtitle"></slot>
      </span>
    </div>
    <hr />
    <div>
      <slot></slot>
    </div>
  </div>
</template>

همانطور که می بینید این span یک slotبه نام subtitle دارد. ما می دانیم که چنین slot ای را دریافت نخواهیم کرد. در فایل App.vue فقط title و slot بدون نام پیش فرض را داریم. برای چنین مواقعی برای اینکه به خطا برنخوریم می توانیم یک مقدار پیش فرض را تعریف کنیم. اگر مقدار دیگری به این  slot رسید که جایگزین مقدار قبلی می شود اما اگر مقدار جدیدی نرسید از همان مقدار پیش فرض استفاده خواهیم کرد. برای این کار در فایل Quote.vue باشید و مثل یک عنصر HTML عادی با آن کار کنید:

<template>
  <div>
    <div class="title">
      <slot name="title"></slot>
      <span style="color: #ccc">
        <slot name="subtitle">The Subtitle</slot>
      </span>
    </div>
    <hr />
    <div>
      <slot></slot>
    </div>
  </div>
</template>

حالا اگر به مرورگر بروید عبارت The Subtitle را با رنگ خاکستری روشن (ccc#) مشاهده خواهید کرد.

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

دیدگاه‌های شما

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