در جلسه سوم این دوره از مجموعههای آموزشی به توضیح مفصل نوع ارتباط دادهای، قالب، قواعد نحوی و نوشتاری فریمورک قدرتمند Vue.js آشنا شدیم. در این جلسه قصد داریم شما را با دو ویژگی کاربردی و اصولی Computed و Watcher این فریم ورک آشنا کنیم.
همانطور که در جریان هستید، عبارتهای موجود در فریم ورک 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 را با استفاده از متدها پیادهسازی کرد. پاسخ سوال شما "بله" است. در ادامه تفاوتهای بین دو این ویژگی و متدها را بیان خواهیم کرد. به مثال زیر توجه کنید:
<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 را محاسبه و ارسال کنیم که این امر بسیار زمانبر و پرهزینه میباشد.
فریم ورک 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 میباشد که پاسخ درستیست.
ویژگی 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 قرار میدهد.
اگرچه ویژگی 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 در ایران را می توانید از طریق اینجا مشاهده کنید.
در این قسمت، به پرسشهای تخصصی شما دربارهی محتوای مقاله پاسخ داده نمیشود. سوالات خود را اینجا بپرسید.
در این قسمت، به پرسشهای تخصصی شما دربارهی محتوای مقاله پاسخ داده نمیشود. سوالات خود را اینجا بپرسید.
در این قسمت، به پرسشهای تخصصی شما دربارهی محتوای مقاله پاسخ داده نمیشود. سوالات خود را اینجا بپرسید.
در این قسمت، به پرسشهای تخصصی شما دربارهی محتوای مقاله پاسخ داده نمیشود. سوالات خود را اینجا بپرسید.
در این قسمت، به پرسشهای تخصصی شما دربارهی محتوای مقاله پاسخ داده نمیشود. سوالات خود را اینجا بپرسید.
در این قسمت، به پرسشهای تخصصی شما دربارهی محتوای مقاله پاسخ داده نمیشود. سوالات خود را اینجا بپرسید.
در این قسمت، به پرسشهای تخصصی شما دربارهی محتوای مقاله پاسخ داده نمیشود. سوالات خود را اینجا بپرسید.