جلسه چهارم: معرفی ویژگی‌های Computed و Watch در Vue.js

Introducing Computed and Watch features in Vue.js

10 مرداد 1400
درسنامه درس 4 از سری آموزش مقدماتی Vuejs
4-vujsmain

در جلسه سوم این دوره از مجموعه‌های آموزشی به توضیح مفصل نوع ارتباط داده‌ای، قالب، قواعد نحوی و نوشتاری فریم‌ورک قدرتمند Vue.js آشنا شدیم. در این جلسه قصد داریم شما را با دو ویژگی کاربردی و اصولی Computed و Watcher این فریم ورک آشنا کنیم.

مقدمه ویژگی‌های Computed

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

<div id="example">
	{{ message.split('').reverse().join('') }}
</div>

در این حالت قالب نوشتاری شما خیلی راحت و قابل فهم نیست. زیرا برای فهمیدن آن نیاز به دوباره خوانی دارید تا بدانید که در این کدها، متغییر message معکوس می‌شود. این موضوع بسیار غیر قابل فهم و سخت می باشد. برای ساده سازی این عبارت پیچیده از ویژگی Computed استفاده می‌کنیم. جهت تفهیم این موضوع مثال ساده زیر را بررسی می‌کنیم:

<div id="example">
	<p>متن اصلی پیام: {{ message }}</p>
	<p>متن پیام معکوس شده: {{ reversedMessage }}</p>
</div>

var vm= new Vue({
	el: '#example',
	data: {
		message:  'Hello Roxo.ir'
	},
	computed: {
		// گیرنده Computed
		reversedMessage: function(){
			return this.message.split('').reverse().join('')
		}
	}
})

در این مثال ما یک ویژگی محاسباتی (Computed) تحت عنوان reservedMessage به مجموعه کدهای خود اضافه کردیم. تابع تعریف شده در این ویژگی به فرمت vm.reservedMessage قابل دسترس خواهد بود. به مثال‌های زیر توجه کنید:

console.log(vm.reversedMessage) // -> ri.oxor olleH
vm.message= Goodbye
console.log(vm.reversedMessage) // -> eybdooG

در مثال بالا کنسول را باز کردیم و اطلاعات موردنظر خود را با متغییر message به گیرنده‌ی computed فرستادیم. در نهایت جواب برای متغییر message برابر Goodbye و برای کل تابع reversedMessage برابر eybdooG می‌باشد. همینطور که در جریان هستید، با تغییر message اطلاعات موجود در بخش reversedMessage تغییر خواهد کرد. بنابراین به صورت کاملا تطابقی هرگونه به اصطلاح Binding‌ای در ویژگی‌های computed بروزرسانی خواهد شد.

تفاوت بین ویژگی computed و متدها (Computed vs Methods)

ممکن است برای شما سوال پیش بیاید که می‌توان ویژگی computed را با استفاده از متدها پیاده‌سازی کرد. پاسخ سوال شما "بله" است. در ادامه تفاوت‌های بین دو این ویژگی و متدها را بیان خواهیم کرد. به مثال زیر توجه کنید:

<p> متن پیام معکوس شده: {{ reversedMessage }}</p>

var vm = new Vue{
	data:{
		message: "Hello Roxo.ir"
	}
	methods: {
		reversedMessage: function(){
			return this.message.split('').reverse().join('')
		}
	}
}

همانطور که در مثال بالا مشاهده کردید می‌توان به‌جای استفاده از ویژگی computed، از یک متد و تابع همراه آن استفاده کرد و نتایج یکسانی را دریافت نمود. اما آنچه که وجه تمایز این دو روش را مشخص می‌کند، در بخش کش (حافظه نهان) می‌باشد. یک ویژگی Computed تنها زمانی شروع به پردازش مجدد می‌کند که مقدار متغیرهای وابسته به آن تغییر می‌کرد. این بدین معنی است که اگر message در مثال بالا تغییر نکند، مقدار reversedMessage برابر همان مقدار قبلی خواهد بود و هیچگونه اجرای مجددی برای ویژگی Computed رخ نمی‌دهد.

به عنوان مثال مقدار computed زیر هیچگاه تغییری نمی‌کند، زیرا مقدار Date.now() همواره ثابت می‌باشد و هیچگونه واکنشی در آن امکان‌پذیر نیست.

computed: {
	now: function(){
		return Date.now()
	}
}

اما در متدها روند بدین صورت نیست، بلکه برنامه همواره پس از هربار رندر شدن، اجرا می‌شود.

یک سوال: چرا برنامه‌های ما به کش نیاز دارند؟
پاسخ: تصور کنید ما یک ویژگی محاسباتی (Computed) به نام A داریم که درون یک آرایه بسیار بزرگ مدام به اجرای برخی کارهای محاسباتی می‌پردازد. از طرفی ما ویژگی محاسباتی (Computed) دیگری داریم که به ویژگی محاسباتی A وابسته است. بدون کش شدن، ما همواره باید ابتدا A را محاسبه و ارسال کنیم که این امر بسیار زمان‌بر و پر‌هزینه می‌باشد.

تفاوت بین ویژگی‌ Computed و Watched

فریم ورک Vue.js یک راه دیگری برای مشاهده و واکنش به تغییرات داده، در اختیار ما قرار داده است که به آن ویژگی Watch گفته می‌شود. هنگامی که برخی از داده‌ها که به سایر داده‌ها وابسته هستند، نیاز به تغییرات داشته باشند، به ویژگی Watch نیاز داریم. بخصوص اگر Backend وب سایت شما با انگولار کنترل شود. هر چند استفاده از ویژگی Computed در بسیاری از موارد توصیه می‌شود. به مثال زیر توجه کنید:

<div id="roxoApp"> {{ fullName }} </div>

var vm = new Vue({
	el: '#roxoApp'
	data: {
		firstName: 'Masoud',
		lastName: 'Salehi',
		fullName: 'Masoud Salehi'
	},
	watch:{
		firstName: function(val){
			this.fullName = val + ' ' + this.lastName
		}
		lastName: function(val){
			this.fullName = this.firstName + ' ' + val
		}
	}
}})

همانطور که ملاحظه می‌کنید، در قسمت ویژگی Watch کد بالا یک مقداری تکرار وجود دارد. حال کد بالا را با کد زیر مقایسه کنید که از ویژگی Computed در آن استفاده شده است:

<div id="roxoApp"> {{ fullName }} </div>

var vm = new Vue({
	el: '#roxoApp'
	data: {
		firstName: 'Masoud',
		lastName: 'Salehi',
	},
	computed:{
		fullName: function(){
			return this.firstName + ' ' + this.lastName
		}
	}
}})

کدام بهتر است؟ قطعا پاسخ شما استفاده از ویژگی Computed می‌باشد که پاسخ درستی‌ست.

Setter ویژگی Computed یا Computed Setter

ویژگی‌ Computed به صورت پیش‌فرض دریافت‌کننده (getter) می‌باشند، اما می‌توانیم یک ویژگی محاسباتی جایگزینی (setter) ایجاد کنیم تا در صورت لزوم از آن استفاده کرد. به مثال زیر توجه کنید:

// ...
computed: {
	fullName: {
		// getter
		get: function(){
			return this.fullName + ' ' + this.lastName
		},
		// setter
		set: function(newValue){
			var names= newValue.split(' ')
			this.firstName = names[0]
			this.lastName = names[names.length - 1]
		}
	}
}

بنابراین با توجه به مثال بالا اگر شما دستور vm.fullName = 'Roxo Tutorials' را بنویسید، Setter با استخراج vm.firstName و vm.lastName مقادیر جدید را درون firstName و lastName قرار می‌دهد.

ناظر (Watchers)

اگرچه ویژگی Computed در بسیاری از موارد مفید می‌باشد اما باید در نظر داشته باشیم بعضی اوقات ممکن است یک ناظر واقعی و ضروری برای برنامه‌ها نیاز باشد. که این ناظر تحت عنوان ویژگی Watch مطرح می‌شود. به همین دلیل یک ویژگی تحت عنوان watch برای فریم ورک قدرتمند Vue.js ایجاد شده است. این ویژگی مانند ویژگی Computed برای حالتی که نیاز به اجرای ناهمزمان برنامه‌ است بسیار مفید می‌باشد. به نمونه‌ کد زیر توجه کنید:

<div id="roxoApp">
	<p>
		پرسیدن یک سوال که جواب بله یا خیر دارد:
		<input v-model = "question">
	</p>
	<p> {{ answer }} </p>
</div>

// تابع _.debouce
// به عنوان یک محدودکننده برای اجرای عملیاتهای محاسباتی سنگین
// مورد استفاده قرار می گیرد که از کتابخانه ی lodash
// فراخوانی می شود. در اینجا ما میخواهیم دسترسی به api
// سایت yesno/wtf/api را 
// محدود کنیم.

<script src="https://unpkg.com/axios@0.12.0/dist/axios.min.js"></script>
<script src="https://unpkg.com/lodash@4.13.1/lodash.min.js"></script>
<script>
var watchExampleVM = new Vue({
	el: "#roxoApp"
	data: {
		question: '',
		answer: ' تا زمانیکه شما سوالی نپرسیدید، نمیتوانیم به شما پاسخی بدهیم '
	},
	watch: {
		question: function(newQuestion){
			this.answer = 'تا لحظه اتمام تایپ شما، لطفا صبر کنید...'
			this.getAnswer()
		}
	}
	method:{
		getAnswer: _.debounce{
			var vm = this
			if(this.question.indexOf('?') === -1){
				vm.answer = "سوالهای شما باید شامل علامت سوال ؟ باشند"
				return
			}
			vm.answer = 'در حال پاسخگویی'
			axios.get('https://yesno.wtf/api')
				.then(function(response){
					vm.answer = _capitalize(response.data.answer)
				})
				.catch(function(error){
					vm.answer = 'خطا، عدم برقراری ارتباط با Api' + error
				})
		},
		// مدت زمانیکه برای پاسخ باید انتظار کشید
		// تا کاربر تایپ نکند
		500
	}
})
</script>

در این مثال از ویژگی watch برای اجرای یک علمیات ناهمزمان استفاده شد که این عملیات با دسترسی به Api امکان‌پذیر بود. این Api دسترسی ما را به برخی از عملکردها محدود کرد و در نهایت یک وضعیت پایدار را برای پاسخگویی به سیستم ایجاد نمود. هیچ یک از این محدودیت ها و دسترسی ها با استفاده از یک ویژگی Computed امکان‌پذیر نیست. چون با استفاده از ویژگی Computed نظارتی روی سیستم صورت نمی‌گیرد.

جامع ترین دوره آموزشی Vue.js 2.0 در ایران را می توانید از طریق اینجا مشاهده کنید.

آموزش ویدیویی Vuejs فارسی

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

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

fatemeh
27 شهریور 1400
سلام فروردین ماه این سایت یک اموزش ویو داشت که خیلی مرتب و تمیز توضیح داده بود ..و همچنین سرفصلهاش خیلی بیشتر بود ..نمی دونم چرا اونو برداشتین و اینو گذاشتین؟!

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

روکسو
28 شهریور 1400
سلام وقت بخیر هیچ آموزشی از روی سایت حذف نشده

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

مهدی
28 مرداد 1399
سلام ظاهرا یکی فقط این متن رو ترجمه کرده ذهنیت برنامه نویسی نداشته یا اگه هم داشته آماتور بوده! اینجا ذکر کردین ". بخصوص اگر Backend وب سایت شما با انگولار کنترل شود." ترجمه درستش میشه بخصوص برای کسی که با AngularJS آشنایی داشته ...

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

arman
30 فروردین 1397
کدهای قبلی اجرا میشد ولی چندتا کد آخر اجرا نمیشه و خودم باید ویرایشش کنم بحث این نیس که کدها در تگ بادی و اسکریپت نیست بلکه قلم خوردگی های دیگه هم داره...

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

امید
11 مرداد 1396
خیلی ممنونم، فقط کاش کدهاتون رو تست هم کنید، چون نمیشه ازشون استفاده کرد، من برای تست مجبور شدم برم از سایت اصلی Vuejs کد نمونه رو بردارم.

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

arman
30 فروردین 1397
دقیقا

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