مبحث two-way-binding و پاسخ به تغییرات

two-way-binding and Responding to Changes

26 شهریور 1399
Vue.JS 2: مبحث two-way-binding و پاسخ به تغییرات

مبحث two-way-binding

اگر با فریم ورک هایی مانند React کار کرده باشید به احتمال زیاد با two-way-binding آشنایی دارید. به کد زیر توجه کنید:

<script src="https://unpkg.com/vue/dist/vue.js"></script>

<div id="app">
    <input type="text">
    <p>{{ name }}</p>
</div>

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

new Vue({
    el: '#app',
    data: {
        name: 'Amir'
    }
})

با اجرای این کد کلمه Amir در برنامه ما دیده می شود. فرض کنید من بخواهم کلمه Amir را نمایش بدهم اما به محض اینکه کاربر چیزی در input نوشت، کلمه نشان داده شده را به همین نام تغییر دهم. به این کار two-way-binding (به معنای «اتصال دو طرفه») می گویند چرا که از طرفی داده ها را به صفحه می فرستیم تا نمایش داده شود و از طرفی داده ها را از خود صفحه (از طریق input) دریافت می کنیم که یک جریان اطلاعات دو طرفه می باشد.

برای انجام این کار از یک directive به نام v-model استفاده می کنیم:

<div id="app">
    <input type="text" v-model="name">
    <p>{{ name }}</p>
</div>

v-model به Vue می گوید که برای این input یک رابطه two-way-binding ایجاد کن و Vue بقیه کارها را بر عهده می گیرد. توجه کنید که مقدار پاس داده شده به این directive باید همان خصوصیتی باشد که قرار است به صورت دو جهته bind شود (یعنی name). شما می توانید کد بالا را در مرورگر خود یا jsfiddle اجرا کنید. من لینک آماده آن را برایتان قرار می دهم:

https://jsfiddle.net/hb56darp/

به محض نوشتن یک مقدار درون این input می توانید تغییر آن در تگ <p> را نیز مشاهده کنید.

واکنش پذیری و پاسخ به تغییرات

در این قسمت می خواهیم واکنش پذیری فریم ورک Vue را بررسی کنیم. تا این قسمت مثال های بسیار ساده ای داشتیم که فقط روی یک مورد تمرکز می کردند اما اگر نمایش یک متن وابسته به خصوصیت دیگری باشد چطور؟ اینجاست که به مبحث واکنش پذیری در Vue می رسیم؛ یعنی آیا تغییر در یک عضو، واکنشی در دیگر اعضا را در پی خواهد داشت یا خیر؟ برای فریم ورک قدرتمندی مانند Vue پاسخ قطعا بله است.

برای بررسی این موضوع مثال تازه ای برایتان نوشته ام که کد آن را در اختیارتان می گذارم. کدهای HTML:

<script src="https://unpkg.com/vue/dist/vue.js"></script>

<div id="app">
    <button v-on:click="increase">Increase</button>
    <p>Counter: {{ counter }}</p>
    <p>Result: {{ result }}</p>
</div>

همانطور که می بینید در این کدها یک دکمه داریم که با کلیک روی آن تابعی به نام increase اجرا خواهد شد. همچنین دو خصوصیت counter (شمارنده) و result (نتیجه) را نیز خواهیم دید. کدهای جاوا اسکریپت ما نیز بدین شکل هستند:

new Vue({
    el: '#app',
    data: {
        counter: 0,
        result: ''
    },
    methods: {
        increase: function () {
            this.counter++;
            this.result = this.counter > 5 ? 'Greater than 5' : 'Smaller than 5'
        }
    }
})

Counter در ابتدا صفر و result در ابتدا خالی است. کار تابع increase نیز ساده است؛ ابتدا یک واحد به counter اضافه می کند و سپس برای result یکی از این دو کار را انجام می دهد: اگر مقدار counter بیشتر از 5 باشد عبارت Greater than 5 (یعنی «بزرگ تر از 5») و در غیر این صورت Smaller than 5 (یعنی «کوچک تر از 5») برای مقدار result نمایش داده خواهد شد. کدی که برای این قسمت نوشتم یک شرط ternary ساده است که مربوط به جاوا اسکریپت عادی است و باید با آن آشنا باشید. خروجی این کد را در ویدیوی زیر می بینید:

حالا تصور کنید در یک برنامه بزرگ تر که بسیاری از عناصر دیگر به این counter وابسته باشند (نه فقط یک پاراگراف). در چنین برنامه های بزرگی نگهداری از counter درون یک تابع به نام increase بسیار سخت خواهد شد. مثلا تصور کنید که در قسمتی دیگر از برنامه نیز متدی داشته باشیم که این counter را تغییر بدهد! همگام و یکی نگه داشتن این دو متد با یکدیگر کار بسیار سختی خواهد بود. حتی اگر در همین پروژه ساده خودمان متدی به نام decrease (به معنای «کاهش دادن») را اضافه کنم کارمان سخت می شود:

<div id="app">
    <button v-on:click="increase">Increase</button>
    <button v-on:click="decrease">Decrease</button>
    <p>Counter: {{ counter }}</p>
    <p>Result: {{ result }}</p>
</div>

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

new Vue({
    el: '#app',
    data: {
        counter: 0,
        result: ''
    },
    methods: {
        increase: function () {
            this.counter++;
            this.result = this.counter > 5 ? 'Greater than 5' : 'Smaller than 5';
        },
        decrease: function () {
            this.counter--;
            this.result = this.counter > 5 ? 'Greater than 5' : 'Smaller than 5';
        }
    }
})

کد بالا به خوبی کار می کند اما اگر دقت کنید کد result را به صورت تکراری در هر دو تابع داریم. تصور کنید که این کار را در یک برنامه بزرگ انجام بدهیم که یک متغیر شاید به ده ها یا صد ها مورد مختلف وابسته باشد! مدیریت چنین کدی (جدا از مسائل بهینه نویسی کد) تقریبا غیرممکن است. برای هر تغییر کوچکی باید ده ها یا صد ها نمونه کد را تغییر دهیم!

اینجاست که بحث واکنش پذیری و تکیه عناصر بر یکدیگر در Vue می درخشد! فریم ورک Vue کار ما را در چنین مواردی بسیار راحت تر کرده است. بگذارید به شما نشان بدهم. ابتدا هر کل قسمت methods (هر دو تابع increase و decrease را) از کدهای جاوا اسکریپت حذف کنید:

new Vue({
    el: '#app',
    data: {
        counter: 0,
        result: ''
    }
})

سپس کدهای HTML را بدین شکل تغییر دهید:

<div id="app">
    <button v-on:click="counter++">Increase</button>
    <button v-on:click="counter--">Decrease</button>
    <p>Counter: {{ counter }}</p>
    <p>Result: {{ result }}</p>
</div>

سوال اینجاست که حالا چطور result را به روز رسانی کنیم؟ این کدها را نزد خودتان داشته باشید تا در قسمت بعد به سوال شما پاسخ بدهم.

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

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