هر وهله از Vue از یکسری مراحل یا (initialization steps) عبور خواهد کرد به عنوان مثال مراحلی از قبیل کامپایل شدن تمپلیت، mount شدن وهله به DOM و یا بروزرسانی DOM زمانیکه دادهها تغییر پیدا میکنند و ... در حین طی کردن این مسیر یکسری توابع ویژه با نام lifecycle hooks فراخوانی خواهند شد. بنابراین درون این توابع میتوانیم در هر مرحله کدهای موردنیازمان را قرار دهیم:
همانطور که مشاهده میکنید این چرخه حیات با وهلهسازی شیء Vue شروع میشود. در این مرحله اولین تابع یعنی beforeCreate فراخوانی میشود. در این مرحله کار مقداردهی اولیه (initialization) ایونتهای پاس داده شده به Vue instance انجام خواهد گرفت. در مرحله بعد تابع created فراخوانی و در ادامه تمپلیت (اگر تعیین شده باشد) کامپایل و بعد از آن تابع beforeMount فراخوانی خواهد شد. این تابع دقیقاً قبل از اینکه تمپلیت به DOM اضافه شود فراخوانی میشود. در اینحالت المنت تعیین شده در قسمت el با محتوای تمپلیت مقداردهی میشود. البته تا اینجا هنوز خروجی به DOM اضافه نشده است؛ تنها اعمال بایندینگ، string interpolation بر روی تمپلیت صورت خواهند گرفت تا خروجی به صورت یک HTML آماده تحویل به مرحله بعد گردد. در ادامه خروجی تهیه شده به DOM اضافه (mount) خواهد شد. در این مرحله اگر دیتایی تغییر کند، تابع beforeUpdate فراخوانی خواهد شد. بعد از اینکه تغییری توسط Vue مشاهده شد، تابع updated فراخوانی خواهد شد. در نهایت توابع beforeDestroyed و destroyed را داریم. درون این توابع فرصت آزادسازی منابع استفاده شده را خواهیم داشت.
به عنوان مثال بعد از اینکه یک وهله از Vue ایجاد شد، تابعی با نام created فراخوانی خواهد شد:
new Vue({ el: '#app', data() { return { a: 1 }; }, created: function () { // `this` points to the vm instance console.log('a is: ' + this.a) } });
در حالت کلی میتوانیم hookها را به چهار دستهبندی زیر تقسیم کنیم:
(Creation (Initialization
این نوع hook در واقع اولین توابعی هستند که درون یک کامپوننت فراخوانی خواهند شد. در اینجا میتوانیم قبل از اینکه کامپوننت به DOM اضافه شود، اکشن مورد نیازمان را قرار دهیم. باید دقت داشته باشید که درون این توابع، به target element (همان المنتی که وهلهی Vue به آن متصل خواهد شد) و همچنین DOM دسترسی ندارید و مقادیر آنها در این فاز، undefined خواهند بود:
new Vue({ el: '#app', data() { return { name: 'Sirwan' }; }, beforeCreate: function () { console.log('name is: ' + this.name); console.log(`We don't have access to target element at this point: ${this.$el}`); }, created: function () { // `this` points to the vm instance console.log('name is: ' + this.name); console.log(`We don't have access to target element at this point: ${this.$el}`); } });
(Mounting (DOM Insertion
در این مرحله میتوانیم بلافاصله قبل و بعد از اولین رندر، به کامپوننت دسترسی داشته باشیم. میتوانیم از این hookها برای تغییر کامپوننت، به محض رندر شدن استفاده کنیم. بنابراین در این فاز به target element نیز دسترسی خواهیم داشت:
beforeMount: function () { console.log(`this.$el doesn't exist yet, but it will soon!`); }, mounted: function () { console.log(this.$el); }
(Updating (Diff & Re-render
این توابع هنگامیکه دادههای تعریف شده در قسمت data تغییر پیدا کنند، فراخوانی خواهند شد. یعنی دقیقاً قبل از اینکه DOM بهروزرسانی شود، فراخوانی خواهند شد. در مثال زیر به محض ایجاد شدن وهلهی Vue، یک تایمر ایجاد شده است. این تایمر هر ثانیه یکبار مقدار دیتای counter را یک واحد افزایش خواهد داد. در حالت عادی اگر دیتایی درون DOM استفاده نشده باشد، درون کنسول خروجی را دریافت نخواهید کرد. در نتیجه این توابع تنها در صورتیکه از دیتا درون DOM استفاده شده باشد، فراخوانی خواهند شد:
new Vue({ el: '#app', data() { return { name: 'Sirwan', counter: 0 }; }, created: function () { setInterval(() => { this.counter++ }, 1000) }, beforeUpdate: function () { console.log(this.counter); // Logs the counter value every second, before the DOM updates. }, updated: function () { console.log(`new value: ${this.counter}`); } });
(Destruction (Teardown
این توابع، قبل و بعد از تخریب شدن (حذف شدن از DOM) کامپوننت فراخوانی خواهند شد:
new Vue({ el: '#app', data() { return { name: 'Sirwan', counter: 0 }; }, beforeDestroy: function () { }, destroyed() { console.log(this) // There's practically nothing here! } });
Vue.js چگونه تغییرات دادهها را متوجه خواهد شد؟
شاید تصور کنید که Vue.js به صورت مداوم تغییرات را مشاهده کرده و در صورت وجود تغییری بر روی دیتا، این تغییرات را مستقیماً به DOM اعمال خواهد کرد. هر پراپرتی دارای یک watcher است؛ یعنی وقتی یک شیء را به سازنده Vue ارسال میکنیم، یک watcher برای تمامی پراپرتیهای تعریف شده، درون پراپرتی data ایجاد خواهد کرد. این watcher در واقع مسئول کنترل تغییرات پراپرتیها میباشد و اگر تغییری صورت بگیرد، آن را به DOM اعمال خواهد کرد. اما نکته اینجاست که این تغییرات بلافاصه بر روی DOM اعمال نخواهند شد؛ زیرا از لحاظ کارآیی، اینکار بهینه نیست. فرض کنید یک پراپرتی با نام message درون قسمت data داریم که مقدار آن Hello است. اکنون همین مقدار توسط UI مجدداً به Hello ست خواهد شد. در اینحالت اعمال تغییرات نباید به DOM منعکس شود، زیرا مقدار message به همان مقدار قبلی تنظیم شده است. در عوض Vue.js از مفهومی با نام Virtual DOM استفاده میکند که در واقع یک کپی از DOM اصلی است؛ با این تفاوت که دسترسی به آن خیلی سریعتر از DOM اصلی میباشد. بنابراین Vue.js تغییرات صورت گرفته را مستقیماً به Virtual DOM اعمال میکند. در نهایت آن را با DOM اصلی مقایسه خواهد کرد و در صورت وجود تغییر، آن را با DOM اصلی ادغام خواهد کرد.