javascript - Cum să reacționezi la schimbările de rută în Vue 3, API-ul de compoziție „script setup”?


Acesta este un exemplu de rute pe care le am în aplicația mea:

{
  path: "/something",
  name: "SomeRoute",
  component: SomeComponent,
  meta: {showExtra: true},
},
{
  path: "/somethingElse",
  name: "SomeOtherRoute",
  component: SomeOtherComponent,
},

Atunci am următoarea componentă, care, după cum veți observa, are două etichete script, una cu API de compoziție și una fără:

<template>
  <div>
    This will always be visible. Also here's a number: {{ number }}
  </div>

  <div v-if="showExtra">
    This will be hidden in some routes.
  </div>
</template>

<script setup lang="ts">
import type { RouteLocationNormalized } from "vue-router"
import { ref } from "vue"

const number = 5
const showExtra = ref(true)

const onRouteChange = (to: RouteLocationNormalized) => {
  showExtra.value = !!to.meta?.showExtra
}
</script>

<script lang="ts">
import { defineComponent } from "vue"


export default defineComponent({
  watch: {
    $route: {
      handler: "onRouteChange",
      flush: "pre",
      immediate: true,
      deep: true,
    },
  },
})
</script>

Aceasta funcționează corect: atunci când introduc un traseu cu meta: {showExtra: false}, ascunde div-ul suplimentar, altfel îl afișează.

Ceea ce vreau să fac, totuși, este să realizez același lucru folosind doar API-ul de compoziție, cu alte cuvinte să elimin complet al doilea tag <script>. Am încercat asta:

<script setup lang="ts">
import type { RouteLocationNormalized } from "vue-router"
import { ref } from "vue"
import { onBeforeRouteUpdate } from "vue-router"


// ...
// same as before
// ...

onBeforeRouteUpdate(onRouteChange)
</script>

Dar acest lucru nu va funcționa așa cum mă aștept atunci când schimb ruta. Sunt conștient de funcția watch pe care aș putea să o import, dar nu sunt sigur cum să obțin informațiile meta despre rută și cum să împac verificatorul de tipuri.

Răspuns #1

Poți să convertești watcher-ul tău la API-ul de compoziție prin importarea metodei watch din vue

<script lang="ts">
import { defineComponent, vue, watch } from "vue"
import { useRoute } from "vue-router"

export default defineComponent({
  setup() {
    const route = useRoute()
    watch(route, (to) => {
      showExtra.value = !!to.meta?.showExtra
    }, {flush: 'pre', immediate: true, deep: true})
  },
})
</script>

Răspunsul #2

Nu am suficiente puncte pentru a comenta, dar răspunsul acceptat de mai sus are totuși o mică diferență în funcționare.

API de Opțiuni:

watch: {
  '$route': {
    handler(oldValue, newValue) => {}
  }
}

API de compoziție:

setup() {
  const route = useRoute();
  watch(route, (newValue, oldValue) => {});
}

În API-ul de compoziție, oldValue va fi doar o clonă a lui newValue (același obiect), în timp ce în API-ul de opțiuni, oldValue va fi de fapt ruta anterioară (util în multe scenarii).