如何使用 Composition 在 Vue 3 中设置 DOM 元素属性 (ScrollLeft)

问题描述 投票:0回答:2

我正在尝试获取一个可水平滚动的 DOM 元素并设置它的滚动位置。然而,即使我在分配后立即在

console.log()
中输出它的值,该属性似乎也没有更新它的值。

<script setup>
import {ref, watch} from 'vue';

const container = ref();

watch(container, () => {
  console.log(container.value.scrollWidth); // Output: 1500
  console.log(container.value.scrollLeft); // Output: 0
  container.value.scrollLeft = 33;
  console.log(container.value.scrollLeft); // ❌ Output: 0, Expected: 33
})
</script>

<template>
  <div ref="container"></div>
</template>

仅供参考,我使用

watch()
而不是
onMounted()
因为我不知道滚动位置应该是什么,直到我在父组件中进行
fetch()
调用。下面给出了
<script>
部分的完整版本,但是可以将上面的版本扔到 vue playground 中并运行以显示问题。

我已经用谷歌搜索了这九种方法到星期天。我可以找到有关 Vue 2、Vue 3 Options API 或 Vue 3 Composition 的文章。我是 Vue 的新手,只使用过 Vue 3 Composition API。无论哪种方式,所有文章或堆栈溢出问题似乎都是关于使用模板引用访问(读取)DOM 元素,但它们没有显示如何为 DOM 元素属性赋值。就读取属性而言,上面的代码让我了解,但是当我尝试为属性分配一个新值时,该属性没有得到更新。

<script setup lang="ts">
import { ref, watch } from "vue";
import type { ProbeRequest } from "@/types/classes/ProbeRequest";
import type { ProbeRequestStatus } from "@/types/classes/ProbeRequestStatus";
import { buildTracker, getScrollPosition } from "./utils";

interface Props {
  probeRequest: null | ProbeRequest;
}

const props = withDefaults(defineProps<Props>(), { probeRequest: null });
const tracker = ref<(ProbeRequestStatus | string)[]>([]);
const trackerContainer = ref();

watch(
  () => props.probeRequest,
  (probeRequest) => {
    tracker.value = probeRequest ? buildTracker(probeRequest) : [];
    if (tracker.value.length > 0) {
      console.log(trackerContainer.value.scrollWidth);
      console.log(trackerContainer.value.scrollLeft);
      const scrollLeft = getScrollPosition(
        tracker.value,
        trackerContainer.value.scrollWidth
      );
      trackerContainer.value.scrollLeft = scrollLeft;
      console.log(trackerContainer.value.scrollLeft);
    }
  }
);
</script>
vue.js dom vuejs3 vue-composition-api
2个回答
0
投票

这不是 dom 问题,我打赌你的

ref='container'
不可滚动: 更多:https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollLeft


0
投票

所以问题是在第一次渲染时,容器没有溢出,因为没有内容(我在等待

tracker.value
成为一个包含多个元素的数组;那是在等待
props.probeRequest
有一个价值)。这意味着
scrollLeft
必须是
0
。 (值得注意的是,这也是为什么我的人为示例不起作用,因为它永远无法滚动)

一旦容器有了内容,我就需要等待它被渲染,然后才能为

scrollLeft
赋值。所以我不得不添加一个
await nextTick()
(不知道那是一件事)。

代码现在看起来像这样:

<script setup lang="ts">
import { ref, watch, nextTick } from "vue";
import type { ProbeRequest } from "@/types/classes/ProbeRequest";
import type { ProbeRequestStatus } from "@/types/classes/ProbeRequestStatus";
import { buildTracker, getScrollPosition } from "./utils";

interface Props {
  probeRequest: null | ProbeRequest;
}

const props = withDefaults(defineProps<Props>(), { probeRequest: null });
const tracker = ref<(ProbeRequestStatus | string)[]>([]);
const trackerContainer = ref<HTMLInputElement | null>(null);

watch(
  () => props.probeRequest,
  async (probeRequest) => {
    tracker.value = probeRequest ? buildTracker(probeRequest) : [];

    await nextTick() // ✅ Here is the magic sauce

    if (trackerContainer.value && tracker.value.length > 0) {
      console.log(trackerContainer.value.scrollWidth);
      console.log(trackerContainer.value.scrollLeft);
      const scrollLeft = getScrollPosition(
        tracker.value,
        trackerContainer.value.scrollWidth
      );
      trackerContainer.value.scrollLeft = scrollLeft;
      console.log(trackerContainer.value.scrollLeft);
    }
  }
);
</script>

感谢@tachibana-shin 的灵感!

© www.soinside.com 2019 - 2024. All rights reserved.