Vue 元素显示后滚动到视图中

Vue scroll element into view after it is shown

我有一个表格可以计算 2 个值,然后显示结果卡。在所有值填写并提交之前,结果卡将不会显示(使用v-if)。

我正在为 UI 框架使用 Vuetify。

这是我尝试过的:

<template>
  <v-container>
    <v-row class="mt-2" justify="center">
      <v-col cols="12" sm="8" md="6">
        <v-form ref="form" @submit.prevent="onSubmit">
          <v-row class="mb-1">
            <v-col cols="6">
        
              <v-select
                v-model="fighter1"
                :items="fighters"
                item-text="name"
                item-value="id"
                return-object
                label="Player 1"
                :rules="[(v) => !!v || 'Required.']"
              />
            </v-col>

            <v-col cols="6">
  
              <v-select
                v-model="fighter2"
                :items="fighters"
                item-text="name"
                item-value="id"
                return-object
                label="Player 2"
                :rules="[(v) => !!v || 'Required.']"
              />
            </v-col>
          </v-row>

          <!-- This is the submit button -->
          <ReadyToFight />
        </v-form>
      </v-col>
    </v-row>

    <v-row>
      <v-col>

        <!-- This is the result card -->
        <v-card v-if="result" id="result" class="pb-2">
          <h1 class="text-center text-uppercase result-score">{{ result }}</h1>
          <h2 class="text-center text-uppercase result-text">
            {{ resultText }}
          </h2>
        </v-card>
      </v-col>
    </v-row>
  </v-container>
</template>

<script lang="ts">
import { Fighter, fighters } from '@/data/fighters'
import matchupsChart from '@/data/matchups'
import Vue from 'vue'
import { MatchupTypes, toResult } from '~/data/matchupTypes'

type IndexPageType = {
  fighters: Fighter[]
  fighter1: Fighter | undefined
  fighter2: Fighter | undefined
  result: MatchupTypes | undefined
}

export default Vue.extend({
  name: 'IndexPage',
  data(): IndexPageType {
    return {
      fighters,
      fighter1: undefined,
      fighter2: undefined,
      result: undefined
    }
  },
  computed: {
    resultText(): string {
      if (this.result) return toResult(this.result)
      return `Can't get result`
    }
  },
  
  // I tried watching the result
  // So after the result changed it will scroll
  watch: {
    result(newResult) {
      if (newResult) document.querySelector('#result')?.scrollIntoView()
    }
  },
  methods: {
    onSubmit() {
      ;(this.$refs.form as any).validate()
      if (this.fighter1 && this.fighter2) {
        this.result = matchupsChart
          .get(this.fighter1.id)
          ?.get(this.fighter2.id) as MatchupTypes
      }
    }
  }
})
</script>

基本上我尝试做的是:
观察 result,如果它变为 truthy,则 scrollIntoView()

但这行不通,因为我认为 result 首先发生变化,然后才呈现元素。

有人知道我应该怎么做吗?

这是因为元素 #result 尚未在实际 DOM 中呈现,此时观察者已被解雇。您将需要等待 this.$nextTick() 以确保 DOM 确实已更新,然后再尝试将元素滚动到视图中,即:

watch: {
    result(newResult) {
        if (newResult) {
            this.$nextTick().then(() => document.querySelector('#result')?.scrollIntoView());
        }
    }
},

如果你熟悉async/await,你也可以这样做:

watch: {
    async result(newResult) {
        if (newResult) {
            await this.$nextTick();
            document.querySelector('#result')?.scrollIntoView();
        }
    }
},