Tepkiselliğin Temelleri
API Tercihi
Bu sayfa ve rehberin ilerleyen bölümlerinin birçoğu, Options API ve Composition API için farklı içerikler sunar. Mevcut tercihiniz Composition API. Sol kenar çubuğunun üst kısmındaki "API Tercihi" anahtarlarını kullanarak API stilleri arasında geçiş yapabilirsiniz.
Tepkisel Durumu Tanımlama
ref()
Composition API'de tepkisel durumu tanımlamanın önerilen yolu ref() fonksiyonunu kullanmaktır:
js
import { ref } from 'vue'
const count = ref(0)ref(), aldığı argümanı .value özelliğine sahip bir ref nesnesi içinde sararak döndürür:
js
const count = ref(0)
console.log(count) // { value: 0 }
console.log(count.value) // 0
count.value++
console.log(count.value) // 1Ayrıca bkz.: Ref Türleri
Bileşen şablonunda reflere erişmek için, bir bileşenin setup() fonksiyonunda bunları tanımlayıp döndürün:
js
import { ref } from 'vue'
export default {
// `setup`, Composition API'ye özel bir kancadır.
setup() {
const count = ref(0)
// ref'i şablona açın.
return {
count
}
}
}template
<div>{{ count }}</div>Ref'i şablonda kullanırken .value eklememize gerek olmadığını fark edin. Kullanım kolaylığı için ref'ler, şablonların içinde kullanıldığında otomatik olarak açılır (bazı istisnalarla).
Ref'i olay işleyicilerinde de doğrudan değiştirebilirsiniz:
template
<button @click="count++">
{{ count }}
</button>Daha karmaşık bir mantık için, ref'leri değiştiren fonksiyonları aynı kapsamda tanımlayıp duruma ek olarak yöntem olarak dışa açabiliriz:
js
import { ref } from 'vue'
export default {
setup() {
const count = ref(0)
function increment() {
// JavaScript'te .value gereklidir.
count.value++
}
// fonksiyonu da dışa açmayı unutmayın.
return {
count,
increment
}
}
}Dışa açılan yöntemler daha sonra olay işleyici olarak kullanılabilir:
template
<button @click="increment">
{{ count }}
</button>Bu örneğin canlı halini, herhangi bir build aracı kullanmadan Codepen üzerinde görebilirsiniz.
<script setup>
setup() üzerinden durumu ve yöntemleri elle dışa açmak ayrıntılı olabilir. Neyse ki Tek Dosyalı Bileşenler (SFC) kullanıldığında bundan kaçınılabilir. <script setup> ile kullanımı sadeleştirebiliriz:
vue
<script setup>
import { ref } from 'vue'
const count = ref(0)
function increment() {
count.value++
}
</script>
<template>
<button @click="increment">
{{ count }}
</button>
</template><script setup> içinde tanımlanan üst düzey importlar, değişkenler ve fonksiyonlar, aynı bileşenin şablonunda otomatik olarak kullanılabilir. Şablonu, aynı kapsamda tanımlanmış bir JavaScript fonksiyonu gibi düşünebilirsiniz; doğal olarak aynı kapsamda tanımlanan her şeye erişebilir.
TIP
Rehberin geri kalanında, Composition API kod örneklerinde öncelikli olarak SFC + <script setup> söz dizimini kullanacağız; çünkü Vue geliştiricileri arasında en yaygın kullanım biçimi budur.
SFC kullanmıyorsanız da Composition API'yi setup() seçeneğiyle kullanabilirsiniz.
Neden Ref?
Ref'leri, düz değişkenler yerine neden .value ile kullandığımızı merak ediyor olabilirsiniz. Bunu açıklamak için Vue'nun tepkisellik sisteminin nasıl çalıştığına kısaca bakalım.
Şablonda bir ref kullandığınızda ve sonrasında bu ref'in değerini değiştirdiğinizde Vue değişikliği otomatik olarak algılar ve DOM'u buna göre günceller. Bu, bağımlılık takibine dayalı tepkisellik sistemi sayesinde mümkündür. Bir bileşen ilk kez render edildiğinde Vue, render sırasında kullanılan her ref'i izler. Daha sonra bir ref değiştirildiğinde, onu izleyen bileşenler için yeniden render işlemini tetikler.
Standart JavaScript'te düz değişkenlere erişimi veya bunların değişimini doğrudan yakalamanın bir yolu yoktur. Ancak bir nesnenin özelliklerindeki get ve set işlemlerini getter ve setter yöntemleriyle yakalayabiliriz.
.value özelliği, bir ref'e ne zaman erişildiğini veya ne zaman değiştirildiğini algılama fırsatını Vue'ya verir. Arka planda Vue, getter içinde izleme yapar ve setter içinde tetikleme gerçekleştirir. Kavramsal olarak bir ref'i aşağıdaki gibi bir nesne olarak düşünebilirsiniz:
js
// sözde kod, gerçek implementasyon değildir
const myRef = {
_value: 0,
get value() {
track()
return this._value
},
set value(newValue) {
this._value = newValue
trigger()
}
}Ref'lerin bir diğer güzel özelliği, düz değişkenlerin aksine ref'leri fonksiyonlara geçirirken en güncel değere erişimi ve tepkisellik bağlantısını koruyabilmenizdir. Bu özellik, karmaşık mantığı yeniden kullanılabilir koda dönüştürürken özellikle faydalıdır.
Tepkisellik sistemi, Derinlemesine Tepkisellik bölümünde daha ayrıntılı ele alınır.
Derin Tepkisellik
Ref'ler, derin iç içe geçmiş nesneler, diziler veya Map gibi JavaScript'in yerleşik veri yapıları dahil olmak üzere her tür değeri tutabilir.
Bir ref, tuttuğu değeri derin tepkisel hale getirir. Bu, iç içe nesneleri veya dizileri değiştirdiğinizde bile değişikliklerin algılanacağı anlamına gelir:
js
import { ref } from 'vue'
const obj = ref({
nested: { count: 0 },
arr: ['foo', 'bar']
})
function mutateDeeply() {
// bunlar beklendiği gibi çalışır.
obj.value.nested.count++
obj.value.arr.push('baz')
}İlkel olmayan değerler, aşağıda ele alınan reactive() aracılığıyla tepkisel proxy'lere dönüştürülür.
Sığ ref'ler ile derin tepkisellikten çıkmak da mümkündür. Sığ ref'lerde tepkisellik için yalnızca .value erişimi izlenir. Sığ ref'ler, büyük nesnelerin gözlemlenme maliyetinden kaçınarak performansı iyileştirmek veya iç durumun harici bir kütüphane tarafından yönetildiği durumlarda kullanılabilir.
Daha fazla bilgi:
DOM Güncelleme Zamanlaması
Tepkisel durumu değiştirdiğinizde DOM otomatik olarak güncellenir. Ancak DOM güncellemelerinin eşzamanlı uygulanmadığını unutmamak gerekir. Vue bunun yerine, yaptığınız durum değişikliği sayısı ne olursa olsun her bileşenin yalnızca bir kez güncellenmesini sağlamak için güncellemeleri güncelleme döngüsündeki "bir sonraki tik" anına kadar arabelleğe alır.
Bir durum değişikliğinden sonra DOM güncellemesinin tamamlanmasını beklemek için nextTick() global API'sini kullanabilirsiniz:
js
import { nextTick } from 'vue'
async function increment() {
count.value++
await nextTick()
// DOM artık güncellendi
}reactive()
Tepkisel durumu tanımlamanın bir başka yolu da reactive() API'sidir. İç değeri özel bir nesneyle saran ref'in aksine reactive(), nesnenin kendisini tepkisel hale getirir:
js
import { reactive } from 'vue'
const state = reactive({ count: 0 })Ayrıca bkz.: Reactive Türleri
Şablonda kullanım:
template
<button @click="state.count++">
{{ state.count }}
</button>Tepkisel nesneler, normal nesneler gibi davranan JavaScript Proxy'leridir. Farkı, Vue'nun tepkiselliği izlemek ve tetiklemek için tepkisel bir nesnenin tüm özelliklerine erişim ve değişim işlemlerini yakalayabilmesidir.
reactive() nesneyi derinlemesine dönüştürür: iç içe nesneler de erişildiğinde reactive() ile sarılır. Ayrıca ref değeri bir nesne olduğunda ref() tarafından dahili olarak da çağrılır. Sığ ref'lere benzer şekilde, derin tepkisellikten çıkmak için shallowReactive() API'si de vardır.
Tepkisel Proxy ve Orijinali
reactive() fonksiyonundan dönen değerin, özgün nesnenin bir Proxy örneği olduğunu ve özgün nesneye eşit olmadığını bilmek önemlidir:
js
const raw = {}
const proxy = reactive(raw)
// proxy, özgün nesneye eşit DEĞİLDİR.
console.log(proxy === raw) // falseYalnızca proxy tepkiseldir; özgün nesneyi değiştirmeniz güncellemeleri tetiklemez. Bu nedenle Vue'nun tepkisellik sistemiyle çalışırken en iyi yaklaşım, durumunuzun yalnızca proxy sürümlerini kullanmaktır.
Proxy'ye tutarlı erişim sağlamak için, aynı nesnede reactive() çağrıldığında her zaman aynı proxy döner; mevcut bir proxy üzerinde reactive() çağrıldığında da yine aynı proxy döner:
js
// aynı nesne üzerinde reactive() çağrısı aynı proxy'yi döndürür
console.log(reactive(raw) === proxy) // true
// bir proxy üzerinde reactive() çağrısı kendisini döndürür
console.log(reactive(proxy) === proxy) // trueBu kural iç içe nesneler için de geçerlidir. Derin tepkisellik nedeniyle tepkisel bir nesnenin içindeki iç nesneler de proxy'dir:
js
const proxy = reactive({})
const raw = {}
proxy.nested = raw
console.log(proxy.nested === raw) // falsereactive() Sınırlamaları
reactive() API'sinin bazı sınırlamaları vardır:
Sınırlı değer türleri: yalnızca nesne türlerinde çalışır (nesneler, diziler ve
Map,Setgibi koleksiyon türleri).string,number,booleangibi ilkel türleri tutamaz.Nesnenin tamamı değiştirilemez: Vue'nun tepkisellik takibi özellik erişimi üzerinden çalıştığı için tepkisel nesne için aynı referansı korumamız gerekir. Bu, ilk referansla kurulan tepkisellik bağlantısı kaybolacağı için tepkisel bir nesneyi kolayca "değiştiremeyeceğimiz" anlamına gelir:
jslet state = reactive({ count: 0 })
// yukarıdaki referans ({ count: 0 }) artık izlenmez // (tepkisellik bağlantısı kayboldu!) state = reactive({ count: 1 })
3. **Yapı bozuma uygun değildir:** tepkisel bir nesnenin ilkel türdeki özelliğini yerel değişkenlere yapı bozumu ile ayırdığımızda veya bu özelliği bir fonksiyona geçirdiğimizde tepkisellik bağlantısını kaybederiz:
```js
const state = reactive({ count: 0 })
// yapı bozumu yapıldığında count, state.count ile bağlantısını kaybeder.
let { count } = state
// orijinal durumu etkilemez
count++
// fonksiyon düz bir sayı alır ve
// state.count üzerindeki değişiklikleri izleyemez
// tepkiselliği korumak için nesnenin tamamını geçmeliyiz
callSomeFunction(state.count)Bu sınırlamalar nedeniyle tepkisel durum tanımlamak için birincil API olarak ref() kullanmanızı öneririz.
Ref Açma Hakkında Ek Ayrıntılar
Tepkisel Nesne Özelliği Olarak
Bir ref, tepkisel bir nesnenin özelliği olarak erişildiğinde veya değiştirildiğinde otomatik olarak açılır. Başka bir deyişle normal bir özellik gibi davranır:
js
const count = ref(0)
const state = reactive({
count
})
console.log(state.count) // 0
state.count = 1
console.log(count.value) // 1Mevcut bir ref'e bağlı özelliğe yeni bir ref atanırsa eskisinin yerini alır:
js
const otherCount = ref(2)
state.count = otherCount
console.log(state.count) // 2
// özgün ref artık state.count ile bağlantılı değil
console.log(count.value) // 1Ref açma işlemi yalnızca derin tepkisel bir nesnenin içine gömülü olduğunda gerçekleşir. Sığ tepkisel bir nesnenin özelliği olarak erişildiğinde uygulanmaz.
Diziler ve Koleksiyonlarda Dikkat Edilecek Nokta
Tepkisel nesnelerden farklı olarak ref, tepkisel bir dizinin elemanı veya Map gibi yerel bir koleksiyon türünün öğesi olarak erişildiğinde açılmaz:
js
const books = reactive([ref('Vue 3 Guide')])
// burada .value gerekir
console.log(books[0].value)
const map = reactive(new Map([['count', ref(0)]]))
// burada .value gerekir
console.log(map.get('count').value)Şablonlarda Açma Sırasında Dikkat Edilecek Nokta
Şablonlarda ref açma yalnızca ref, şablon render bağlamında üst düzey bir özellikse uygulanır.
Aşağıdaki örnekte count ve object üst düzey özelliklerdir, ancak object.id üst düzey değildir:
js
const count = ref(0)
const object = { id: ref(1) }Bu nedenle aşağıdaki ifade beklendiği gibi çalışır:
template
{{ count + 1 }}...ancak aşağıdaki ifade çalışmaz:
template
{{ object.id + 1 }}Render sonucu [object Object]1 olur; çünkü ifade değerlendirilirken object.id açılmaz ve ref nesnesi olarak kalır. Bunu düzeltmek için id değerini üst düzey bir özellik olacak şekilde yapı bozumu ile ayırabiliriz:
js
const { id } = objecttemplate
{{ id + 1 }}Artık render sonucu 2 olacaktır.
Dikkat edilmesi gereken bir diğer nokta da şudur: Bir ref, metin enterpolasyonunda (yani {{ }} etiketinde) son değerlendirilen değer olduğunda gerçekten açılır. Bu yüzden aşağıdaki örnek 1 olarak render edilir:
template
{{ object.id }}Bu yalnızca metin enterpolasyonunun sağladığı bir kullanım kolaylığıdır ve {{ object.id.value }} ile eşdeğerdir.