Countups.js相关问题?

<script setup lang="ts">
import UserCommodityInfo from "@/store/home/commodity/Info.ts";
import { storeToRefs } from "pinia";
import CardChild from './CardChild/index.vue'

import { ref, onMounted } from "vue";
import { CountUp } from "countUp.js";
// 拿到服务器商品信息的数据
const UserCommodityInfos = UserCommodityInfo();
UserCommodityInfos.getReqCommodityInfo();
const { Reqdata } = storeToRefs(UserCommodityInfos);

let Count = ref<HTMLElement>();



onMounted(() => {
  // 创建CountUp实例
  const Countups = new CountUp(Count.value!, 1000);
  console.log(Count.value);
  
  // 开始执行
  Countups.start();

});

</script>

<template>
  <el-row justify="space-between" :gutter="10">
    <template v-for="item in Reqdata" :key="item.amount">
      <el-col :span="6">
       <CardChild v-bind="item"></CardChild>
       <span ref="Count">0</span>
      </el-col>
    </template>
  </el-row>
</template>

<style scoped lang="less">

</style>

当span被包裹在el-col 中时代码中拿到的Count实例是undefined,如果将他抽成一个组件(CardChild)就不会出现拿不到实例对象(看上面代码)

CardChild组件:

<script setup lang="ts">
import { ref, onMounted } from "vue";
import { CountUp } from "countUp.js";

const prop = defineProps({
  title: {
    type: String,
  },
  tips: {
    type: String,
  },
  number1: {
    type: Number,
  },
  number2: {
    type: Number,
  },
  subtitle: {
    type: String,
  },
});
// ******变量******
// 获取需要执行CountUp的组件实例
let Count1 = ref<HTMLElement>();
let Count2 = ref<HTMLElement>();


onMounted(() => {
  // 创建CountUp实例
  const Countup1 = new CountUp(Count1.value!, prop.number1 ?? 0);
  const Countup2 = new CountUp(Count2.value!, prop.number2 ?? 0);
  // 开始执行
  Countup1.start();
  Countup2.start()
});

</script>

<template>
  <div class="card">
    <div class="head">
      <h2>{{ title }}</h2>
      <el-tooltip class="box-item" effect="light" :content="tips" placement="top">
        <el-icon><Warning /></el-icon>
      </el-tooltip>
    </div>
    <div class="conter">
      <span ref="Count1">{{ number1 }}</span>
    </div>
    <div class="footer">
      <h4 >{{ subtitle }} <span ref="Count2">{{ number2 }}</span></h4>
    </div>
  </div>
</template>
阅读 358
avatarAI BotBETA

问题的根源在于,你在父组件中使用ref来尝试引用模板中的<span>元素,但是ref是在循环v-for中使用的,这会导致ref指向不确定的元素,或者可能根本指向不到任何元素。在Vue 3中,使用ref在循环中引用DOM元素是不推荐的,并且可能不会按预期工作。

对于你提到的情况,如果你将<span>抽离成CardChild组件,并且在这个组件内部使用refonMounted来初始化CountUp,那么每个CardChild实例都会有它自己的refCountUp实例,因此不会出现undefined的问题。

然而,如果你希望在父组件中管理所有的CountUp实例,那么你需要找到一种方式来为每个<span>创建一个唯一的ref。你可以使用Vue 3的v-for:ref的绑定语法,但这需要一些额外的逻辑来管理这些ref

另外,请注意,CountUp库是用来在DOM元素上执行数字动画的,所以你需要确保在DOM元素可用时初始化它。如果元素在初始化CountUp时不可用(比如因为v-if条件未满足或者仍在等待异步数据),那么CountUp实例可能会是undefined或者无法正常工作。

对于你的代码,一个可能的解决方案是在CardChild组件内部管理CountUp的初始化,这样每个组件实例都可以独立处理其数字动画。如果你确实需要在父组件中管理这些实例,你可能需要重构代码以使用更复杂的逻辑来跟踪和初始化每个CountUp实例。

总之,你遇到的问题是因为在循环中使用了ref,并且可能没有在DOM元素可用时初始化CountUp。你应该确保在适当的时机和上下文中初始化你的CountUp实例。

1 个回答

你在父组件中循环v-for使用ref(count)来引用元素,ref会有多个同名实例存在;
你抽取组件 每个子组件实例都会有它自己的ref实例,互不干扰 所以正常显示;

推荐问题
logo
Microsoft
子站问答
访问
宣传栏