آشنایی با کامپوننت‌ها

Familiarity with Components

Vue.JS 2: آشنایی با کامپوننت ها - قسمت 30

به فصل جدید خوش آمدید! در این فصل به سراغ کامپوننت ها می رویم که بخش بزرگی از Vue را تشکیل می دهند و تقریبا تمام برنامه هایی که با Vue نوشته می شوند از کامپوننت ها استفاده می کنند. برای درک کامپوننت ها باید به قسمت های قبل برگردیم و از خصوصیت Template استفاده کنیم. من کدهایی را برایتان آماده کرده ام که می توانید آن را درون jsfiddle امتحان کنید. کدهای HTML:

<div id="app">
    
</div>

کدهای جاوا اسکریپت:

new Vue ({
    el: '#app',
    data: {
        status: 'Critical'
    },
    template: '<p>Server Status: {{ status }}</p>'
});

همه شما می دانید که کد بالا باعث نمایش متن زیر می شود:

Server status: critical

بنابراین چیز جدیدی نداریم. همانطور که در فصل قبل دیدیم، اگر بخواهم از این template در قسمت های مختلف برنامه استفاده کنم، به مشکل برمی خوریم چرا که خصوصیت Template در چند جا render نمی شود. چرا؟ به دلیل اینکه طبیعت شیء Vue این است که فقط یک مورد را هدف می گیرد.

راه حل این مشکل کامپوننت ها هستند. برای استفاده از کامپوننت ها باید دستور Vue.component را اجرا کنیم. این دستور در واقع یک شیء Vue است که قابلیت های بیشتری دارد. آرگومان اولی که باید به این دستور پاس داده شود، نام تگ خاصی است که به سلیقه ما انتخاب می شود. شما می توانید کامپوننت را به عنوان یک عنصر خاص HTML در نظر بگیرید که توسط ما ساخته می شود.

Vue.component('my-cmp');

new Vue ({
// بقیه کدها //

نکته: نامی که برای این تگ انتخاب می کنید (در کد بالا، my-cmp) نباید با نام تگ های HTML یکی باشد. سعی کنید همیشه نامی برای کامپوننت هایتان انتخاب کنید که خاص باشند و با پکیج ها و کتابخانه های دیگر تداخل پیدا نکنند.

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

<div id="app">
    <my-cmp>
        
    </my-cmp>
</div>

آرگومان دومی که به component پاس داده می شود همان شیء Vue است بنابراین کد قبلی را کپی می کنم و در آن قرار می دهم:

Vue.component('my-cmp', {
    data: {
        status: 'Critical'
    },
    template: '<p>Server Status: {{ status }}</p>'
});

new Vue({
    el: '#app',
});

البته این کد هنوز کار نمی کند. چرا؟ Component کلاس و شیء Vue را extend می کند بنابراین با نوشتن data، با data های قبلی در کلاس پدر تداخل ایجاد می کنیم. اگر می خواهید از خصوصیت data در کامپوننت های خودتان استفاده کنید باید آن را به صورت یک تابع تعریف کنید:

Vue.component('my-cmp', {
    data: function () {
        return {
            status: 'Critical'
        }
    },
    template: '<p>Server Status: {{ status }}</p>'
});

new Vue({
    el: '#app',
});

حالا اگر این کد را اجرا کنید هیچ مشکلی نخواهیم داشت. همچنین اگر بخواهیم آن را در چند قسمت مختلف نیز بگذاریم، هیچ مشکلی نخواهد بود. به طور مثال:

<div id="app">
    <my-cmp>
    </my-cmp>
    <my-cmp>
    </my-cmp>
</div>

این کد باعث می شود نتیجه زیر را بگیریم:

Server status: critical

Server status: critical

یعنی می توانیم قالب هایمان را به تعداد بی نهایت در هر قسمتی از صفحه نمایش بدهیم. قدرت اصلی کامپوننت ها در همین مسئله است.

مسئله بعدی قسمت data در کامپوننت ها است. من به شما گفتم که باید حتما از یک تابع استفاده کنیم و نمی توانیم یک شیء را به data پاس بدهیم، اما چرا؟ بگذارید به شما نشان بدهم. به کد زیر نگاه کنید:

var data = { status: 'Critical' };

Vue.component('my-cmp', {
    data: function () {
        return data;
    },
    template: '<p>Server Status: {{ status }}</p>'
});

new Vue({
    el: '#app',
});

اگر مستقیما یک شیء را به data پاس بدهیم Vue به ما خطا می دهد اما می توانیم با روش بالا، Vue را دور بزنیم تا خطا نگیریم. در کد بالا شیء ای را خارج از component تعریف کرده ام و آن را با تابع برگردانده ام. در حال حاضر ما دو بار از این کامپوننت استفاده می کنیم:

<div id="app">
    <my-cmp>
    </my-cmp>
    <my-cmp>
    </my-cmp>
</div>

اما شیء data برای هر دوی آن ها یکسان است. منظورم «محتوای یکسان» نیست بلکه منظورم «موقعیت در مموری» است. متغیر data که با تابع مورد نظر return شده است برای هر دو نمونه کامپوننت ما دارای یک موقعیت یکسان در مموری است و این باعث مشکل خواهد شد. به طور مثال من یک دکمه را به کدهایم اضافه می کنم:

var data = { status: 'Critical' };

Vue.component('my-cmp', {
    data: function () {
        return data;
    },
    template: '<p>Server Status: {{ status }} (<button@click="changeStatus">Change</button>)</p>',
    methods: {
        changeStatus: function () {
            this.status = 'Normal';
        }
    }
});

new Vue({
    el: '#app',
});

من در Template خود یک دکمه را تعریف کرده ام که با کلیک شدن روی آن متد ChangeStatus اجرا می شود. این متد را نیز تعریف کرده ام (تنها کاری که می کند تغییر critical به normal است). حالا با اجرای کدهای بالا دکمه ها را می بینیم اما با کلیک روی یکی از آن ها، مقدار critical در هر دو کامپوننت به normal تغییر می کند! مشکل داشتن شیء data یکسان برای چند کامپوننت یا چند نمونه از یک کامپوننت همین است. اگر به جای این کار از روش استاندارد پیروی کنیم مشکلی نخواهیم داشت:

Vue.component('my-cmp', {
    data: function () {
        return {
            status: 'Critical'
        };
    },
    template: '<p>Server Status: {{ status }} (<button@click="changeStatus">Change</button>)</p>',
    methods: {
        changeStatus: function () {
            this.status = 'Normal';
        }
    }
});

همانطور که می بینید من با تابع درون data یک شیء جدید را برگردانده ام بنابراین هر دو <my-cmp> دو data جداگانه خواهند داشت (مکان آن در مموری متفاوت است) و تغییر در یکی باعث تغییر در دیگری نمی شود.

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

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

محمد
07 مهر 1399
ممنون از آموزش خوبی که گذاشتین اما فهرست مطالب یه مشکلی داره که مثلا الان تو این صفحه که هستیم تا درس شماره یک که ساخت کامپوننت هست رو داره نمایش میده اما اگه بریم درس شماره 28 تا قسمت 34 که props ها هستن رو نمایش میده

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