Kişisel web tasarım ve kodlama blogu. Web tasarımı ve kodlama araçları ile ilgili bilgiler ve yardımcı dökümanlar.

Kod yazmak sanattır...

gokhankr.com

Blogger tarafından desteklenmektedir.

Getting $_REQUEST (like POST and GET) as JSON with PHP


 

JSON is the most practical and fastest way to get data. PHP provides encode and decode feature for JSON object. However, you cannot directly fetch data as application-json.

That's why you can't fetch data with the JSON standard over $_GET and $_POST. We will use the input that PHP provides for I/O to get the data.


file_get_contents('php://input')

Now let's expand this a little more and assume that the incoming data is JSON.


json_decode(file_get_contents('php://input'), true);

The above process will take the data when we receive JSON data and convert it to PHP Array, and if the incoming data does not come as JSON, it will return null. So we can now try this process on a Router.


function getJSON()
{
    $jsonData = json_decode(file_get_contents('php://input'), true);
    return $jsonData ?? [];
}

Now you can get the data as JSON via getJSON() just as we get the data via $_POST and $_GET.

If you want, we can also define and use the data globally as we receive it via $_POST or $_GET. For this:


// index.php
$jsonData = json_decode(file_get_contents('php://input'), true);
$GLOBALS['_JSON'] = $jsonData;

//user.php
if (isset($_JSON['userLogin'])) {
    /* ... */
}

In this way, you can define $_GLOBALS on your requested page and use it like $_POST on any page you want. That's all I'm going to tell you in detail about "Getting JSON requests with PHP". Thanks.

PHP ile JSON olarak $_REQUEST(POST ve GET gibi) alma işlemi


JSON veri almanın en pratik ve hızlı yoludur. PHP, JSON nesnesi için encode ve decode özelliği sunar. Ancak veriyi application-json olarak doğrudan alma işlemi yapamazsınız. 

Bu yüzden $_GET ve $_POST üzerinden JSON standardı ile bir veri alımı yapamazsınız. Veriyi almak için PHP'nin I/O için sağlamış olduğu girişi kullanacağız.


file_get_contents('php://input')

Şimdi bunu biraz daha genişletelim ve gelen verinin JSON olduğunu varsayalım.


json_decode(file_get_contents('php://input'), true);

Yukarıdaki işlem bize JSON verisi geldiğinde veriyi alıp PHP Array'a çevirecek ve eğer gelen veri JSON olarak gelmezse de null olarak dönecek. Böylece bu işlemi artık bir Router üzerinde deneyebiliriz.


function getJSON()
{
    $jsonData = json_decode(file_get_contents('php://input'), true);
    return $jsonData ?? [];
}

Şimdi $_POST ve $_GET üzerinden veriyi aldığımız gibi getJSON() üzerinden de alma işlemini JSON olarak gerçekleştirebilirsiniz.

Eğer isterseniz veriyi $_POST veya $_GET üzerinden aldığımız gibi global olarak tanımlayıp kullanabiliriz de. Bunun için:


// index.php
$jsonData = json_decode(file_get_contents('php://input'), true);
$GLOBALS['_JSON'] = $jsonData;

//user.php
if (isset($_JSON['kullaniciGirisi'])) {
    /* ... */
}

Bu şekilde istek atılan sayfanızda $_GLOBALS tanımlayarak istediğiniz herhangi bir sayfada $_POST gibi de kullanabilirsiniz. "PHP ile JSON istek alma işlemi" ile ilgili detaylı anlatacaklarım bu kadardı. Teşekkürler.

Javascript "Computed Propery Name"


Javascript Computed Property Name

Computed Property Name

ES6’nın "Computed Propery Name" özelliği, bir nesnede bir özellik adı olarak hesaplanacak bir ifadeye (bir değişken veya işlev çağrısı gibi tek bir değerle sonuçlanan bir kod parçası) sahip olmanızı sağlar.

Örnek Kodlama

Örneğin, iki bağımsız değişken (anahtar, değer) alan ve bu bağımsız değişkenleri kullanarak nesne döndüren bir fonksiyon oluşturmak istediğinizi varsayalım. Nesnedeki özellik adı bir değişken (anahtar) olduğundan, önce nesneyi oluşturmanız, ardından bu özelliği değere atamak için köşeli ayraç gösterimi kullanmanız gerekirdi.


function nesneYap (key, value) {
  let obj = {}
  obj[key] = value
  return obj
}

nesneYap('name', 'Kaan') // { name: 'Kaan' }

Ama artık Computed Propery Name ile bir nesneyi önce oluşturmak zorunda kalmadan, doğrudan nesne üzerinde bir özellik olarak atamak için nesne değişmez gösterimini kullanabilirsiniz. Yani yukarıdaki kod artık bu şekilde yeniden yazılabilir.


function nesneYap (key, value) {
  return {
    [key]: value
  }
}

nesneYap('name', 'Kaan') // { name: 'Kaan' }

Anahtar, köşeli parantez [ ] içine alındığı sürece herhangi bir şey olabilir.

Vuex Store - Mutations'da Sabitler ve Senkronize


Mutasyonlar İçin Sabitleri Kullanmak

Çeşitli Flux uygulamalarında mutasyon türleri için sabitlerin kullanılması yaygın olarak görülen bir durumdur. Bu, kodun linter gibi araçlardan yararlanmasını sağlar ve tüm sabitleri tek bir dosyaya koymak, beraber çalıştığınız geliştiricilerin tüm uygulamada hangi mutasyonların mümkün olduğunu bir bakışta görmelerini sağlar:


// mutasyon-listesi.js
export const MUTASYONLAR = 'MUTASYONLAR'


// store.js
import Vuex from 'vuex'
import { BIR_MUTASYON } from './mutasyon-listesi'

const store = new Vuex.Store({
  state: { ... },
  mutations: {
    // Sabit'i "ES2015 Computed Property Name" özelliği ile
    // bir fonksiyon adı olarak kullanabilirsiniz
    [BIR_MUTASYON] (state) {
      // bir mutasyon gerçekleştir
    }
  }
})

Sabitlerin kullanılıp kullanılmaması büyük ölçüde bir tercihtir ve birçok geliştiricinin olduğu büyük projelerde yardımcı olabilir, ancak beğenmezseniz tamamen isteğe bağlıdır.

Mutasyonlar Senkron Olarak Çalışmalıdır

Hatırlanması gereken önemli bir kural, mutasyonların eşzamanlı olması gerektiğidir. Neden mi ? Aşağıdaki örneği düşünün:


mutations: {
  birMutasyon (state) {
    api.callAsyncMethod(() => {
      state.miktar++
    })
  }
}

Şimdi uygulamada hata ayıkladığımızı ve devtool üzerinden Vue'nun Mutations loglarına baktığımızı düşünün. Kaydedilen her mutasyon için, devtool, "önce" ve "sonra" olarak durumları anlık görüntü biçiminde yakalama ihtiyacı duyacak. Bu yüzden, yukarıdaki örnekte olduğu gibi mutasyonun içindeki eşzamansız bir geri çağırma fonksiyonu bunu imkansız kılar. Mutasyon işlendiğinde callback o anda anlık olarak çağrılmayacağı için devtool'un callback'in ne zaman çağrılacağını bilmesinin bir yolu yoktur. Dolayısıyla callback ile gerçekleştirilen herhangi bir mutasyon işlemi takip edilemez!

Mutasyonlar ile ilgili anlatım bilgileri bu kadardı. Bundan sonraki süreçte Actions'lara değineceğiz. Teşekkürler.

Bootstrap - 12 yerine 24'lü Izgara Yapısı


Son yaptığım projemi Figma'da tasarımladıktan sonra HTML üzerine dökerken çok enteresan bir durumla karşılaştım. Yatay eksende 3 bölüme ayırdığım bir Section içerisinde sol ve sağ bloklar içerisinde tasarımlamış olduğum kartlarım ile orta bölüme de dikey olarak attığım ufak bir çizgi Bootstrap'ın grid yapısına uymadı. 

İçeriği orantılı bir şekilde ortalamam için sağa ve sola .col-5, .col-5 i ve orta bölüme de kalan .col-2 yi vermem gerekiyordu. Yani örnekteki gibi:

 

Tahmin edebileceğiniz üzere bir tane çizgi için orta bölüm aşırı geniş durdu ve tasarımın görünümünde biçimsizliğe neden oldu:

Dolayısıyla CSS üzerinden bir çözüm arayışına giriştim.

Çözümüm

Çok ta uğraştırıcı bir çözümü yoktu tabi. Sağ ve sol karta width:108%; verdim ve sağ tarafa da margin-left:-8%; verip mobilde de bunu sıfırlayınca sütunlar üzerinde herhangi bir değişiklik yapmadan meseleyi çözmüş oldum. Ancak tasarım düzeninde biraz oynama yapmak durumunda kaldım.

Sonuç

Peki bu ızgara sisteminin hep klasik web sayfaları ortaya koymak olduğunu gören bir tek ben miyim ? Hayır. Bu sistemin tasarımı sabit bir ızgara sistemine bağımlı kıldığını söyleyen çok insan var. Ancak nasılsa bu durum halen Bootstrap 5 üzerinde de devam etmekte. Aslında benim rahatsız olduğum tek mesele bu da değil. Bootstrap Container boyutu genişliği de var. Nedendir bilmem ama bir ekran neden 1140px içerisinde sabitlenmek zorunda ? 

Farklı düşünenler var mıdır bilemem ama, Bootstrap Container içerisine bulunan bir web sitesini en az 22" bir LCD üzerine çektiğim zaman kısa tabiriyle cücük gibi duruyor. En azından son zamanların Flex Layout düzeni ile kodlanan Bulma CSS bu konuda biraz daha elini genişletmiş ve Container boyutunu 1152px'e çekmiş. Deneme yaptığımda tabiki de Bootstrap'a göre daha ferah bir görünüm sağlıyor. 12px ne kadar etkili olabilir düşüncesinde olabilirsiniz ama evet gerçekten görünüme çok etki ediyor kesinlikle deneyin. Ayrıca 1488px ve üzeri için de 1344px lik bir Container genişliği belirlemiş.

Bulma İçin: https://bulma.io/

Yazımın sonuna geldiğimde ızgara konusuda artık bireysel bir çözüm üretme araşıyışına giriştim ve kendim için 24'lük ızgara mantığı ile yeni bir yapı ürettim. Üstelik bunu varsayılan Bootstrap class'larının üzerine bastırarak uyguladım. Şu anki aşamada ilk olarak kendi blog sayfamda kullanıyorum ancak ufak denemelerim sonucunda biraz daha bunu genişleterek 32 veya 54'e çıkarabilirim diye düşünüyorum. Ayrıca blog sayfamın Content alanının genişliğini de bir nebze olsun genişleterek şimdiden kendi ızgaram ile kendi görünümümü özelleştirebildim. 

24'lük Izgara CSS Kodu

Uygulamış olduğum 24 lük grid CSS'ini minify olarak alabilirsiniz. İlerde daha detaylı olarak Github üzerinden yayınlamayı düşünüyorum.

*{box-sizing:border-box}body{margin:0}[class^=col]{flex-shrink:0;padding-left:17px;padding-right:17px}.col-1{flex-basis:4.166666667%;max-width:4.166666667%}.col-2{flex-basis:8.333333334%;max-width:8.333333334%}.col-3{flex-basis:12.500000001%;max-width:12.500000001%}.col-4{flex-basis:16.666666668%;max-width:16.666666668%}.col-5{flex-basis:20.833333335%;max-width:20.833333335%}.col-6{flex-basis:25%;max-width:25%}.col-7{flex-basis:29.166666667%;max-width:29.166666667%}.col-8{flex-basis:33.333333334%;max-width:33.333333334%}.col-9{flex-basis:37.500000001%;max-width:37.500000001%}.col-10{flex-basis:41.666666668%;max-width:41.666666668%}.col-11{flex-basis:45.833333335%;max-width:45.833333335%}.col-12{flex-basis:50%;max-width:50%}.col-13{flex-basis:54.166666667%;max-width:54.166666667%}.col-14{flex-basis:58.333333334%;max-width:58.333333334%}.col-15{flex-basis:62.500000001%;max-width:62.500000001%}.col-16{flex-basis:66.666666668%;max-width:66.666666668%}.col-17{flex-basis:70.833333335%;max-width:70.833333335%}.col-18{flex-basis:75%;max-width:75%}.col-19{flex-basis:79.166666667%;max-width:79.166666667%}.col-20{flex-basis:83.333333334%;max-width:83.333333334%}.col-21{flex-basis:87.500000001%;max-width:87.500000001%}.col-22{flex-basis:91.666666668%;max-width:91.666666668%}.col-23{flex-basis:95.833333335%;max-width:95.833333335%}.col-24{flex-basis:100%;max-width:100%}.container{margin-left:auto;margin-right:auto}.row{display:flex;flex-wrap:wrap}@media screen and (min-width:768px){.container{max-width:720px}.col-sm-1{flex-basis:4.166666667%;max-width:4.166666667%}.col-sm-2{flex-basis:8.333333334%;max-width:8.333333334%}.col-sm-3{flex-basis:12.500000001%;max-width:12.500000001%}.col-sm-4{flex-basis:16.666666668%;max-width:16.666666668%}.col-sm-5{flex-basis:20.833333335%;max-width:20.833333335%}.col-sm-6{flex-basis:25%;max-width:25%}.col-sm-7{flex-basis:29.166666667%;max-width:29.166666667%}.col-sm-8{flex-basis:33.333333334%;max-width:33.333333334%}.col-sm-9{flex-basis:37.500000001%;max-width:37.500000001%}.col-sm-10{flex-basis:41.666666668%;max-width:41.666666668%}.col-sm-11{flex-basis:45.833333335%;max-width:45.833333335%}.col-sm-12{flex-basis:50%;max-width:50%}.col-sm-13{flex-basis:54.166666667%;max-width:54.166666667%}.col-sm-14{flex-basis:58.333333334%;max-width:58.333333334%}.col-sm-15{flex-basis:62.500000001%;max-width:62.500000001%}.col-sm-16{flex-basis:66.666666668%;max-width:66.666666668%}.col-sm-17{flex-basis:70.833333335%;max-width:70.833333335%}.col-sm-18{flex-basis:75%;max-width:75%}.col-sm-19{flex-basis:79.166666667%;max-width:79.166666667%}.col-sm-20{flex-basis:83.333333334%;max-width:83.333333334%}.col-sm-21{flex-basis:87.500000001%;max-width:87.500000001%}.col-sm-22{flex-basis:91.666666668%;max-width:91.666666668%}.col-sm-23{flex-basis:95.833333335%;max-width:95.833333335%}.col-sm-24{flex-basis:100%;max-width:100%}}@media screen and (min-width:1024px){.container{max-width:960px}.col-md-1{flex-basis:4.166666667%;max-width:4.166666667%}.col-md-2{flex-basis:8.333333334%;max-width:8.333333334%}.col-md-3{flex-basis:12.500000001%;max-width:12.500000001%}.col-md-4{flex-basis:16.666666668%;max-width:16.666666668%}.col-md-5{flex-basis:20.833333335%;max-width:20.833333335%}.col-md-6{flex-basis:25%;max-width:25%}.col-md-7{flex-basis:29.166666667%;max-width:29.166666667%}.col-md-8{flex-basis:33.333333334%;max-width:33.333333334%}.col-md-9{flex-basis:37.500000001%;max-width:37.500000001%}.col-md-10{flex-basis:41.666666668%;max-width:41.666666668%}.col-md-11{flex-basis:45.833333335%;max-width:45.833333335%}.col-md-12{flex-basis:50%;max-width:50%}.col-md-13{flex-basis:54.166666667%;max-width:54.166666667%}.col-md-14{flex-basis:58.333333334%;max-width:58.333333334%}.col-md-15{flex-basis:62.500000001%;max-width:62.500000001%}.col-md-16{flex-basis:66.666666668%;max-width:66.666666668%}.col-md-17{flex-basis:70.833333335%;max-width:70.833333335%}.col-md-18{flex-basis:75%;max-width:75%}.col-md-19{flex-basis:79.166666667%;max-width:79.166666667%}.col-md-20{flex-basis:83.333333334%;max-width:83.333333334%}.col-md-21{flex-basis:87.500000001%;max-width:87.500000001%}.col-md-22{flex-basis:91.666666668%;max-width:91.666666668%}.col-md-23{flex-basis:95.833333335%;max-width:95.833333335%}.col-md-24{flex-basis:100%;max-width:100%}}@media screen and (min-width:1216px){.container{max-width:1152px}.col-lg-1{flex-basis:4.166666667%;max-width:4.166666667%}.col-lg-2{flex-basis:8.333333334%;max-width:8.333333334%}.col-lg-3{flex-basis:12.500000001%;max-width:12.500000001%}.col-lg-4{flex-basis:16.666666668%;max-width:16.666666668%}.col-lg-5{flex-basis:20.833333335%;max-width:20.833333335%}.col-lg-6{flex-basis:25%;max-width:25%}.col-lg-7{flex-basis:29.166666667%;max-width:29.166666667%}.col-lg-8{flex-basis:33.333333334%;max-width:33.333333334%}.col-lg-9{flex-basis:37.500000001%;max-width:37.500000001%}.col-lg-10{flex-basis:41.666666668%;max-width:41.666666668%}.col-lg-11{flex-basis:45.833333335%;max-width:45.833333335%}.col-lg-12{flex-basis:50%;max-width:50%}.col-lg-13{flex-basis:54.166666667%;max-width:54.166666667%}.col-lg-14{flex-basis:58.333333334%;max-width:58.333333334%}.col-lg-15{flex-basis:62.500000001%;max-width:62.500000001%}.col-lg-16{flex-basis:66.666666668%;max-width:66.666666668%}.col-lg-17{flex-basis:70.833333335%;max-width:70.833333335%}.col-lg-18{flex-basis:75%;max-width:75%}.col-lg-19{flex-basis:79.166666667%;max-width:79.166666667%}.col-lg-20{flex-basis:83.333333334%;max-width:83.333333334%}.col-lg-21{flex-basis:87.500000001%;max-width:87.500000001%}.col-lg-22{flex-basis:91.666666668%;max-width:91.666666668%}.col-lg-23{flex-basis:95.833333335%;max-width:95.833333335%}.col-lg-24{flex-basis:100%;max-width:100%}}@media screen and (min-width:1408px){.container{max-width:1344px}.col-xl-1{flex-basis:4.166666667%;max-width:4.166666667%}.col-xl-2{flex-basis:8.333333334%;max-width:8.333333334%}.col-xl-3{flex-basis:12.500000001%;max-width:12.500000001%}.col-xl-4{flex-basis:16.666666668%;max-width:16.666666668%}.col-xl-5{flex-basis:20.833333335%;max-width:20.833333335%}.col-xl-6{flex-basis:25%;max-width:25%}.col-xl-7{flex-basis:29.166666667%;max-width:29.166666667%}.col-xl-8{flex-basis:33.333333334%;max-width:33.333333334%}.col-xl-9{flex-basis:37.500000001%;max-width:37.500000001%}.col-xl-10{flex-basis:41.666666668%;max-width:41.666666668%}.col-xl-11{flex-basis:45.833333335%;max-width:45.833333335%}.col-xl-12{flex-basis:50%;max-width:50%}.col-xl-13{flex-basis:54.166666667%;max-width:54.166666667%}.col-xl-14{flex-basis:58.333333334%;max-width:58.333333334%}.col-xl-15{flex-basis:62.500000001%;max-width:62.500000001%}.col-xl-16{flex-basis:66.666666668%;max-width:66.666666668%}.col-xl-17{flex-basis:70.833333335%;max-width:70.833333335%}.col-xl-18{flex-basis:75%;max-width:75%}.col-xl-19{flex-basis:79.166666667%;max-width:79.166666667%}.col-xl-20{flex-basis:83.333333334%;max-width:83.333333334%}.col-xl-21{flex-basis:87.500000001%;max-width:87.500000001%}.col-xl-22{flex-basis:91.666666668%;max-width:91.666666668%}.col-xl-23{flex-basis:95.833333335%;max-width:95.833333335%}.col-xl-24{flex-basis:100%;max-width:100%}}

İlerleyen zamanlarda nasıl düşünürüm bilmiyorum ancak muhtemelen bu gidişle bu yapının çok daha dışına çıkabilirim diye düşünüyorum. Zaman ayırdığınız için teşekkürler.

Vuex Store - Mutations ve Vue.js Reaktivitesi


Mutasyonların Vue'nun Reaktivite Kurallarına Uyması

Bir Vuex mağazasının state'i Vue tarafından reaktif hale getirildiğinden, state üzerinde değişiklik yaptığınızda durumu gözlemleyen Vue bileşenleri otomatik olarak güncellenecektir. Bu aynı zamanda Vuex mutasyonlarının düz Vue ile çalışırken aynı reaktivite uyarılarına tabi olduğu anlamına gelir. 

Yani CLI üzerinden değil de, web üzerinde kullanmış olduğunuz Vue örneği ile Store üzerinde commit işlemi yapacağınız zaman karşınıza Vue'nun reaktivitesi sorunu çıkacaktır. Değişim yaptığınız veri ile değişen verileriniz birbirleri ile reaktif bir şekilde çalışacağından iki veri arasında bir bağ kurulmuş olacak ve siz store üzerinde değişiklik yapmadığınız halde değişim yapmış olduğunuz veri üzerinde değişiklik yaptığınızda Store üzerindeki veri de bundan etkilenecektir. Aşağıdaki örnekleri inceleyelim.


state: {
    user: {
      id: 1
    }
},

Yukarıdaki user'a bir mutation uygulayalım.


mutations: {
    setUserName (state, userData) {
        // userData = {
        //     id: 2,
        //     name: Ali
        //}
        state.user = userData;
}

Yukarıda gördüğünüz gibi "userData"yı direk "user"a mutate ettik. Şimdi "userData" yı bir Vue bileşeni içerisinde "userData.name = Veli" yaparsak, Store üzerindeki "user.name" de değişmiş olacak. Bu yüzden aşağıdaki yöntemler ile bu sorunu aşmanız gerekir.

state: {
    user: {
      id: 1
    }
  },
  getters: {
    getUserId: state => state.user.id,
    getUserName: state => state.user.name
  },
  mutations: {
    setUserName (state, name) {
      // İlk çözüm:
      // user üzerinde değeri önceden belirtin örn: user.name = null ve şöyle görünmeli
      // user: {
      //     id: 2,
      //     name: null
      // }
      // Böylelikle "name" daha önceden belirtildiği için Vue içerisindeki değişiklik
      // burayı tetiklemeyecek
      state.user.name = name

      // İkinci çözüm:
      // Object assign methodu ile her iki verinin de referansını sıfırlayın
      // Object.assign({}, state.user, { name })
      state.user = { ...state.user, name }

      // Üçüncü çözüm:
      // Vue'nun kendi içerisindeki Vue.set() fonksiyonunu kullanın.
      // Aynı sonucu verecektir.
      Vue.set(state.user, 'name', name)
}

Vue'nun reaktivitesinin Mutations üzerindeki etkisini ve bunun bir sorunken üç farklı yol ile çözümüne değindik. Tekrar hatırlatmakta fayda var bu sorun tam olarak düz Vue kullanırken karşılaşabileceğiniz bir durum. CLI üzerinde böyle bir sorun yaşamayacaksınız. Bir sonraki yazımda Mutatitonsların sabitler ile kullanımına değineceğiz. Teşekkürler.

Vuex Store - Mutations Kavramı ve Anlatımı


Bir Vuex mağazasında State üzerindeki veriyi değiştirmenin tek yolu bir mutasyon gerçekleştirmektir. Mutasyon içerisinde bir fonksiyon oluşturduğumuzda State'i ilk argüman olarak alır:


const store = new Vuex.Store({
  state: {
    miktar: 1
  },
  mutations: {
    artir (state) {
      // State üzerindeki "miktar"ı güncelle
      state.miktar++
    }
  }
})

Bir mutasyonu doğrudan nesne adı ile çağıramazsınız. Bunun için store.commit("") fonksiyonunu çağırmanız gerekir.


store.commit('miktar')

Veriyi Commit Etmek

Store.commit'e payload(güncelleyeceğiniz veri) olarak adlandırılan ek bir bağımsız değişken iletebilirsiniz:


mutations: {
  increment (state, payload) {
    state.miktar += payload.sayi
  }
}

Payload güncel olarak değişim yapacağınız data'dır.


store.commit('artir', {
  sayi: 10
})

Nesne Tarzında Commit Yapmak

Bir mutasyonu gerçekleştirmenin alternatif bir yolu, type özelliği olan bir nesneyi doğrudan kullanmaktır:


store.commit({
  type: 'artir',
  sayi: 10
})

Yukarıda commit() içerisine sadece bir nesne ekledik ve daha önce birinci parametrede belirttiğimiz mutasyon adını bu sefer type değeri ile ekledik. Vuex de adı type üzerinden aldı. Bu durum mutasyonun daha önceki yapısı üzerinde de bir değişiklik yapmanızı gerektirmez. Yani aynı işlemi yapmış olduk.

Mutasyonların nasıl işlediğine ve kullanıldığına değindik. Mutasyon kullanımını üç farklı makalede ele alacağız. Bir sonrakinde Vue'nun reaktivite sisteminin Mutasyonlar üzerindeki etkisini inceleyeceğiz.

Vuex Store - Getters Kavramı ve Anlatımı


Bazen, örneğin bir öğe listesini filtrelemek ve onları saymak gibi, duruma göre çıktısını istediğiniz bir veriyi ayrıca hesaplamamız gerekebilir.


computed: {
  gorevListesi() {
    return this.$store.state.gorevler.filter(
      (gorev) => gorev.bitisDurumu === true
    ).length;
  },
}

Birden fazla alanla bunu kullanmak istiyorsak, ya bu işlevi çoğaltmamız lazım ya da ayrı bir dosyaya ekleyip her ihtiyacımız olduğunda bu dosyayı ilgili component içerisinde import etmemiz gerekir. İki seçenek te düzenli kodlama mantığından biraz uzak.

Vuex Store bu işlevleri Getters üzerinden tanımlamanıza olanak tanır. Bu işlevleri Vue örneğindeki computed'lar üzerinde tanımladığımız işlevler gibi de düşünebilirsiniz. Computed'lar da Getters'lar gibi bağımlılıklarına göre önbelleğe alınır ve sadece belirli bağımlılıklar değiştirildiğinde yeniden işlevsel olarak hesaplamaya dahil edilir.  

Getters Tanımlamak

Bir Getters tanımlamak istediğinizde, state'i ilk parametresinden alabilirsiniz.


const store = new Vuex.Store({
  state: {
    gorevler: [
      { id: 1, baslik: '...', bitisDurumu: true },
      { id: 2, baslik: '...', bitisDurumu: false }
    ]
  },
  getters: {
    tamamlanmisGorevler: state => {
      return state.gorevler.filter(gorev => gorev.bitisDurumu)
    }
  }
})

Getters'a State Gibi Erişmek

Bir Getters'a "store.getters" üzerinden erişebilirsiniz ve direk nesne öğesi olarak alabilirsiniz.


store.getters.tamamlanmisGorevler

Ayrıca Getters içerisine diğer Getters işlevlerini de alabilirsiniz. İkinci değer olarak da Getters'lara erişebilirsiniz.


getters: {
  // ...
  bitmisGorevlerinSayisi: (state, getters) => {
    return getters.tamamlanmisGorevler.length
  }
}

Daha önce tanımlamış olduğumuz "tamamlanmisGorevler" adlı getters'ı yeni bir getters olan "bitmisGorevlerinSayisi" içerisinde kullandık.

Getters'ın Component İçerisinde Kullanımı

Artık onu herhangi bir component içerisinde kullanabiliriz.


computed: {
  bitmisGorevler () {
    return this.$store.getters.tamamlanmisGorevler
  }
}

Not: Getters'ların Vue'nun reaktivite sistemine dahil olduğunu unutmayın.

Method'a Farklı Bir Erişme Biçimi

Getters'lara bir fonksiyon üzerinden argüman da iletebilirsiniz. Bu işlem mağazada bir diziyi sorgulamak istediğinizde kullanışlıdır.


getters: {
  // ...
  gorevGetir: (state) => (id) => {
    return state.gorevler.find(gorev => gorev.id === id)
  }
}


store.getters.gorevGetir(2) // -> { id: 2, baslik: '...', tamamlanmis: false }

Yukarıdaki işlem ile "id" üzerinden herhangi bir gorev'i alabiliyoruz.

Getters'lar ile ilgili makalenin sonuna geldik. Bir sonraki yazımda görüşmek üzere.

.map dosyaları nedir, ne işe yarar ?


Web sayfanıza bir Javascript kütüphanesi eklediğinizde aşağıdaki gibi bir uyarıyı gözlemleyebilirsiniz. Çünkü sizden .min.x.js eklemesi yaptığınızda sonu .map uzantılı bir dosya isteyecektir.

Web üzerinde .map dosyaları Javascript, CSS ve Typescript dosyaları için kullanılmaktadır. Bu dosyalar kaynak haritaları olarak adlandırılırlar. Peki ne amaçla kullanılmaktadırlar.

Angular.js gibi bir kütüphane dosyasını minify ettiğinizde, elinizdeki düzenli kodu verip yerine okunamayacak biçimde yani sözdeyimi çirkin hale getirilmiş boşluklarından arındırılmış biçimini alırsınız. Uygulamanız üretim modunda yani projenin sunum halinde bir hata oluştuğunda kaynak haritası minify edilmiş dosyanızı otomatik olarak alacak ve kodun orjinal sürümünü görmenize izin verecektir. Bunu görmek için bir örnek uygulamakta fayda var.

.map Dosyasını Kullanmak

Örnek vermek gerekirse sitemizde Bootstrap kullanıyor olalım. Bootstrap içerisinde bootstrap.min.js ve bootstrap.min.js.map dosyalarını dist/js içerisinden site dizinimize atalım. İndirdiğiniz arşiv içerisindeki js/src altındaki dosyaları site dizininizde bir /maps klasörü oluşturun ve içerisine atın. Ardından .map dosyanızı editörde açın ve içerisindeki "../../js/src/" kaynak yollarının hepsini oluşturduğunuz /maps dizini yolu ile değiştirin.

Şimdi bootstrap.min.js dosyamızı <script> etiketi ile çağıralım. Siteyi açtığınızda Console altında .map dosyası için bir hata ile karşılaşmayacaksınız çünkü tarayıcı .min.js ile aynı dizinde olan .map dosyasını otomatik olarak tespit edecektir.

Ardından Geliştirici Araçlarının,  Sources panelinden bootstrap.min.js dosyasını bulup açtığınızda dosya içerisinde şöyle bir uyarı ile karşılaşacaksınız.

"Source Map detected". Yani .map dosyası tespit edildi. Bu uyarıyı gördüğünüze göre şimdi Ctrl+P ile dosya denetleyicisi penceresini açın ve oradan bir Bootstrap dosyası olan modal.js dosyasını açın. Dosyayı açtığınızda artık debug yapmak istediğinizde, buradan sorunun tam olarak nerede olduğunu dosyanın orjinali üzerinden tespit edebileceksiniz.

Aynı durum CSS için de geçerlidir. SASS ve SCSS dosyalarımızın kaynak haritasını da çıkartarak bu işlemi uygulayabiliriz.

Bir geliştirici bu işlemi nasıl uygulayabilir ?

Bir üretim uygulamasında hata ayıklamak için kullanırsınız. Geliştirme modunda, Angular'ın tam sürümünü kullanabilirsiniz. Üretimde, minify edilmiş sürümü kullanırsınız.

Kaynak haritası kullanmak zorunda mıyım ?

Üretim kodunda daha kolay hata ayıklamayı önemsiyorsanız, evet, yapmalısınız.

Map dosyası ile ilgili açıklamalar bu kadardı, bir sonraki makalede görüşmek üzere.

Vuex Store - State Kavramı ve Anlatımı


Daha önce Vuex Store'a bir giriş yapmış ve bir Vuex Store örneğini incelemiştik. Oradaki dört bölümden kısaca bahsetmiştik. Bunlar State, Getters, Mutations ve Actions'tı.

State Management Pattern

Vuex bir State Management Pattern yani bunu çevirmeyeceğim ama şöyle söyleyeyim Veri yönetimi kütüphanesidir. Bir devlet düşünün çatısı altında her şey yönetilir, işte State burada devlet konumundadır ve aynı zamanda hem uygulama içerisindeki veriyi hem de kendi kendini yöneten anlamına gelmektedir.

State kavramını anladığımıza göre Vuex'in işlevine geçelim. Vuex tam olarak veriyi veya verileri istediğiniz bir biçimde merkezi bir yapı içerisinde yönetmenizi sağlar. Yani kısaca tüm uygulama içerisinde bir merkezi depo görevi görür. State kavramını yukarıda açıklamıştım. Şimdi tam olarak çalışma sisteminden bahsedeceğim.


import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

const store = new Vuex.Store({
  state: {
    isim: "Gokhan"
  },
  mutations: {
    ismiDegistir (state, data) {
      state.isim = data
    }
  }
})

Yukarıdaki bizim Vuex örneğimiz. Şimdi herhangi bir component içerisinde State'deki isim değerini alalım.

State Verisine Erişim


computed: {
  isim() {
    return this.$store.state.isim
  }    
}

Bildiğiniz gibi computed özelliği Vue'nun reaktivitesine dahil olmadığı için tekrar tekrar hesaplamaya dahil edilmiyor. Store içerisinden veriyi almak için de computed kullanılıyor. Çünkü set/get mantığıyla değil sadece get mantığı ile çalışıyor. Artık "isim" adında bir datamız var ve istediğimiz şekilde kullanabiliriz.

State Verisi Üzerine Değişim Uygulama

Önceki yayında mutationsların state üzerindeki veriyi değiştirmek yani mutasyona uğratmak için kullanıldığından bahsetmiştim. "ismiDegistir" adında bir mutations'ımız var. Şimdi state.isim'e yeni bir değer atayalım. Bunun için Vue örneği içerisinde daima this.$store.commit() fonksiyonunu kullanacağız.


methods: {
  yeniIsim(isim) {
    this.$store.commit('ismiDegistir', isim);
  }
}

Fonksiyon adları karışmasın diye method adını "yeniIsim" olarak kullandım. this.yeniIsim("Adınız") biçiminde artık Store üzerindeki veriyi değiştirebilirsiniz.

 

State üzerindeki verinin nasıl alındığını ve mutasyona uğratıldığını anlattım. Bir sonraki yazımda da Getters özelliğine geçeceğiz. 

Polyfill nedir, ne için kullanılır ?


Web platformu üzerindeki ilerleyen zamanlarınızda karşınıza Polyfill adında bir kavram çıktı. Nedir bu Polyfill ve ne demektir ?

PolyFill Kavramı

Polyfill, kısaca tanımlamak gerekirse yazmış olduğunuz kodlarınızın eski tarayıcılarda da çalışmasını sağlamak için ayrıca üretmiş olduğunuz destekleyici yazılımlara denir.

Tüm dünyada kullanılan birçok farklı tarayıcı ve tarayıcı sürümü vardır, her biri diğerlerinden biraz farklı özelliklere sahiptir. Bu, tarayıcılar için geliştirmeyi zor bir görev haline getirebilir. Popüler tarayıcıların en son sürümleri, eski tarayıcıların yapamadığı birçok şeyi yapabilir ancak yine de eski tarayıcıları desteklemeniz gerekebilir. Polyfill'ler, eksik özellikleri çoklu dolgularla yeniden oluşturmaya çalışarak farklı tarayıcıları desteklemeyi kolaylaştırır: Bunları destekleyen tarayıcılarda ve desteklemeyen tarayıcılarda en yeni ve en iyi özelliklerden yararlanabilirsiniz.

Mesela güncel tarayıcıların kullandığı Javascript Promise'ı düşünün.


Yukarıdaki caniuse.com/promises çıktısına baktığınız zaman Pormise'ların IE 6'dan 11'e kadar desteklemediği görürsünüz. Promise için ES6(Ecma Script 6) kullanmanız gerekmekte. İşte tam olarak burada Polyfill'ler devreye girmektedir. 
Ya sizin bunu kendinizin ek olarak bir kütüphane hazırlamanız ya da Promise örneği gibi bilinen bir özellik ise dışarıdan bir kütüphane ile bunu sağlamanız gerekir. Ancak eğer eski tarayıcılarla ilgili böyle bir sorununuz varsa.

Tabi ki bu durum yalnızca Javascript tarafında karşılaşılan bir durum değil. Ne demiştik, güncel tarayıcılar ve güncel olmayan tarayıcılar arasındaki farklılık. Bu yüzden aynı durum HTML ve CSS için de geçerli. 

Neler Kullanabiliriz ?

Aşağıda Polyfill için yardımcı olabilecek araçların bir listesi oluşturulmuş. Bu liste Modernizr projesi içerisinde bulunuyor. Evet, daha önce Modernizr ile karşılaştıysanız bu kütüphane de aslında Polyfill sağlıyor.

HTML5 Cross Browser Polyfills



Modernizr'ı da ayrıca vermek gerekirse:

Modernizr.com


Bununla beraber Polyfill.io adında yine web üzerinde aynı desteği sağlayan farklı bir kütüphane de bulunuyor. Ulaşmak için:

Polyfill.io



Vuex Store - Giriş ve Konu Anlatımı


Vue.js ile beraber Vuex'e girmeye karar verdiyseniz yada ne olduğunu merak ediyorsanız, buradan itibaren temiz bir giriş yapacağız. Temelden derinlere doğru inerek Vuex içerisindeki tüm konulara ve alanlara değinmek istiyorum. Hazırsanız başlayalım.

Vuex Kullanım Amacı

Vue.js de dikkat ettiyseniz component yapısı içerisinde veriyi içerden dışarıya, yani alt component'ten üst component'e göndermek zor ve karmaşık bir durum. Ayrıca verinin alt component'te sürekli değişimini ve bunun gibi onlarca component olduğunu düşünün.

Tam olarak burada Vuex veriyi merkezi bir yerde birleştirip tüm component'ler arasında paylaşmayı ve daha dinamik bir yapıyı sağlamayı amaçlıyor. 

Vuex Kullanımına Giriş

Kurulumdan bahsetmeyeceğim, yeni bir Vue örneği ile beraber gelen seçenekler arasında direk kurabiliyorsunuz veya vâr olan bir projeye dahil etmek istiyorsanız netten dökümantasyon incelemek durumundasınız.

Vuex projenizde kuruysa veya kurduysanız ilk olarak /store dizinindeki index.js'i inceleyelim.

import Vue from 'vue' 
import Vuex from 'vuex'

Vue.use(Vuex) 

const store = new Vuex.Store({ 
  state: { 
    count: 0 
  },
  getters: {
  
  }   
  mutations: { 
    increment (state) { 
      state.count++ 
    } 
  },
  actions: {

  }
})

Burada gördüğünüz üzere bir Vuex Store nesnesi oluşturulmuş gözükmekte. Bölümleri şu şekilde.

State: Store verilerinin tutulduğu alan. Store'a ait tüm veriler State içerisinde barındırılır. Yani kaynak burasıdır.

Getters: State içerisindeki veriyi hem direk State üzerinden hem de buradan alabilirsiniz. Ancak Getters'ın farkı veriye mesela "State.kullanicilar.map( ... return x ...)" gibi bir değişiklik yaparak çıktı almak istediğiniz durumlarda kullanılır.

Mutations: State üzerindeki bir veriyi güncellemek istediğiniz zaman Mutations'ları kullanıyoruz. Yani bu demek oluyor ki State üzerindeki veriyi doğrudan değiştiremezsiniz.

Actions: Bazen çok daha detaylı işlemler yapmanız gerekir, mesela form isteği atıp gelen veriyi işlemek gibi. Bunun için Mutations değil Actions'ları kullanırsınız. Sonra veriyi yine değiştirmek için Actions üzerindeki işleminiz bitince, yine Actions içerisinde Mutations'ları çağırır veri güncellemeyi aynı metot ile yaparsınız.


Bu yazımda inceleyeceklerimiz bu kadardı. Bir sonraki yazımda Vuex Store üzerindeki State özelliğine değineceğiz. Teşekkürler.

PHP ile Site Adresini ve Dosya Dizinini Yazdırmak


 


PHP ile çalıştığınız URL'i ve dosya dizin yolunu almak için $_SERVER global değişkeninden yararlanmanız gerekir.

Bir çok değeri bünyesinde barındıran bu değişkende site adresi "HTTP_HOST" üzerinde barınır.

echo $_SERVER['HTTPS'] ?? 'http' . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];

Yukardaki kodun çıktısı aşağıdaki şekilde görünecektir.

http://siteadresi.com/calisma-dizini/
$_SERVER["HTTPS"] değeri eğeri eğer var ise tanımlı olacaktır, yok ise hata vereceği için nullsafe operatörü ile kontrol ettirip olmadığında yerine "http" yazdırıyoruz.

Git 'in Linux üzerinde sürekli şifre isteme sorunu.




Git 'i Linux üzerinde kullanmak ta farklı bir deneyim oldu benim için. Bu durum ilk defa Visual Studio Code üzerinde karşıma çıktı. Çözümü oldukça basit aslında ama böyle işlemleri araştırmak ve bulmak bazen zaman alabiliyor.

Çözümü yine git komutları ile yapacağız. Aşağıdaki komutu terminaliniz üzerinden çalıştırın. Komut sonrası sizden VS Code üzerinde güncelleme yapmak istediğinizde yine şifre isteyecek ama bu girişten sonra bir daha girmeyeceksiniz.

git config --global credential.helper store

Bu komutun amacı da tahmin edebileceğiniz gibi Ev Dizininizde bir dosya oluşturup git kullanıcı bilgilerinizi saklı tutmasıdır.

Vue.js Lifecycle Hooks Anlatımı


Vue.js Lifecycle Hooks

Türkçesi biraz değişik gelebilir ama aslında çok net ve anlaşılabilir bir çevirisi var. "Lifecycle Hooks" yani "Yaşamdöngüsü Kancaları" nedir bunu işleyeceğiz.

Bir örnek ile anlamaya çalışalım, elinizde bir çark var. A, B, C, D noktaları var ve çark döndükçe bu noktalara temas edecek. İşte bu noktaları programın içerisinde çalışan kod blokları olarak alın.

Mesela A fonksiyonu, B fonksiyonu olacak şekilde kabul edelim. A 'ya geldiğinde A içerisindeki kodlar işlenecek sonra da diğerleri. Buna Yaşamdöngüsü diyelim. Şimdi de kodlar çalışırken A ' veya B 'ye uğramadan veya her ikisi arasında bir işlem yapmak istiyorsak ne yaparız ?

Yaşamdöngüsünü bir anlık ta olsa durdurmamız gerekir. İşte burada Kancalar devreye giriyor. Yani A, B, C fonksiyonları çalışırken araya A > A 'dan önce bunu yap > B > C > D 'den önce bunu yap > E şeklinde bu döngüye müdahalede bulunuyoruz.

İşte her Vue örneği aslında bu Yaşamdöngüsü şeklinde çalışıyor ve bizlere bu döngü içerisinde çeşitli yerlere müdahale etme imkanı sunuyor.

Lifecycle Hooks Diyagramı
Öncelikle diyagrama bir göz atalım.

Yukarıdaki diyagram herşeyi açıklıyor aslında. Aşağıda bu diyagram içerisindeki fonksiyonları açıklamasıyla verdim. "before", önce ve "after", sonra demek.

// Uygulama oluşturulmadan önce
beforeCreate()
// Uygulama oluşturulduktan sonra
created()
// Uygulamaya bir etiket mount edilmeden hemen önce
beforeMount()
// Mount edildikten sonra
mounted()
// DOM verisi güncellenmeden hemen önce
beforeUpdate()
// DOM güncellendikten sonra
updated()
// beforeDestroy yani uygulama dağıtılmadan önce
beforeDestroy()
// Uygulama dağıtıldıktan sonra çalışır
destroyed()

Bunların ne olduklarını açıkladık listeledik şimdi detaylarına inelim ve aşama aşama görelim.


  1. beforeCreated() ile uygulama henüz oluşturulmadan önce yani data 'lar ve event 'lerden önce istediğinizi bu fonksiyon içerisinde çalıştırabilirsiniz. 
  2. Bundan sonra da created() yani uygulama oluşturuldu ve bu fonksiyon içerisinde uygulama oluşturulduktan sonra yapılacak bir şey varsa kullanılır.
  3. ve aşağı doğru inerken program bir soru soruyor: "el" var mı? Görüyoruz uygulamada ilk olarak "el" degerini girip etikete bağlıyorduk. Peki ya bağlı değilse ? O zaman program diyor ki uygulama.$mount("#etiket") girildiği zaman devam et. (Hani mount etmenin ikinci yöntemiydi bu($mount("#etiket")))
  4. "el" işlemini sorguladıktan sonra bir soru soruyor "template" degeri ile bir şablon girilmiş mi. Eğer varsa render fonksiyonu ile derle, yoksa "el" ile bağlı olan etikete derle. (Biz başladığımızdan bu yana hep "el" kullandık)
  5. Mount edilmeden hemen bir tık öncesinde beforeMount() fonksiyonuna geçiyor.
  6. Ardından $mount işlemi yapılıyor. DOM verisi listeleniyor ve sonrasında mounted() fonksiyonuna geçiyor. Eğer listeleme tarzında işlemler kullanacaksanız sık kullanacağınız aşama.
  7. Şimdi mounted 'den sonra süreç ikiye ayrılıyor. Birisi diyagramda gördüğünüz üzere beforeUpdate() -> Update(), diğeri de beforeDestroy() -> destroyed()
  8. sayfada bir update işlemi yaparsanız, mesela ürün listelediniz ve "Sil" deyip listeyi db 'den tekrar çekip listelediniz. Sonuç olarak veri değişikliği oldu o zaman beforeUpdate() yani güncellemeden hemen önce ve sonrasında updated() fonksiyonu ile DOM verisi tekrar güncellendikten hemen sonra.
  9. Yukardakilerin hepsi anlaşılır fakat destroy görmediğiniz bir şey. Destroy bir Vue uygulaması üzerinden tüm direktiflerinin, eylemlerinin(events) ve alt çocuk örneklerinin dağıtılması yani kaldırılmasıdır. Örneğin açtığınız etiket içerisindeki tanımladığınız hiç bir eylemi bir daha kullanamazsınız. Ancak bu etiketin boşalması, silinmesi vs. durumu değil. Sadece o etiket üzerindeki işlemlerinizi kullanamazsınız. Listelediğiniz veriler son haliyle orada kalır.

Bir uygulama aşağıdaki şekilde dağıtılır.

uygulama.$destroy()


Bir örnek uygulama ile bu anlatımı da bitireceğim. Baştan aşağı lifecycle hooks ile tasarlanmış bir uygulama hazırladım. Aşağıya kodları ve jsfiddle önizlemesini paylaştım. Sayfa ilk açıldığında beforeCreate -> created çalışacak, "Başlat" dediğimizde $mount edecek, "Değiştir" dediğimizde veri değeri değişecek ve beforeUpdate -> updated çalışacak ardından "Uygulamayı dağıt" denildiğinde $destroy devreye girecek.

Ek olarak belirteyim ben alert() kullandığım için veri değeri güncellenmeden önce uyarı çıkıyor gibi duruyor ancak alert() güncelleme işlemine paralel değil daha erken davranıyor. Bu yüzden veri güncellemesi sonra yapılıyor gibi duruyor.

Bu yazımda burada bitmiş bulunuyor. Bir sonraki yazımda görüşmek üzere...

Vue.js Bileşenler


Vue.js Bileşenler

Bu yazımda Vue Bileşenleri 'ni anlatacağım. Bileşenler sayfa içerisinde kullandığımız hazır şablonlardır. Bileşenler tıpkı bir Vue uygulaması gibi çalışır ancak amaçları farklıdır.
Klasik bir bileşen yapısı aşağıdaki gibidir.
Aslında düşündüğümüz zaman bir web sayfasında her alan bir bileşendir. Mesela sayfanın header kısmı yani <header> etiketi içerisindekiler ile beraber bir bileşendir.

Bileşenleri oluşturur ve tekrar tekrar sayfada kullanırız. Örneğin bir e-ticaret sitesini düşünün her zaman ürünlerin listelendiği bir sayfası ve bu ürünleri sayfa içerisinde bir kart içerisinde göstermek zorunda. Ancak bu kartları hem anasayfada hem de herhangi bir ürün sayfasının alt kısmında diğer ürünler olarak göstermek zorunda. Bunun için her sayfaya bu bileşeni kopyala yapıştır yapmak mı daha doğru yoksa tek bir bileşen haline getirip istediği yere sadece <urun-karti> şeklinde listelemesi mi ?

Tab ki bileşen sistemi öte yandan bu bileşeni tekrar tekrar düzenlediğinde tüm sayfadaki ürün kartları da eşzamanlı olarak bu değişimle birlikte görüntülenecek. Böyle de bir avantajı var.

Bir bileşen aşağıdaki gibi oluşturulur:

Vue JS
Vue.component('urun-karti',
template: '<li>Yepyeni mobilyalar</li>' 
})

<ol>
<!-- Burada urun-karti çağırılacak ve <li> elementi dönecek -->
 <urun-karti></urun-karti>
</ol>


Bu kullanım sade ve sadece tek bir "Yepyeni mobilyalar" çıktısını üretmekten öteye geçemez. İşimizi daha da profesyonelleştirelim.

Burada prob özelliğini kullanacağız ve bir Vue uygulaması içerisindeki bir data 'yı önce bileşen etiketi içerisinde v-bind:xxx şeklinde bağlayacağız ve bunu probs['xxx'] şeklinde bileşen içerisine alacağız.
Tam olarak anlamadıysanız örneği inceleyin.

Vue JS Bileşeni
// Bileşeni oluşturduk
Vue.component('urun-karti', 
// probs ile etiket üzerindeki "veri" attribute 'unu aldık.
props: ['veri'], 
template: '<li>{{ veri.urunIsmi }}</li>' 
})

HTML
<!-- Listelenecek etiketimizi oluşturduk -->
<div id="urunleri-listele">
<ol> 
<!-- Burada önce v-for ile verileri urun 'e attık sonra da v-bind ile "veri" attribute 'una bağladık -->
 <urun-karti v-for="urun in urunler" v-bind:veri="urun"></urun-karti>
</ol>
</div>

Vue JS
//Uygulamamızı oluşturduk ve ürünler adında dizimizi oluşturduk
var uygulama = new Vue({
el: '#urunleri-listele', 
data: { 
urunler: [ 
{ id: 0, urunIsmi : 'Dolap' }, 
{ id: 1, urunIsmi : 'Sandalye' }, 
{ id: 2, urunIsmi : 'Yeni masa gıcır gıcır' } 
})

Bu örneğin çıktısını aşağıdan inceleyebilirsiniz
probs içerisinde farklı attribute 'lar da çağırıp bileşen içerisinde kullanabilirsiniz. Örneğin probs['id','value','class'] şeklinde kullanabilirsiniz.

Bileşenler yazım bu kadar, bundan sonra Lifecycle Hooks(Yaşamdöngüsü Kancaları) 'u anlatacağım. Görüşmek üzere...

Vue.js Koşullar ve Döngüler


Vue.js Koşullar ve Döngüler

Vue
içerisindeki Koşulları ve Döngüleri anlatmaya çalışacağım. Daha önce direktiflerden bahsetmiştim. Şimdi bu iki özellik de birer direktif olarak çalışmakta. Ancak bunlar Vue içerisinde tanımlanmış direktiflerdir.

Koşullar
İf direktifini inceleyelim.

Vue JS
var uygulama = new Vue(
{
el: '#icerik',
data: {
goster: true
}
})

HTML
<div id="icerik">
<span v-if="goster">Görüntüleniyor</span> 
</div>

Yukarıdaki "v-if" örneği:


En basit kullanımı budur. Peki devamını getirelim, yani else, else if kullanalım.

HTML
<div id="icerik">
<span v-if="goster == 1">Deger: 1</span> 
<span v-else-if="goster == 2">Deger: 2</span>
<span v-else">Ne 1, ne de 2</span>
</div>

Döngüler
Döngüleri gösterelim. Uygulama içerisinde bir dizi tanımlayalım ve içerisindeki verileri HTML etiketi içerisinde döndürelim.

Vue JS
var uygulama = new Vue({
el: '#icerik', 
data: { 
veriler: [ 
{ isim: 'Ali' }, 
{ isim: 'Veli' }, 
{ isim: 'Metin' } 
})

HTML
<div id="icerik">
<ol> 
<li v-for="veri in veriler"> {{ veri.isim}} </li> 
</ol>
</div>

yukarıdaki örnekte de verileri içerisindeki veriyi <li> olarak listeleme etiketi içerisinde yazdırdık. Örneği aşağıdan inceleyebilirsiniz.

İsterseniz diziyi anahtarlarıyla beraber yazdırabilirsiniz.

HTML
<div id="icerik" class="p-4">
<p v-for="(veri, key) in veriler">
  <b>{{key}}.</b> {{ veri.isim}} </p>
</div>

Yukarıdaki örneğin çıktısı:

Son olarak söylemek istediğim aynı etiket içerisinde v-if ve v-for direktiflerini beraber kullanmayın.

Tasarımcılara bu konuda cazip gelen iki durum var:

  • <li v-for="kullanıcı in kullanıcılar" v-if="kullanıcı.aktifMi"> bunu bu şekilde değil de kullanıcılar verisini döndürmeden önce aktifKullanicilar diye bir değer oluşturup listelenecekler buraya filtre ile atılabilir sonra listelenebilir.(filterelere değineceğiz anlaşılması açısından değindim)
  • ikincisi bir li elemanında if ve for kullanacaksanız öncesinde bir etiket açın if direktifini girin daha sonrasında li içerisinde for kullanarak verilerinizi listeleyin. Örn:

<ul v-if="goster">
      <li v-for="kullanici in kullanicilar">{{kullanici.isim}}</li>
</ul>


Bu dersimiz de burada bitti. Bundan sonra Components yani Bileşenleri işleyeceğiz. Görüşmek üzere...


Vue.js Direktifler


Vue.js Direktifler

Vue.js
ile bir elemente özellik atamak veya kontrol sağlamak için direktifler kullanılır. Mesela önceki dersimizde method 'lardan bahsetmiştim. onclick ve onfocus gibi özellikleri direktif olarak kullanıyoruz.

v-html
Örneğin bir Vue uygulamasında bir data içerisinde bir HTML kodu bulunsun.

Vue JS
var uygulama = new Vue({
el: "#anasayfa",
data:{
      veriHTML: "<b>Gökhan</b>"
}
})

Şimdi veriHTML değerini {{ veriHTML }} olarak yazdırabiliriz ancak sayfada HTML olarak değil string olarak görüntülenecektir. Bunun için "v-html" direktifini kullanacağız.

HTML
<div id="anasayfa">
      <p v-html="veriHTML"></p>
</div>

Böylece değeri HTML kodu olarak p etiketi içerisinde görüntüledik.

v-show
Bir başka direktif de "v-show" dur. Eğer veri true dönerse etiketi görüntüleyecektir, false dönerse etiket yok olacaktır. v-show ekranda display:block|none; işlemi görecektir. v-if gibi etiketi komple ortadan kaldırmaz.

Vue JS
var uygulama = new Vue({
el: "#anasayfa",
data:{
      veri1: "Merhaba",
      veri2: true,
      veri3: false
}
})

HTML
<div id="anasayfa">
      <p v-show="veri1">{{ veri1 }}</p>
      <p v-show="veri2">{{ veri2}}</p>      <p v-show="veri3">Çalışmayacak</p>
</div>

  • veri1 görüntülenecek ve Merhaba yazacaktır.
  • veri2 görüntülenecek ve true yazacaktır.
  • veri3 ise false olduğu için görüntülenmeyecektir.

v-model
Bir diğer direktif v-model bu direktif ile reaktif olarak input girişi yapılmaktadır.

Vue JS
var uygulama = new Vue({
el: "#anasayfa",
data:{
      inputGiris: "Merhaba"
}
})

HTML
<div id="anasayfa">
      <input type="text" v-model="inputGiris" />
      <p>{{ inputGiris }}</p>
</div>


v-model input örneği:
v-bind
Son olarak yoğun olarak kullanacağımız v-bind direktifinden bahsedeceğim. v-bind ile bir element içerisinde istediğimiz attribute 'a işlem yapabiliyoruz ve istersek isteğe bağlı attr değeri ekleyebiliyoruz.

Vue JS
var uygulama = new Vue({
el: "#anasayfa",
data:{
      sinifAdi: "Merhaba",
      idDegeri: "paragrafim"
}
})


HTML
<div id="anasayfa">
<p v-bind:class="sinifAdi" v-bind:id="idDegeri">Gökhan Korul</p>
</div>

İstersek class ataması yaparken bir if koşulu da kullanabiliriz. Mesela 2 adet butonumuz var hangisi tıkalırsa ona aktif(active) sınıfı eklemek istiyoruz.

Vue JS
var uygulama = new Vue({
el: "#anasayfa",
data:{
      btn1:1,
      btn2:2
},
methods: {
aktifEt(id) {
      if (id == 1) {
        this.btn1 = 1
        this.btn2 = 0
        } else if (id == 2) {
        this.btn2 = 1
        this.btn1 = 0
        }
      }
}
})

HTML
<div id="anasayfa" class="p-2">
   <a href="#"
   v-bind:class="[btn1 == 1 ? 'active' : '']"
   v-on:click="aktifEt(1)"
   class="btn btn-primary btn-lg">
      Anasayfa
   </a>
   <a href="#"
   v-bind:class="[btn2 == 1 ? 'active' : '']" 
   v-on:click="aktifEt(2)"
   class="btn btn-primary btn-lg">
      Ürünler
   </a>
</div>

Burada btn1 ve btn2 adında iki data verisi oluşturduk ve bunlardan hangisi 1 ise o class içerisinde active yazacak şeklinde a etiketi v-bind:class içerisinde koşul oluşturduk. Tabiiki böyle kullanmayın :) Sadece örnek olsun diye böyle kodladım sizin daha usta örnekler yapacağınızdan eminim.

Butonu akif et örneği:


Bir sonraki yazımda Koşullardan ve Döngülerden bahsedeceğim. Görüşmek üzere...

Vue.js data ve methods


Vue.js data ve method 'lar


Klasik bir Vue uygulamasının nasıl oluşturulduğunu öğrenmiştik. Şimdi tekrar Vue örneğini bir hatırlayalım.

var vm = new Vue({ 
// özellikler 
})

Daha sonra verilerimizin tamamını içerisinde barındıracağımız data nesnesini ekleyelim.

var vm = new Vue({ 
data {
      veri:" "
})


Data ve Method 'lar
Yukarıda data içerisinde veri adında bir değer oluşturduk ve şimdi bu örneğe bazı veriler eklemeye çalışalım.

vm.veri = 2;

Bu şekilde veri 'ye "2" değerini verdik. Vue reaktif olduğu için hemen tepki verecektir. Örneğin bir önceki derste de anlattığım gibi {{ veri }} şeklinde sayfanın herhangi bir yerinde bu data 'yı kullanacak olsaydık anlık olarak sayfada da "2" yazdığını görecektik.

Aynı şekilde bir Vue uygulaması içerisinden bir data 'ya ulaşmak isterseniz aşağıdaki örneği de kullanabilirsiniz.

vm.$data.veri

Ayrıntılara ilerde değineceğiz. Bu uygulamaya dışardan bir değer almak istersek de aşağıdaki gibi bir örnek uygulayabiliriz.

var deger = "Merhaba";

var vm = new Vue({ 
data {
      veri: deger 
})

Değer değişkenini veri içerisine attık. 

Şimdi ise method 'lara değinelim. Bildiğimiz onclick ve onfocus gibi olayları Vue 'da methods olarak kullanırız ve klasik olarak JS ile yaptığımız işlerin aynısını Vue örneği içerisinde yaparız. Bir onclick olayı örneği yapalım.

Vue JS
var vm = new Vue({
el:"#uygulama",
data {
      veri:"Merhaba"
})

HTML
<div id="uygulama"> 
<p>{{ veri }}</p> 
<button v-on:click="veri = 'Selam'">Değiştir</button> 
</div>

Yukarıdaki örnekte "Değiştir" tıklanınca bir event tetiklenecek ve method kullanmış olacağız. Böylece veri değişkenine "Selam" değerini vermiş olacağız. 

Şimdi daha detaylı olarak onclick içerisinde bir fonksiyon devreye sokalım. Bunun için Vue içerisine data 'nın hemen altına methods:{ } nesnesini ekliyoruz ve nesne parantezlerini açıyoruz. Bundan sonra fonksiyonlarımız burada oluşturacağız. Bir örnek:

 
Vue JS
var vm = new Vue({
el:"#uygulama",
data {
      veri:"Merhaba"
},
methods:{
degistir() {
   this.veri = "Selam ben Gökhan";
  }
}
})

HTML
<div id="uygulama"> 
<p>{{ veri }}</p> 
<button v-on:click="degistir()">Değiştir</button> 
</div>

Şimdi de butona tıkladığımızda "Selam ben Gökhan" yazacaktır ve aynı işlemi bu sefer bir fonksiyon(method) tanımlayarak yaptık. Burada son olarak dikkat etmişsinizdir, data içerisindeki verilere ulaşmak için uygulama içerisinde her zaman this.veri şeklinde ulaşırız.
Bu dersimizde burada bitmiş bulunuyor. Görüşmek üzere...