Vue.js - Komponentlər ilə işin təşkili

Abdulla Emchiyev
8 min readMar 11, 2019

İnterfeys qurarkən kodlaşdırmada əsas məsələlərdən biri də prosesə obyekt yönümlü baxa bilməkdir. Belə ki, hazırladığınız proyekt bir-biri ilə əlaqəli ancaq ayrıca spesifik fərqlər ilə və ya hansısa quruluşuna görə ayrıca olaraq hazırlanan hissələrdən ibarət ola bilir. Belə nüanslarda kodları bir faylda və ya bir kod blokunun daxilində icra etmək işin daha da çətinləşməsinə, daha sonra isə oxunaqlılığına mənfi təsir edir. Buna görə də yazdığımız kodu kiçik və məntiqi hissəciklərə ayırmaqla, daha effektiv və yenidən istifadə oluna bilən formaya gətirib çıxarmalıyıq. Vue.js daxilində də interfeys hissəciklərini ayrı-ayrı hazırlamaq imkanımız vardır. Bunun üçün komponentlərdən (component) istifadə olunur.

Komponentlərin istifadəsi sizə həm kodu hissəciklərə bölməyə, həm də digər bir səhifədə eyni işi görəcək uzun kodu yox, sadəcə komponenti daxil edərək istifadə etməyə imkan verir. İndi isə praktiki bir misal üzərindən komponentlər ilə işləməyin necə olmasına başlayaq. Yeni html fayl yaradaraq ora Vue.js-in istifadə oluna bilməsi üçün lazım olan ilkin kodu əlavə edək.

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>

<body>
<div id="app">

</div>

<script>
var app = new Vue({
el: '#app',
data: {

}
})

</script>
</body>
</html>

Üst tərəfdəki kodları əlavə etdikdən sonra artıq Vue.js istifadə edərək işimizə başlaya bilərik. İlkin olaraq minimal bir səhifənin görüntüsünü ən sadə formada hazırladım. Səhifəni hazırlamaqda məqsədim kodu refactor (daha uyğun hala salmaq) edərək komponent strukturuna keçid zamanı nə kimi faydalar əldə edə biləcəyimizi praktiki formada görməkdir.

Aşağıdakı kodu kopyalayaraq yaratdığınız html faylına daxil edin və save edərək səhifəni yeniləyin.

Qarşınıza üst tərəfdə şəkildəki kimi Vue.js və və bootstrap ilə hazırlanmış sadə bir xəbər saytı görünüşü çıxmalıdır. İndi isə kodumuzu incələməyə başlayaq. İlkin olaraq bootstrap row-unun birinci div-inin daxilində xəbərlərin necə formalaşdığını görə bilərik. Belə ki, Vue-nin data property-si daxilində news adında array təyin etmişik və onları v-for xüsusi direktivi ilə loop edərək html-i formalaşdırırıq. Xəbərlərin məlumatları obyekt formasında olduğu üçün hər bir obyektin property-sinə native javascriptdə olduğu kimi nöqtə ilə keçid edə bilirik. Beləliklə, h1 tag daxilində xəbərin adı {{ newsContent.name }} , h4 tagı daxilində başlığı {{newsContent.header}}, p tagı daxilində isə xəbərin mətni {{newsContent.body}} göstərilmişdir. 3 ədəd xəbərimiz olduğuna görə v-for ilə avtomatik olaraq 3 ədəd xəbər öz məlumatlarına uyğun olaraq yerləşdirilmiş olur. 2ci olaraq isə sağ tərəfdə digər bölmələrə keçidləri göstərmişik. Onlar da hazır məlumatlar əsasında v-for loop-u ilə səhifəyə render olunur. Belə ki, link obyeklərini təşkil edən links adlı array data daxilində göstərilmişdir. Tərkibində isə urlname property-lərini saxlayır. 3cü olaraq isə reklamlar bölməsi, əlavə linklər bölməsinin alt hissəsində yerləşdirilmiş və data daxilindəki adds array-ı əsasında formalaşmışdır.

Göründüyü kimi komponentlər olmadan da eyni istədiyimiz funksinallığı etmək və nəticəni almaq mümkündür. Ancaq kodun komponentlər formasında ayrılması və ya ümumiyətlə hər bir səhifəmizdə təkrarən istifadə edə biləcəyimiz reusable komponentlər yaratmaq bizə strukturun formalaşmasında çox böyük kömək edir. İndi isə başlayaq kodumuzu komponentlər formasında ayıraraq refactor etməyə.

Aşağıda gördüyünüz kodlar 1ci fayldakı kodlarda görülən işlərin eynisini edir, ancaq bu dəfə html tagları daxilində bütün işi görmək əvəzinə hissə-hissə onları Vue komponentlərinə ayırmışıq.

Göründüyü kimi, html daxilində sadəcə komponentlərimizin adları göstərilmişdir. html hissələri isə 3 ədəd Vue komponenti formasında saxlanmışdır. Vue üçün komponent yaradılmasında Vue.component() metodundan istifadə edilir. 1ci olaraq komponentin adı, 2ci isə onunla əlaqəli olan spesifik məlumatlar obyekt formasında ötürülür. 1-ci komponentimiz üzərində izah etsək ilkin olaraq yeni olan template property qarşımıza çıxacaqdır. Template göründüyü kimi html daxilində yazdığımız formanı özündə əks etdirir. Onun daxilində göstərilən html əvvəlki kodda olduğu kimi render olunacaqdır. Template yazılışı sizin üçün çətin kimi görünə bilər ancaq bu ən sadə formada HTML fayl daxilində komponentin yaranması üçün kifayətdir. Ancaq daha irəli səviyyədə komponentlər hər biri ayrı fayllarda saxlanılaraq istifadə olunur. Növbəti məqalədə bu haqda ətraflı danışacam və misallar üzərindən izah edəcəm. İndi isə komponentlərimizin necə işlədiyini incələməyə davam edək.

Diqqət etməniz gərəkən əsas nüans isə data property-nin yazılış formasıdır. Komponentlər daxilində data funksiya olmalı və daxilindəki dəyişənləri qaytarmalıdır (return). Əks halda Vue error olaraq bunu etməyinizin mütləq olduğunu console — da göstərəcəkdir. Bundan sonra isə Vue daxilində işlədilən computed, methods, created, mounted ve s. bütün əməliyyatlar hər komponent daxilində eynilə yerinə yetirilə bilər.

Komponentlər bir biri ilə məlumat mübadiləsində iştirak edirlər. Praktikada komponentlərin yaradılmasının əsas məqsədi də onlara məlumatın ötürülərək, öz daxilində uyğun əməliyyatları etməsi və lazımi nəticələri göstərməsidir. Misal ilə əvvəlki kodumuzu dəyişərək məlumat mübadiləsini göstərək.

İlkin olaraq hər bir komponentimizdən data daxilindəki məlumatları əsas Vue obyektimizə geri qaytardıq. Komponentlər daxilində isə props property təyin elədik. Props Vue komponentlərinə məlumat ötürmək üçündür, komponentə spesifik property rolunu oynayır. Kodu son formaya dəyişdikdən və səhifəni yenilədikdən sonra hər şeyin əvvəlki formada davam etdiyini görə bilərsiniz. html daxilində isə komponentlərimizə props daxilində təyin etdiyimiz adı istifadə edərək komponentə (:news=”news”) html atributu kimi məlumat ötürməsini yerinə yetirdik (əgər prop adı somePropName kimi uzun olduqda onu komponent tagı üzərində göstərən zaman some-prop-name kimi defs ilə ayıraraq yazmaq lazımdır). Məlumatlar render vaxtı avtomatik olaraq öz komponentlərində yerlərinə gəlmiş olur. Props ötürülməsi zamanı array formasında nə qədər lazımdırsa property yaratmaq mümkündür. Bundan başqa props ilə komponentə ötürülən datanın validasiyasını, təyin etdiyimiz qaydalara uyğunluğunu da göstərə bilirik. Misal ilə göstərim.

1-ci news-holder komponenti dəyişmişdir.

<div class="col-md-9 col-12">
<news-holder :news="news" date="yesterday"></news-holder>
</div>

Eyni zamanda komponent scriptləri də aşağıdakı formada dəyişmişdir.

Vue.component('news-holder', {
template: '<div>\n' +
'<div class="news-holder" v-for="newsContent in news">\n' +
'<h1 class="text-danger">{{newsContent.name}}</h1>\n' +
'<h4 class="text-primary">{{newsContent.header}}</h4>\n' +
'<p>{{newsContent.body}}</p>\n' +
'<div class="mb-2 text-info">{{date}}</div>\n' +
'<div style="border: 1px dashed;"></div>\n' +
'</div>\n' +
'</div>',

props: {
news: {
type: Array,
required: true
},
date: {
type: String,
required: false,
default: 'today'
}
}

});

Burada göründüyü kimi ilkin olaraq xəbərin tarixini bildirən date adlı props yaratdıq. Eyni zamanda newsdate property-lərinin tipini, mütləq olub olmamasını və olmaz isə default olaraq yerində nəyi göstərmək istədiyimizi təyin etdik. (required false olduqda default göstərməyə də bilərsiniz). Beləliklə komponentin qəbul edə biləcəyi dataları təyin etdik. Əgər komponentə ötürülən məlumat göstərilən tip ilə uyğun olmazsa xəta çıxacaqdır. Bundan başqa html daxilində də news-holder komponentimizə date property üçün sadə yazı formasında yesterday yazaraq onu komponentimizə keçirdik. Diqqət etdiysəniz v-bind və ya iki nöqtə işlətmədən keçirmə əməliyyatı etdim. Belə ki, məlumatı dəyişən yox, sadə yazı və ya rəqəm formasında ötürən zaman v-bind istifadə etməyə ehtiyac yoxdur. Komponent daxilində isə date prop tipinin String olduğunu göstərmişdik və bu tələbə cavab verdiyi üçün xəta baş vermədən səhifə render olunacaqdır.

Komponentlər ana komponentdən məlumat almaq ilə yanaşı ana komponentə geri məlumat ötürə bilirlər. Bunun üçün $emit prosesi yerinə yetirilir. Emit dedikdə daxildəki komponentin təyin olunan işi gördükdən sonra ana komponentə məlumat ötürməsi üçün event göndərməsidir. Daha aydın olması üçün misal ilə istifadə olunmasını göstərim.

Misalda ilkin olaraq xəbər komponentinə xəbəri oxuduğumuzu təsdiqləyən button əlavə etdik və göstərdik ki, buttona tıklandıqda readNews metodu işə düşsün və bir event atsın (fire). Vue-də eventlər $emit yolu ilə göndərilir. 1-ci parametrdə isə eventin adının nə olacağını göstərilir.

readNews(newsNum){
this.$emit('read', newsNum);
}

Bundan sonra isə news-holder komponentinə bu event atıldığı zamanı onun əsas komponentdə necə istifadə olunmasını anlaması üçün eventin adı ilə eyni olan event təyin edirəm.

<div class="col-md-9 col-12">
<news-holder :news="news" v-on:read="newsRead" date="yesterday"></news-holder>
</div>

Gördüyünüz kimi v-on:read digər standart v-on:click, v-on:change eventləri kimi artıq istifadə oluna bilir. Həmin event göndərilən zaman isə nəyin baş verəcəyini təyin edən funksiyanı göstərmişəm. Həmin funksiya root (kökdəki) Vue obyektində saxlanılır. Siz oxudum button-una tıkladıqda artıq child (daxildeki) komponent əsas komponentə read adında event atır və əsas komponentdə də read eventi zamanı nə olunacağını göstərən funksiya (newsRead) işə düşərək sadə formada alert göstərilir. Eventlər göndərən zaman lazımlı məlumatı da event daxilində göndərmək mümkündür. Bunu artıq misaldakı koddan da anlamaq olur, çünki komponent daxilinda xəbərin sıra sayını metodun daxilinə ötürmüşəm (<button type=”button” class=”btn btn-outline-primary btn-sm” v-on:click=”readNews(index + 1)”>Oxudum</button>) və onu əsas komponentə göndərmişəm, ancaq onu əsas komponentdə qəbulunu etməmişəm. İndi isə sıra sayının əsas komponentə göndərilməsini kodda azca dəyişiklilər edərək göstərək.

newsRead(num){
alert('Xəbəri oxudunuz! Nömrəsi: ' + num)
}

Kiçik bir dəyişiklik ilə artıq xəbərin sıra sayını görə bilirik. Belə ki, Vue event ilə data göndərdikdə onun handle edən metodun daxilində avtomatik istfadə olunmasını təmin edir. Siz isə event ilə birgə gələn datanı parametrdə qəbul edərək istifadə edə bilirsiniz.

Komponentlər arasında parent və root komponentlərin məlumatına, metodlarına çatmaq üçün sadə bir yol da vardır. Bunun üçün aşağıdakı formada məlumatları almaq mümkündür. Ancaq praktikada bu tipli məlumat istifadəsinin qarışıqlıq yaradacağı və struktursuz hal alacağını düşündüyüm üçün istifadə olunmasını məsləhət görmürəm. Daha ətraflı məlumat üçün isə prosesin necə baş verdiyinə buradan baxa bilərsiniz.

//ancaq bir pillə üstdəki komponent üçün
this.$parent
.someDataOrSomeFunction;
// root komponent üçün
this.$root
.someDataOrSomeFunction;

Bundan başa siz Vue daxilində global eventlər (global event bus) təyin edərək onları parent -> chlid münasibətində deyil də, istənilən komponentdə istifadə edə bilirsiniz. Belə ki, $emit əməliyyatında birinci göstərəcəyimiz event adını adi qaydada istifadə edəcəyik. Həmin event atıldıqda isə istənilən yerdən ona qulaq asa və lazımi əməliyyatları edə bilərik. Öz təcrübəmdə global event bus istifadəsini ayrı-ayrı səhifələrdə sadəcə atılan eventə qulaq asaraq resetləmə işini asanlıqla etmişdim.

//event yeni Vue obyekti yaradılmazdan əvvəl tanıdılır. 
Vue.prototype.$resetComponentData = new Vue();
//Event bus ilə bağlı global event atılır
this.$resetComponentData.$emit('resetData', language.short);
//event dinlənilir və lazımlı əməliyyat yerinə yetirilir.
this.$resetComponentData.$on('resetData', this.someFunctionToRun());

Ancaq global eventlər daimi olaraq dinlənildiyi üçün resurs istifadəsi artır. Bunun qarşısını almaq üçün isə eventi söndürmək lazımdır. Bu kimi bəzi nüansların daha ətraflı izahı üçün buradakı məqaləni oxumağınızı tövsiyyə edirəm.

Göründüyü kimi web interfeys daxilində belə eventlər istifadəsi ilə istədiyimiz məlumatı app-in istənilən hissəsinə göndərə və lazımi dəyişiklikləri asanlıqla edə bilərik. Ancaq bu tipli global event-lərin istifadəsi kiçik sayda tələblər əsasında yerinə yetirilməlidir. Əgər siz bir-biri ilə müntəzəm olaraq məlumat mübadiləsində olan, kompleks bir struktur quracaqsanız global eventlər yerinə Vue üçün xüsusi olaraq hazırlanmış state management library (kitabxanası) olan Vuex-dən istifadə etməlisiniz. Bu zaman sizin app kontrolunuz tamamilə mərkəzləşdirilmiş və istənilən yerdən əl çatılan formada hazırlanmış olur. Vuex əsasən “single source of truth” olaraq tanınmışdır. Belə ki, bütün app üçün global istifadə olunacaq məlumatlar bir mərkəzdə saxlanılaraq, reaktiv olaraq bir-biri ilə bağlı şəkildə avtomatik yenilənərək, istifadəsi yüksək səvəiyyəli bir alətə çevrilir. Vuex barədə ətraflı məlumatları almaq üçün, Vuex üçün hazırlanmış rəsmi səhifədən istifadə edə bilərsiniz.

Beləliklə komponentlər barədə ən sadə istfadə formasını misallar ilə göstərdim. Ümumiyyətlə isə professional iş prosesində komponentlər “.vue” uzantılı ayrı-ayrı fayllarda saxlanılır və import edilən və ya global olaraq təyin edilən komponentlər kimi istifadə olunur. Vue faylları daxilində isə komponent strukturu ideal qurulmuş, script, style və html - 3 ayrı hissədə hazırlanmağa imkan yaradılmışdır. Ancaq, bu zaman .vue fayllarının browserlərin anlaya biləcəyi javascript formasına çevirmək lazım olur. Bunun üçün bir sıra alətlərdən istifadə olunur. Bu tipli alətlərin (webpack, gulp, npm və.s) quraşdırılması isə ayrıca olaraq vaxt aldığıdan hazır paketlərdən istifadə etmək mümkündür. Vue spesifik hazırlanmış Vue cli bu məqsədlə istifadə olunur, terminaldan komandalar əsasında üzərində işləməyə hazır və sadə proyekt formasının yaradılması prosesini avtomatlaşdırır və daha bir çox prosesdə developer-lərə kömək edir. Növbəti yazımda Vue cli ilə indiki yazıda 1 html fayl daxilində hazırladığım komponentlərin necə daha oxunaqlı və strukturlu ola biləcəyini, Vue fayllarından istifadə edərək səhifələrin hazırlanmasının necə sürətli və strukturlaşdırılmış hal alacağını göstərəcəm. Təşəkkürlər :)

Faydalı linklər

  1. Komponentlərin istifadəsi barədə rəsmi səhifə məlumatları — https://vuejs.org/v2/guide/components.html
  2. .vue uzantılı single file components forması — https://vuejs.org/v2/guide/single-file-components.html
  3. Global event istifadəsinin digər bir yolu — https://alligator.io/vuejs/global-event-bus/
  4. Vuex barədə Vue.js rəsmi web saytı — https://vuex.vuejs.org/guide/

--

--