آموزش Vue.js: متدها در Vue — بخش هفتم
منظور از متد در Vue تابعی مرتبط با یک وهله از Vue است. متدها در Vue درون مشخصه methods تعریف میشوند. در این بخش از سری مقالات آموزش Vue.js قصد داریم به بررسی متدهای ویو بپردازیم. برای مطالعه بخش قبلی این سری مقالات روی لینک زیر کلیک کنید:
چنان که اشاره کردیم متدهای Vue درون مشخصه methods تعریف میشوند:
1new Vue({
2 methods: {
3 handleClick: function() {
4 alert('test')
5 }
6 }
7})
در مورد کامپوننتهای تک فایلی شیوه تعریف آنها به صورت زیر است:
1<script>
2export default {
3 methods: {
4 handleClick: function() {
5 alert('test')
6 }
7 }
8}
9</script>
متدها به طور خاص در مواردی مفید هستند که بخواهیم یک اکشن را اجرا کنیم و یک دایرکتیو v-on روی یک عنصر برای مدیریت رویداد الصاق شده باشد. در اکشن زیر میبینیم که وقتی عنصر کلیک میشود، handleClick فراخوانی میشود:
1<template>
2 <a @click="handleClick">Click me!</a>
3</template>
ارسال پارامترها به متدهای Vue.js
متدها میتوانند پارامتر نیز بگیرند.
به این منظور کافی است پارامتر را در قالب ارسال کنید:
1<template>
2 <a @click="handleClick('something')">Click me!</a>
3</template>
1new Vue({
2 methods: {
3 handleClick: function(text) {
4 alert(text)
5 }
6 }
7})
در مورد کامپوننتهای تک فایلی به صورت زیر عمل میکنیم:
1<script>
2export default {
3 methods: {
4 handleClick: function(text) {
5 alert(text)
6 }
7 }
8}
9</script>
شیوه دسترسی به دادههای یک متد
با استفاده از this. میتوان به همه مشخصههای دادهای کامپوننتهای Vue دسترسی یافت:
1<template>
2 <a @click="handleClick()">Click me!</a>
3</template>
4
5<script>
6export default {
7 data() {
8 return {
9 name: 'Flavio'
10 }
11 },
12 methods: {
13 handleClick: function() {
14 console.log(this.name)
15 }
16 }
17}
18</script>
لازم نیست که از this.data.name استفاده کنیم و this.name کفایت میکند. Vue یک اتصال شفاف برای ما ایجاد میکند. استفاده از this.data.name منجر به بروز خطا خواهد شد. همان طور که در بخش قبلی در مورد رویدادها دیدیم، متدها ارتباط بسیار نزدیکی با رویدادها دارند زیرا به عنوان دستگیرههای رویداد استفاده میشوند. هر بار که رویدادی رخ میدهد یک متد فراخوانی میشود.
Watcher
Watcher یک قابلیت خاص Vue.js است که امکان تحت نظر گرفتن یک مشخصه از حالت کامپوننت را فراهم میسازد و زمانی که مقدار مشخصه تغییر یابد تابعی را اجرا میکند. به مثال زیر توجه کنید. در این مثال کامپوننتی داریم که یک نام را نمایش میدهد و امکان تغییر دادن آن را با کلیک کردن یک دکمه فراهم ساخته است:
1<template>
2 <p>My name is {{name}}</p>
3 <button @click="changeName()">Change my name!</button>
4</template>
5
6<script>
7export default {
8 data() {
9 return {
10 name: 'Flavio'
11 }
12 },
13 methods: {
14 changeName: function() {
15 this.name = 'Flavius'
16 }
17 }
18}
19</script>
زمانی که نام تغییر پیدا کند باید کاری مانند پرینت کردن چیزی در لاگ کنسول انجام دهیم. این کار از طریق افزودن یک مشخصه به نام مشخصهی دادهای که میخواهیم تحت نظر بگیریم به شیء watch میسر است:
1<script>
2export default {
3 data() {
4 return {
5 name: 'Flavio'
6 }
7 },
8 methods: {
9 changeName: function() {
10 this.name = 'Flavius'
11 }
12 },
13 watch: {
14 name: function() {
15 console.log(this.name)
16 }
17 }
18}
19</script>
تابع انتساب یافته به watch.name میتواند به طور اختیاری 2 پارامتر بگیرد. پارامتر اول مقدار مشخصه جدید و دومی مقدار مشخصه قدیمی است:
1<script>
2export default {
3 /* ... */
4 watch: {
5 name: function(newValue, oldValue) {
6 console.log(newValue, oldValue)
7 }
8 }
9}
10</script>
Watcher-ها چنان که در مورد مشخصههای محاسبهشده انجام میدادیم، نمیتوانند از روی قالب بررسی شوند.
مشخصههای محاسبه شده
در این بخش به توضیح مفهوم «مشخصههای محاسبه شده» (Computed Properties) میپردازیم.
مشخصههای محاسبه شده چه هستند؟
در Vue.js میتوان هر مقدار دادهای را با استفاده از پرانتز در خروجی ارائه کرد:
1<template>
2 <p>{{ count }}</p>
3</template>
4
5<script>
6export default {
7 data() {
8 return {
9 count: 1
10 }
11 }
12}
13</script>
این مشخصه میتواند میزبان محاسبات کوچکی باشد. به مثال زیر توجه کنید:
1<template>
2 {{ count * 10 }}
3</template>
اما در این روش محدود به یک عبارت منفرد جاوا اسکریپت هستیم. علاوه بر این محدودیت تکنیکی، باید این نکته را در نظر داشته باشید که قالبها باید تنها به نمایش دادهها برای کاربر بپردازند و اجرای محاسبات منطقی وظیفه آنها نیست.
برای انجام کاری بیش از یک عبارت منفرد، و برای این که قالبهای دستوریتر داشته باشیم، باید از مشخصه محاسبهشده استفاده کنیم. مشخصههای محاسبه شده در مشخصه computed کامپوننت Vue تعریف میشوند:
1<script>
2export default {
3 computed: {
4
5 }
6}
7</script>
نمونهای از یک مشخصه محاسبه شده
در ادامه مثالی را بررسی میکنیم که از یک مشخصه محاسبهشده به نام count برای محاسبه خروجی استفاده میکند. توجه داشته باشید که ما ملزم به فراخوانی {{ ()count }} نیستیم. Vue.js تابع را به صورت خودکار فراخوانی میکند.
ما از یک تابع معمولی (نه یک تابع arrow) برای تعریق مشخصه محاسبه شده با نام count استفاده میکنیم، زیرا باید بتوانیم از طریق this به وهله کامپوننت دسترسی پیدا کنیم.
1<template>
2 <p>{{ count }}</p>
3</template>
4
5<script>
6export default {
7 data() {
8 return {
9 items: [1, 2, 3]
10 }
11 },
12 computed: {
13 count: function() {
14 return 'The count is ' + this.items.length * 10
15 }
16 }
17}
18</script>
مقایسه مشخصههای محاسبه شده و متدها
اینک که با متدهای Vue و مشخصههای محاسبه شده آشنا شدید شاید کنجکاو باشید که تفاوت آنها در چیست. اولین تفاوت این است که متدها باید فراخوانی شوند و ارجاع دادن به آنها کافی نیست، بنابراین باید به صورت زیر عمل کنید:
1<script>
2export default {
3 data() {
4 return {
5 items: [1, 2, 3]
6 }
7 },
8 methods: {
9 count: function() {
10 return 'The count is ' + this.items.length * 10
11 }
12 }
13}
14</script>
اما تفاوت اصلی این است که مشخصههای محاسبهشده کَش میشوند. نتیجه مشخصه محاسبهشده count به صورت داخلی تا زمانی که مشخصه دادهای items تغییر نیافته است، کش میشود.
نکته مهم: مشخصههای محاسبه شده تنها زمانی بهروزرسانی میشوند که منابع واکنشی بهروز شوند. متدهای معمولی جاوا اسکریپت واکنشی نیستند و از این رو مثال رایجی که برای نمایش این تفاوت استفاده میشود Date.now() است:
1<template>
2 <p>{{ now }}</p>
3</template>
4
5<script>
6export default {
7 computed: {
8 now: function () {
9 return Date.now()
10 }
11 }
12}
13</script>
این متد یک بار رندر میشود و سپس حتی زمانی که کامپوننت مجدداً رندر شود، رندر مجدد نخواهد شد. تنها در صورت رفرش شدن صفحه بهروزرسانی میشود و این زمانی است که کامپوننت Vue ترک شود و از نو راهاندازی شود. در این حالت متد برای رفع نیازها مناسبتر خواهد بود.
مقایسه متد با Watcher و مشخصههای محاسبه شده
اکنون که با متدها، Watcher-ها و مشخصههای محاسبه شده آشنا شدیم، به مقایسه آنها و کاربردهای هر کدام میپردازیم. پاسخ این سؤال به شرح زیر است.
چه زمانی از متد استفاده کنیم؟
- برای واکنش به رویدادی که در DOM اتفاق میافتد.
- برای فراخوانی یک تابع هنگامی که اتفاقی در کامپوننت میافتد. متد را میتوان از مشخصههای محاسبه شده یا Watcher ها فراخوانی کرد.
چه زمانی از مشخصههای محاسبه شده استفاده کنیم؟
- زمانی که باید دادههای جدیدی از منابع دادهای موجود تشکیل دهیم.
- متغیری داشته باشیم که در قالب استفاده کنیم و از یک یا چند مشخصه ساخته شده باشد.
- بخواهیم یک نام مشخصه پیچیده و تو در تو را به چیزی که خوانایی بیشتری دارد و استفاده از آن نیز سادهتر است کاهش دهیم (اما زمانی بهروزرسانی میشود که مشخصه اصلی تغییر پیدا کند.)
- به ارجاعی به یک مقدار از قالب نیاز داشته باشیم. در این مورد ایجاد یک مشخصه محاسبه شده بهترین کار است زیرا کش میشود.
- نیاز باشد به تغییرهای بیش از یک مشخصه دادهای گوش دهیم.
چه زمانی از Watcher-ها استفاده کنیم؟
- زمانی که بخواهیم ببینیم چه زمانی مشخصه دادهای تغییر مییابد و اکشن خاصی اجرا کنیم.
- بخواهیم به تغییر مقدار یک prop گوش دهیم.
- لازم باشد صرفاً به یک مشخصه خاص گوش دهیم (و نتوانیم به چندین مشخصه به صورت همزمان توجه کنیم).
- بخواهیم مشخصه دادهای را تا زمانی که به مقدار معینی میرسد تحت نظر قرار دهیم و سپس کار مشخصی انجام دهیم.
Props برای ارسال داده به کامپوننتهای فرزند
Props روشی هستند که کامپوننتها میتوانند دادهها را از کامپوننتهایی که والدشان هستند بپذیرند. زمانی که یک کامپوننت یک یا چند prop قبول میکند، باید آنها را در مشخصه props خود تعریف کند:
1Vue.component('user-name', {
2 props: ['name'],
3 template: '<p>Hi {{ name }}</p>'
4})
در مورد کامپوننتهای تک فایلی به صورت زیر عمل میکنیم:
1<template>
2 <p>{{ name }}</p>
3</template>
4
5<script>
6export default {
7 props: ['name']
8}
9</script>
پذیرش چندین props
با الحاق props به یک آرایه میتوان چند مورد از آنها را با هم داشت:
1Vue.component('user-name', {
2 props: ['firstName', 'lastName'],
3 template: '<p>Hi {{ firstName }} {{ lastName }}</p>'
4})
تعیین نوع props
نوع props را میتوان با استفاده از یک شیء به جای یک آرایه تعیین کرد. به این منظور از نام مشخصه به عنوان کلید هر مشخصه و از نوع به عنوان مقدار آن استفاده میکنیم:
1Vue.component('user-name', {
2 props: {
3 firstName: String,
4 lastName: String
5 },
6 template: '<p>Hi {{ firstName }} {{ lastName }}</p>'
7})
انواع مجاز که میتوان استفاده کرد به شرح زیر هستند:
- String
- Number
- Boolean
- Array
- Object
- Date
- Function
- Symbol
زمانی که ناسازگاری نوع پدید میآید، Vue (اگر در حالت توسعه باشد) هشداری در کنسول ارائه میکند. نوعهای props میتوانند دستهبندی شوند. بدین ترتیب میتوان انواع مقدار متفاوتی داشت:
1props: {
2 firstName: [String, Number]
3}
الزامی ساختن prop
میتوان یک prop را به صورت الزامی تعیین کرد:
1props: {
2 firstName: {
3 type: String,
4 required: true
5 }
6}
تعیین مقدار پیشفرض یک prop
برای یک prop میتوان مقدار پیشفرض تعیین کرد:
1props: {
2 firstName: {
3 type: String,
4 default: 'Unknown person'
5 }
6}
در مورد اشیا به صورت زیر عمل میکنیم:
1props: {
2 name: {
3 type: Object,
4 default: {
5 firstName: 'Unknown',
6 lastName: ''
7 }
8 }
9}
Default میتواند به جای یک مقدار واقعی، یک تابع نیز باشد که مقدار مناسب را بازگشت میدهد. حتی میتوان یک validator سفارشی ساخت که در مورد دادههای پیچیده مناسبتر است:
1props: {
2 name: {
3 validator: name => {
4 return name === 'Flavio' //only allow "Flavios"
5 }
6 }
7}
ارسال props به کامپوننت
اگر چیزی که ارسال میشود یک مقدار استاتیک باشد، با استفاده از ساختار زیر میتوان یک prop را به کامپوننت ارسال کرد:
1<ComponentName color="white" />
اگر یک مشخصه دادهای است، میتوان از ساختار زیر بهره گرفت:
1<template>
2 <ComponentName :color=color />
3</template>
4
5<script>
6...
7export default {
8 //...
9 data: function() {
10 return {
11 color: 'white'
12 }
13 },
14 //...
15}
16</script>
میتوانید از عملگر سهتایی درون مقدار prop برای بررسی شرط درست بودن و ارسال یک مقدار که به آن وابسته است استفاده کنید:
1<template>
2 <ComponentName :colored="color == 'white' ? true : false" />
3</template>
4
5<script>
6...
7export default {
8 //...
9 data: function() {
10 return {
11 color: 'white'
12 }
13 },
14 //...
15}
16</script>
بدین ترتیب به پایان بخش هفتم از سری مقالات آموزش فریمورک Vue.js میرسیم. برای مطالعه بخش بعدی روی لینک زیر کلیک کنید:
اگر این مطلب برای شما مفید بوده است، آموزشهای زیر نیز به شما پیشنهاد میشوند:
- مجموعه آموزشهای JavaScript (جاوا اسکریپت)
- مجموعه آموزشهای برنامهنویسی
- آموزش JavaScript ES6 (جاوا اسکریپت)
- آموزش Vue.js: آشنایی با مفاهیم مقدماتی Vue — بخش اول
- پنج ابزار برای توسعه سریع اپلیکیشن های Vue.js — راهنمای کاربردی
==