holodepth

Framework entegrasyonları · Vue + Three

Kare Döngüsü & watchEffect: Reaktif Graf Vergisinden Kaçış

Reaktif harita kurulduktan sonra sahne her karede nefes alır. Bu sayfa requestAnimationFrame ile Vue reaktivite sınırını anlatır: Vue 101 dersi değil · tik içinde bağımlılık grafiği üretmemek.

Holodepth bu yaprağı Composition API sözlüğü veya watch / watchEffect temeli olarak yazmaz. R3F kare diplomasi useFrame / useThree yaprağındadır (Fiber store aboneliği). Angular Zone vergisi Kare döngüsü & NgZone yaprağındadır. Mount kökü Mount & kök sözleşmesi , reaktif harita Reaktif şablon → Object3D yapraklarındadır. Ms / jank SLA Platform · FPS yaprağındadır. Ağır reaktif kaçış Reaktif kaçış & performans yaprağında derinleşir. glTF bu kapının konusu değildir.

Sayfayı bitirdiğinizde şu cümleye inanın: «rAF metronomdur; her karede watchEffect grafiği vergi keser. Döngü reaktif kapı dışında yaşar. Object3D markRaw hattındadır. onDemand invalidate kökü uyandırır. Gizli sekme pause eder. onBeforeUnmount yalnızca stop eder; dispose bir sonraki kapıdadır.»

Bu sayfanın sınırı · komşu konularla ayrım

Bu sayfa Vue + Three'de kare / reaktivite diplomasisini anlatır:

  • rAF metronom · bağımlılık grafiği yasağı
  • watchEffect kötüye kullanım · render vergisi
  • useLoop composable · Tres useRender yüzeyi
  • always / onDemand · invalidate köprüsü
  • Görünürlük pause · onBeforeUnmount stop silueti

Bilinçli olarak dışarıda bırakılan konular:

Kısa ayrım: Bu sayfa «tik grafiği üretmesin» · R3F useFrame «Fiber kare aboneliği» · NgZone «CD patch vergisi» · Platform FPS «ms bütçesi».

useLoop: metronomun evi

Holodepth ürün varsayılanı: kare döngüsünü tek bir composable (useLoop) içinde toplamak. Böylece rAF sahibi, pause politikası ve onBeforeUnmount stop tek yerde mühürlenir. Dağınık onMounted içi döngüler ikinci metronom riski taşır; useLoop «tek sahip» sözleşmesidir.

useLoop callback'i reaktif kapı dışında çalışmalıdır: içinde ref okumak grafiğe bağlar, her karede yeniden izleme adayı üretir. Parametre olarak gelen delta ve elapsed yeterlidir; kare içinde watchEffect açmayın.

TresJS gibi kütüphaneler benzer yüzeyi useRender adıyla sunar. Holodepth burada kütüphane API'sini kataloglamaz; yalnızca «kare aboneliği composable'da yaşar» ilkesini mühürler. Kendi useLoop'unuz veya Tres useRender aynı diplomatiktir: ince callback, ağır iş yok.

watchEffect vergisi

Vue reaktivitesi güçlüdür; kare döngüsü için fazla güçlüdür. watchEffect içinde her tikte okunan ref, reactive veya computed bağımlılık kaydı açar. 60 Hz vitrinde bu, saniyede 60 kez «graf güncelle, belki render et» demektir. R3F'deki setState zehri ve Angular'daki Zone içi rAF ile aynı aileden bir faturadır: yüksek frekanslı 3D iş, düşük frekanslı UI çerçevesine sızmamalıdır.

Tipik hata: watchEffect(() => { mesh.rotation.y += 0.01 }) veya rAF callback içinde reaktif state okuyup yazmak. Doğru hat: karede Object3D'yi doğrudan itmek; UI'ye yansıyacak değeri seyreltmek (watch ile anlamlı değişimde, veya N karede bir).

Tik ucuz sandığınız watchEffect, ikinci bir render motoru çalıştırır.

rAF: her karede graf yok

requestAnimationFrame ekran ritmine yaslanır; Three renderer.render çoğu üründe burada çağrılır. Holodepth kuralı: rAF zinciri reaktif sistemle konuşmamalı, yalnızca sahne grafını güncellemelidir. Mount yaprağında renderer mühürlendi; burada metronomun Vue Proxy'sine değil Object3D'ye bağlandığını doğrulayın.

Çift rAF (hem parent hem child composable) yarış üretir. Tek döngü sahibi useLoop veya eşdeğeridir. Delta ölçümü karede bir kez yapılır; aynı tikte ikinci clock.getDelta() tuzağına düşmeyin. Platform FPS ms dilim teşhisi ayrı yapraktadır; siz yalnızca tik politikasını mühürlersiniz.

İki saat: şablon ve kare

Vue şablon render'ı durum değişince (veya üst yeniden çizilince) çalışır. Three karesi ise rAF metronomuna bağlıdır: sürekli (always) veya talepte (onDemand). Holodepth: bu iki saati aynı boruda karıştırmayın. Panel checkbox'ı için ref güncellemesi; orbit, sallanma, trail için kare callback'i.

Imperatif Three'de kendi animate döngünüzü yazarsınız. Vue + Three'de döngüyü composable toplar; sizin işiniz o döngüye reaktif olmayan iş eklemektir. Şablonu her kare yeniden uzlaştırmak, R3F'de her kare JSX prop yazmaya benzer pahalıdır.

Tres useRender yüzeyi

TresJS, Vue şablonunda deklaratif Three bileşenleri sunarken kare aboneliğini useRender ile verir. Holodepth burada Tres kurulumu öğretmez; yalnızca yüzey eşlemesini not eder: useRender((state) => { … }) R3F useFrame kardeşidir, fakat Vue reaktivite kuralları geçerlidir: callback ince kalmalı, içinde reaktif okuma yapılmamalıdır.

Kendi composable'ınız (useLoop) veya Tres useRender seçimi ürün mimarisidir. İkisini aynı sahnede ikinci metronom olarak çalıştırmayın. Kütüphane sürümünüzde pause / priority semantiği değişebilir; sözleşmeyi «tek sahip, ince callback» olarak yazın.

Object3D mutasyon hattı

Kare içinde mesh konumunu değiştirmenin yolu işaretlenmiş Object3D referansıdır: önceki yaprakta markRaw ile Proxy'den kaçınmış shallowRef veya template ref. Karede root.value.rotation.y += speed * delta yazılır; bu, şablon prop'unu her karede yeniden başlatmaz.

Reaktif haritada mühürlenen «tek kaynak» kuralı burada şöyle okunur: sürekli değişen bir alanı hem :rotation-y bağlaması hem kare callback'i ile itmek çift kapıdır. Ya deklaratif (seyrek) ya kare (sık); ikisini aynı eksen için yarıştırmayın.

Kare içi / dışı karar tablosu
İş Konum Not
renderer.render / mesh itiş rAF callback (reaktif dışı) Her kare
Seçim id → şablon watch (seyrek) Anlamlı değişimde
Her kare HUD metni Kaçının veya seyreltin Render selı

always, onDemand ve invalidate

Vitrin idle motion sürekli rAF ister (always profili). Dashboard paneli verisi gelince tek kare (veya kısa burst) çizebilir: onDemand politikası R3F frameloop="demand" kardeşidir. Holodepth: boşta dönen loop pil yer; panelde always varsayılanı sorgulanır.

onDemand iken dış event, prop seed veya resize sonrası tek kare uyandırmak gerekir (invalidate benzeri bayrak veya kontrollü requestAnimationFrame). Karışık profil: sürekli idle motion isteyen çocuk + onDemand kök = uyumsuz sözleşme. Ya kökü always yapın ya idle motion'u bırakın ya da kontrollü invalidate üretin.

Görünürlük, pause ve onBeforeUnmount stop

Gizli sekme (document.visibilityState === 'hidden') veya bileşen görünürlük bayrağı: döngüyü duraklatın. Pil ve ısı için ürün politikasıdır. useLoop içinde pauseWhenHidden veya eşdeğer dinleyici tek yerde mühürlenir; her child'ın ayrı visibility listener'ı ikinci politika riskidir.

Sekme geri döndüğünde unbounded delta için hız tavanı düşünün; uzun aralıktan sonra tek karede dev sıçrama animasyonu kırar. Bu, Platform FPS jank teşhisine köprüler; burada yalnızca pause / resume sözleşmesi yazılır.

Bileşen ömrü bittiğinde cancelAnimationFrame ile zinciri kesin. Holodepth bu sayfada yalnızca stop siluetini mühürler: metronom ömürle ölür. Geometry, material, texture dispose derinliği Yükleme & onBeforeUnmount yaprağındadır; burada tekrar anlatılmaz.

Orphan rAF, orphan WebGL context'in ikizidir. useLoop onBeforeUnmount içinde stop() çağırmalıdır; aksi hâlde unmount sonrası tik atmaya devam eden callback, Proxy'siz ama hayalet sahneye yazar.

Görünmez sekmede akan rAF, görünmez fatura keser.

Güvenli kare: simüle composable

Örnekler öğretim amaçlıdır; paket sürümünüzü doğrulayın. Mount'ta renderer/scene/camera hazır kabul edilir. Vue reaktivite temeli öğretilmez.

Simüle · useLoop: reaktif graf yok, pause ve stop mühürlü. Mutasyon markRaw Object3D üzerinden; her karede ref yazımı yok.

import { onBeforeUnmount, onMounted } from 'vue'
import * as THREE from 'three'

type LoopCallback = (delta: number, elapsed: number) => void

export function useLoop(render: () => void, onTick?: LoopCallback) {
  let raf = 0
  let running = false
  const clock = new THREE.Clock()

  const frame = () => {
    if (!running) return
    const delta = clock.getDelta()
    const elapsed = clock.elapsedTime
    onTick?.(delta, elapsed)
    render()
    raf = requestAnimationFrame(frame)
  }

  const pauseWhenHidden = () => {
    if (document.hidden) {
      running = false
      cancelAnimationFrame(raf)
      raf = 0
    } else if (!running) {
      running = true
      clock.start()
      raf = requestAnimationFrame(frame)
    }
  }

  onMounted(() => {
    running = true
    clock.start()
    document.addEventListener('visibilitychange', pauseWhenHidden)
    raf = requestAnimationFrame(frame)
  })

  onBeforeUnmount(() => {
    running = false
    cancelAnimationFrame(raf)
    document.removeEventListener('visibilitychange', pauseWhenHidden)
  })
}

Simüle · onDemand tek kare uyandırma. Panel profili: sürekli loop yok; seed değişince bir kare.

import { watch, type Ref } from 'vue'

/** Panel: sürekli loop yok · invalidate benzeri tek kare */
export function useOnDemandRender(
  seed: Ref<unknown>,
  render: () => void,
): void {
  watch(seed, () => {
    requestAnimationFrame(() => {
      render()
    })
  })
}

/**
 * Veri seed değişince (Vue ref):
 *   useOnDemandRender(dataSeed, () => renderer.render(scene, camera))
 * Her render turunda çağırmayın · yalnız anlamlı değişimde.
 */

Güvenlik: rAF callback içinde kullanıcı string'ini eval etmeyin. Kare içinde reaktif okuma yapmayın; UI güncellemesi seyrek watch ile ayrı kanalda kalsın.

Kare / reaktivite tuzakları

  1. watchEffect içi rAF: her kare graf güncellemesi.
  2. rAF içi ref okuma: sessiz bağımlılık kaydı.
  3. Proxy'li Scene: markRaw atlanmış mesh.
  4. Çift metronom: iki composable iki loop.
  5. Unmount'süz rAF: orphan tik.
  6. Boşta always: panelde pil yangını.
  7. Her move'da ref yazımı: picking selı (sonraki yaprak).
  8. useFrame / NgZone ezberi: Vue'da Fiber store veya Zone yok.

Üç kare profili

  • 01 · Tik

    Sürekli vitrin

    Loop
    useLoop always · pauseWhenHidden
    UI
    Seyrek watch
    Risk
    Gizli sekmede unutulmak
  • 02 · Tik

    onDemand panel

    Loop
    Tek kare invalidate
    Tetik
    Ref seed / resize
    Risk
    always unutmak
  • 03 · Tik

    Tres + composable hibrit

    3D
    useRender ince callback
    UI
    Şablon seyrek · kare sık
    Risk
    İkinci metronom

Holodepth perspektifleri ve sonraki kapı

Kareyi ince tutun

useLoop callback'i bir mikro-işletmendir; uygulama çekirdeği değildir. Ağır iş kare dışına veya worker'a itilir.

Grafiği karede üretmeyin

Reaktivite güçlü araçtır; 60 Hz borusuna bağlamak pahalıdır. Object3D hattı Proxy dışındadır.

Ömürle öldürün

cancelAnimationFrame onBeforeUnmount'un parçasıdır; dispose ayrı kapıdadır.

Teşhis maddeleri

  1. rAF callback reaktif okuma yapıyor mu?
  2. watchEffect döngü içinde mi?
  3. Tek döngü sahibi kim?
  4. pauseWhenHidden / visibility var mı?
  5. onBeforeUnmount stop mühürlü mü?
  6. Panel always mı onDemand mı?
  7. UI güncellemeleri seyrek mi?
  8. useFrame, NgZone veya glTF bu sayfaya sızmış mı?

Holodepth içgörüsü

«Vue yavaşlatıyor» çoğu zaman Three değildir; kare içinde açılan reaktif graf ve şablon selidir. Önce metronomun evini okuyun, sonra tici yazın.

Sonraki kapı: yükleme & onBeforeUnmount

Tik canlıyken asıl yük çoğu zaman asenkron varlıktadır. Sonraki sayfa Yükleme & onBeforeUnmount loader ömrü ile dispose sahipliğini anlatır. Picking ve reaktif kaçış sonraki yapraklardadır.