Cordova ile Vue.js Entegrasyonu
Önceki yazımızda Framework7 ile birlikte gelen Template7’den bahsetmiştik. Template7 sadece sayfa render etme işlemlerini gerçekleştirdiği için ve model-view binding yapısı bulunmadığı için form elemanına model bağlama gibi işlemlerde kullanılamaz. Bunun için uygulamamızı Vue.js ile nasıl entegre ederiz onu inceleyeceğiz. Öncelikle Vue.js nedir ona bakalım.
Vue.js nedir?
View
okur gibi telaffuz edilen bu JavaScript kütüphanesi MVVM (Model-View-ViewModel) pattern’ı kullanarak uygulamalar hazırlamamızı sağlar. Diyelim ki elinizde bir HTML form var. Bu forma ilgili model’i basıyorsunuz. Kullanıcı form’daki alanları değiştirdikçe JavaScript tarafındaki modelinizin özellikleri de otomatik olarak değiştirilmiş oluyor. Bu sayede DOM-bağımsız bir uygulama elde etmiş oluyorsunuz ve bakım maliyetleriniz de oldukça azalıyor.
Bu yazıda sizlere v-if
, v-for
kullanımı gibi temel bileşenler nelerdir onlardan bahsetmeyeceğim zira zaten halihazırda vuejs.org‘ta’ 5dk’da bu bilgileri edinebileceğiniz giriş yazısı bulunmakta. Bunun yerine gerçek bir projede Vue.js kullanımına değineceğim.
Framework7 component’ları
Bir Vue.js projesinde yazılan DOM elementlerinin tekrar tekrar kullanılabilmesi için Component (bileşen) sistemi mevcuttur. Bu soyutlama mantığı ile büyük çaplı projelerde HTML çorbasına dönen uygulamalar yerine küçük bileşenlerden oluşan ve tekrar tekrar kullanılabilen yapılar elde etmiş oluruz. Bu component’ları kendimiz oluşturabileceğimiz gibi hazır UI kütüphanelerinden de faydalanabiliriz. Framework7’de de Vue.js ile uyumlu component’lar mevcuttur. Haydi film projemizi Vue.js’e entegre edelim.
Vue.js ve Framework7 Vue plugin’inin yüklenmesi
Projemize Vue.js ve Framework7-Vue kütüphanelerinin yülenmesi için aşağıdaki kodu çalıştırıyoruz.
npm install --prefix ./ vue framework7-vue
Not: --prefix ./
parametresi ile mevcut dizinde node_modules
dizini oluşturularak içerisine ilgili kütüphanelerin eklenmesi sağlanır. Aksi takdirde www dizinin dışındaki node_modules dizinine eklenir ki www dizini içerisinden lite-server’ı açtığımızda bu kütüphanelerimize erişim sağlayamayız.
İlgili kütüphanelerin yüklenmesi tamamlandığında <script> etiketlerimizin bulunduğu bölüme Vue.js ve Framework7-Vue dosyaların yollarını aşağıdaki şekilde olacak halde ekleyelim:
<script type="text/javascript" src="bower_components/framework7/dist/js/framework7.min.js"></script>
<script type="text/javascript" src="node_modules/vue/dist/vue.js"></script>
<script type="text/javascript" src="node_modules/framework7-vue/dist/framework7-vue.min.js""></script>
code;script type="text/javascript" src="js/index.js"></script>
F7 component’larının kullanımı
F7 component’ları kullanarak index.html’i yeniden düzenleyelim:
<body>
<div id="app">
<f7-statusbar></f7-statusbar>
<f7-views>
<f7-view id="main-view" navbar-through :dynamic-navbar="true" main>
<f7-pages>
<f7-page>
<f7-navbar title="Quentin Tarantino Filmleri" back-link="Back" sliding></f7-navbar>
<f7-block-title>Filmler</f7-block-title>
<f7-block v-if="movies.length == 0">
<f7-preloader></f7-preloader>
</f7-block>
<f7-list v-else media-list >
<f7-list-item
v-for="movie in movies"
:media="'<img src='+movie.poster+' style=border-radius:50%;width:44px;height:44px;>'"
:title=movie.show_title
:subtitle=movie.release_year
:link="'/movie_detail/' + movie.show_id + '/'">
</f7-list-item>
</f7-list>
</f7-page>
</f7-pages>
</f7-view>
</f7-views>
</div>
...
Şimdi birkaç açıklama yapalım. <div id="app">
etiketi ile uygulamamızı sarmalamış bulunuyoruz. Bu vesileyle Vue’a bu komutu veriyoruz: Al bak app elemanı, bu eleman bizim uygulamamız. Bak içerisindekiler de bizim component’larımız. Bunları, karşılıkları olan div elemanlarına dönüştürecek şekilde düzenle ve içerisine ilgili modeli bas.
v-if="movies.length == 0"
ifadesi ile movies
isimli film listemiz boş ise içerisinde f7-preloader
elemanını göstererek, listemiz uzak sunucudan gelip dolana dek gösterilecek bir loading screen
ekranı yaratmış oluyoruz.
Eğer listemiz dolu ise filmlerimizi görüntüleyecek f7-list
component’ımızı ekliyoruz ve içerisinde her bir film bilgisi için f7-list-item
elemanımızı ekliyoruz. v-for="movie in movies"
ifadesi ile movies
dizisi içerisindeki her bir elemana movie
adını vererek ilgili özellikleri f7-list-item component’ının özelliklerine bind
ediyoruz.
index.html’i tarayıcımızda açtığımızda içerisinde sadece Filmler yazan beyaz bir sayfa ile karşılaşıyoruz. Beklediğimiz şekilde uygulamamızın çalışmamasının sebebi, oluşturduğumuz <f7-...>
elemanlarının ilgili div elemanları ile değiştirilmemesi ve CSS dosyalarımızda da bu elemanlar hakkında bir stil tanımlaması bulunmamasıdır. Şimdi index.js dosyamızın içeriğini tamamen temizleyelim ve Vue uygulamamızı oluşturalım.
Vue uygulamasının oluşturulması
Framework7 Vue eklentisinin ve Vue uygulamasının etkinleştirilmesi için aşağıdaki kodu index.js dosyamızın içerisine yapıştıralım.
Vue.use(Framework7Vue)
var vm = new Vue({
el: '#app',
framework7: {
root: '#app',
material: true,
},
data: { movies: localStorage.movies ? JSON.parse(localStorage.movies) : [] },
})
Şimdi kodu açıklayacak olursak:
Vue.use(Framework7Vue)
ifadesi ile Framework7 Vue eklentisinin etkinleştirilmesini sağladık.var vm = new Vue({...})
ifadesi ileapp
div’ini baz alan Vue uygulamamızı oluşturduk.data:
ifadesi ile index.html’de kullanılacak movies dizimizin içeriğini oluşturduk. Eğer localStorage’ta dizimiz varsa atayacak yoksa boş dizi olarak döndürecek ve preloader görünecektir.
Şimdi film verilerinin alınmasına bakalım.
JSON verisinin sunucudan çekilmesi ve modele set edilmesi
JSON verisinin sunucudan çekilip modele set edilmesi için Vue nesnesi içerisinde yer alan created
fonksiyonunu kullanabiliriz. created
fonksiyonu, Vue nesnesi oluşturulduktan sonra yapılacak işlemlerin gerçekleştirilmesini sağlar. Biz de bu fonksiyonu kullanarak suncuuya istek gönderme ve gelen JSON verisini modelimize eşleştirme işlemini yapacağız. MVVM yapısını kullandığımız için, modelimiz değiştiğinde otomatik olarak arayüzümüz de güncellenecektir.
var $$ = Dom7;
var vm = new Vue({
el: '#app',
framework7: {
root: '#app',
material: true,
},
data: { movies: localStorage.movies ? JSON.parse(localStorage.movies) : [] },
created: function () {
if (!localStorage.movies){
$$.getJSON('http://netflixroulette.net/api/api.php?director=Quentin%20Tarantino', function(data) {
localStorage.movies = JSON.stringify(data);
vm.movies = data;
});
}
}
})
Not: Vue’ın düzgün çalışabilmesi için meta CSP elemanımız aşağıdaki şekilde olmalıdır:
<meta http-equiv="Content-Security-Policy" content="default-src 'self' 'unsafe-inline' 'unsafe-eval' http://netflixroulette.net/ ws://localhost:3000/browser-sync/socket.io/ data: gap: https://ssl.gstatic.com; media-src *;">
Sayfamız çalışıyor fakat herhangi bir filme tıkladığımızda hiçbir şey gerçekleşmiyor. Bunun için /movie_detail/:show_id/
‘e gidecek routes dizisinin elemanını oluşturmamız gerekiyor.
Framework7-Vue routes dizisinin kullanımı
Vue uygulamasında normalde sayfadan sayfaya yönlendirme işlemleri yer almaz. Bunun için ikincil bir kütüphaneye ihtiyaç duyulması gerekir. Framework7-Vue eklentisinin özelliklerinden biri de tam olarak budur. Framework7-Vue uygulamasında diğer bir sayfaya geçişler için ilgili link parçası Vue nesnesi içerisinde bulunan routes dizini altında belirtilmelidir.
var vm = new Vue({
el: '#app',
framework7: {
root: '#app',
material: true,
routes: [
{
path: '/movie_detail/:show_id/',
component: 'movie_detail'
}
],
},
data: { movies: localStorage.movies ? JSON.parse(localStorage.movies) : [] },
created: function () {
if (!localStorage.movies){
$$.getJSON('http://netflixroulette.net/api/api.php?director=Quentin%20Tarantino', function(data) {
localStorage.movies = JSON.stringify(data);
vm.movies = data;
});
}
}
})
path
parametresinde yer alan :show_id
kısmı linkte yer alan değer ile otomatik olarak değiştirecektir. component
parametresi ise hangi component’ın görüntüleneceğini belirler. movie_detail component’ımız bulunmadığı için öncelikle oluşturmamız gerekiyor
movie_detail component’ının oluşturulması
Aşağıdaki kodu index.js dosyamıza ekleyelim:
Vue.component('movie_detail', {
template: '#movie_detail',
data: function () {
var showId = this.$route.params.show_id;
var movie = JSON.parse(localStorage.movies).filter(function(movie, index) {
return movie.show_id == showId
})[0];
return movie;
}
})
Vue.component fonksiyonu içerisindeki template
elemanı ilgili sayfa yerine hangi DOM elemanının geleceğini belirler. Bu sayede daha sonra index.html içerisinde oluşturacağımız <template id="movie_detail">
elemanı içerisindeki sayfa index sayfamızla yer değiştirecektir. data
fonksiyonu ise template’in hangi veriler ile doldurulacağını belirler. Buradaki ifadede, $route
parametresinden gelen show_id
değeri ile eşleşen movie nesnesi bulunur ve geri döndürülür.
movie_detail template’inin oluşturulması
index.html içerisinde app
elemanımızdan sonra aşağıdaki movie_detail template’ini ekleyelim:
<div id="app">
...
</div>
<template id="movie_detail">
<f7-page>
<f7-navbar :title=show_title back-link="Back" sliding></f7-navbar>
<f7-block-title>Detay</f7-block-title>
<f7-list media-list>
<f7-list-item
:media="'<img src='+poster+' width=80>'"
:title=show_title
:after="'<b>Puan:</b> ' + rating"
:subtitle="'<b>Süre:</b> ' + runtime + '<br>'+
'<b>Yönetmen:</b> ' + director +'<br>'+
'<b>Yönetmen:</b> ' + director +'<br>'+
'<b>Kategori:</b> ' + category +'<br>'+
'<b>Oyuncular:</b> ' + show_cast"
>
</f7-list-item>
</f7-list>
<f7-block>{{summary}}</f7-block>
</f7-page>
</template>
Burada diğer HTML kodlarımızdan ayrılan tek fark {{summary}}
alanı olsa gerek. iki HTML etiketi arasına eleman bağlamak istiyorsak süslü parantezler kullanabiliriz.