ارتباط بین کامپوننت‌ها با Props

Relationship Between Components with Props

Vue.JS 2: ارتباط بین کامپوننت ها با props - قسمت 33

من برای این جلسه فایلی را برای شما آماده کرده ام که می توانید از این لینک دانلود کنید. این فایل حاوی کدهای یک پروژه بسیار ساده به شکل زیر است:

یک پروژه ی ساده برای شروع کار
یک پروژه ساده برای شروع کار

همانطور که در این تصویر مشاهده می کنید، دو کامپوننت ساده را در این پروژه داریم. من می خواهم اطلاعاتی را از کامپوننت پدر (قرمز رنگ) به کامپوننت فرزند (سبز رنگ) ارسال کنم. برای این کار (از پروژه ای که به شما دادم) وارد فایل User.vue شده و دکمه جدیدی را ایجاد کنید:

<template>
    <div class="component">
        <h1>The User Component</h1>
        <p>I'm an awesome User!</p>
        <button @click="changeName">Change my Name</button>
        <hr>
// بقیه کدها //

من می خواهم با کلیک شدن این دکمه، متدی به نام ChangeName اجرا شود (هنوز تعریف نشده است). حالا به قسمت script می رویم و data را تعریف می کنیم تا اصلا داده ای داشته باشیم که بعدا بخواهد تغییر کند:

<script>
import UserDetail from "./UserDetail.vue";
import UserEdit from "./UserEdit.vue";

export default {
  data: function() {
    return {
      name: "Amir"
    };
  },
  methods: {
    changeName() {
      this.name = "Roxo";
    }
  },
  components: {
    appUserDetail: UserDetail,
    appUserEdit: UserEdit
  }
};
</script>

یعنی در این حالت داده ای به نام name داریم که مقدارش Amir است و سپس با کلیک روی آن باید به روکسو تبدیل شود. مشکل اینجاست که من می خواهم name را درون کامپوننت userDetail.vue نمایش بدهم نه در همین فایل. بنابراین به این فایل بروید:

<template>
  <div class="component">
    <h3>You may view the User Details here</h3>
    <p>Many Details</p>
    <p>User Name : {{ name }}</p>
  </div>
</template>

کد بالا جواب نمی دهد. چرا؟ به دلیل اینکه در این فایل خصوصیتی به نام name نداریم. برای انتقال دادن اطلاعات بین دو کامپوننت از مفهومی به نام props استفاده می کنیم. برای اینکه به کامپوننت userDetail.vue بگویم قرار است از خارج از خودش اطلاعاتی را دریافت کند، باید خصوصیت props را در آن تعریف کنیم:

<script>
export default {
    props: []
}
</script>

همانطور که می بینید props یک آرایه است که درون آن خصوصیاتی را به صورت رشته تعریف خواهیم کرد. این خصوصیات، همان خصوصیاتی هستند که از خارج کامپوننت به آن ارسال می شوند. مثلا name یکی از آن ها است، بنابراین:

<script>
export default {
  props: ['name']
};
</script>

توجه داشته باشید که name در اینجا باعث ساخت خصوصیت جدیدی به نام name می شود بنابراین باید هنگامی که در تگ های template از آن استفاده می کنیم، باید دقیقا از نام تعریف شده در props استفاده کنیم. حالا برای پاس دادن این props به فایل User.vue برمی گردیم و آن را روی کامپوننت دیگر به صورت attribute قرار می دهیم بنابراین:

// بقیه کدها //
    <div class="row">
      <div class="col-xs-12 col-sm-6">
        <app-user-detail name="name"></app-user-detail>
      </div>
      <div class="col-xs-12 col-sm-6">
        <app-user-edit></app-user-edit>
      </div>
    </div>
// بقیه کدها //

این کد درست کار نمی کند! به دلیل اینکه name در اینجا به مقدار name در data اشاره نمی کند بلکه واقعا یک رشته با مقدار name است:

name در چنین حالتی پویا نیست بلکه واقعا به رشته اشاره می کند
name در چنین حالتی پویا نیست بلکه واقعا به رشته اشاره می کند

راه حل استفاده از v-bind است. البته من از حالت خلاصه آن (علامت دو نقطه) استفاده می کنم:

<app-user-detail :name="name"></app-user-detail>

حالا منظور ما از name همان خصوصیت name درون data است. حالا اگر برنامه را در مرورگر خود تست کنید (دستور npm run dev در حال اجرا باشد) ابتدا نام Amir را می بینید و در صورتی که روی دکمه change my name کلیک کنید به Roxo تغییر پیدا می کند.

برای جمع بندی نکاتی را خدمتتان عرض می کنم. Attribute ای که برای پاس دادن روی عنصر app-user-detail گذاشته ایم باید با مقداری که در خصوصیت props تعریف کرده ایم یکی باشد اما مقدار پاس داده شده مهم نیست و طبق خواسته شما است. مثلا کد زیر کاملا صحیح است.

در فایل userDetail.vue:

<template>
  <div class="component">
    <h3>You may view the User Details here</h3>
    <p>Many Details</p>
    <p>User Name : {{ Roxo }}</p>
  </div>
</template>

<script>
export default {
  props: ["Roxo"]
};
</script>

در این فایل نکته مهم یکی بودن Roxo در قسمت Template با رشته درون props است. نامی که به props می دهید در اینجا دلخواه است اما template باید از آن تبعیت کند. سپس در فایل user.vue:

<app-user-detail :Roxo="anotherName"></app-user-detail>

قسمت Script فایل user.vue:

export default {
  data: function() {
    return {
      anotherName: "Amir"
    };
  },
  methods: {
    changeName() {
      this.anotherName = "Roxo";
    }
  },
// بقیه کدها //

این کدها نیز از زاویه دیگر به شما می گویند که چه مقادیری باید با هم یکی باشند. مثال دیگری از آن بدین شکل است:

export default {
  props: ["myName"]
};

سپس:

<p>User Name : {{ myName }}</p>

و نهایتا:

<app-user-detail :myName="name"></app-user-detail>

نکته: نام هایی که برای props خود انتخاب می کنید case-sensitive هستند (به بزرگی و کوچکی حروف حساس می باشند) اما این مسئله فقط زمانی جواب می دهد که از single file template استفاده کنید، یعنی همین کاری که الان انجام داده ایم. اگر از روش های el و خصوصیت template استفاده کنید (فصل های اول) به مشکل برمی خورید چرا که DOM قابلیت تشخیص حروف بزرگ و کوچک را ندارد (case-insensitive است).

همانطور که گفتم از این به بعد در این دوره از Single file template ها استفاده خواهیم کرد و دیگر به سراغ روش el یا خصوصیت Template نمی رویم چرا که بهترین روش و بی دردسر ترین روش است. به شما نیز پیشنهاد می کنم برای پروژه های واقعی خود حتما از این روش استفاده نمایید.

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

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