梗概

Vue请求数据的时机有三种选择:

  • created周期(能更快获取数据)、
  • setup周期(组合式API推荐)、
  • mounted周期(需要访问DOM时使用)。选择依据是否需要DOM访问和渲染优化需求。

详细分析

created 周期请求数据

优势:

  • 能更快获取到服务端数据,减少页面 loading 时间
  • 放在 created 中有助于一致性,因为SSR 服务端渲染 不支持 beforeMount 、mounted 钩子函数
  • 组件实例已创建,data和methods可用

劣势:

  • 会阻塞渲染
  • 无法访问DOM元素(此时还未挂载)
export default {
  data() {
    return {
      userInfo: null
    }
  },
  created() {
    // 推荐:不需要DOM的数据请求
    this.fetchUserInfo();
  },
  methods: {
    async fetchUserInfo() {
      this.userInfo = await api.getUserInfo();
    }
  }
}

setup 周期请求数据

组合式API的推荐方式

setup函数在created之前执行,相当于created和beforeCreate的结合:

import { ref, onMounted } from 'vue'
 
export default {
  setup() {
    const userInfo = ref(null)
    
    // 立即执行的数据请求(等同于created)
    const fetchUserInfo = async () => {
      userInfo.value = await api.getUserInfo()
    }
    
    // 组件创建时请求数据
    fetchUserInfo()
    
    return {
      userInfo
    }
  }
}

setup中的异步请求处理:

setup() {
  const data = ref(null)
  const loading = ref(true)
  
  // 使用立即执行的异步函数
  ;(async () => {
    try {
      data.value = await fetchData()
    } finally {
      loading.value = false
    }
  })()
  
  return { data, loading }
}

mounted 周期请求数据

适用场景:需要访问DOM信息

  • 想要缩短白屏时间,避免请求数据阻塞渲染
  • 需要根据DOM尺寸、位置等信息来请求数据
  • 需要初始化第三方库后再请求数据

劣势:

  • 会导致回流
  • 数据获取较晚,可能出现页面闪烁
export default {
  mounted() {
    // 需要DOM信息的数据请求
    const containerHeight = this.$refs.container.offsetHeight;
    this.fetchDataByHeight(containerHeight);
    
    // 初始化图表后请求数据
    this.initChart();
    this.fetchChartData();
  }
}

实际应用建议

Vue 3 组合式API最佳实践

import { ref, onMounted, nextTick } from 'vue'
 
export default {
  setup() {
    const data = ref([])
    const chartRef = ref(null)
    
    // 基础数据请求 - 立即执行
    const fetchBaseData = async () => {
      data.value = await api.getBaseData()
    }
    fetchBaseData()
    
    // 需要DOM的数据请求 - mounted后执行
    const fetchChartData = async () => {
      await nextTick() // 确保DOM更新完成
      const chartWidth = chartRef.value.offsetWidth
      const chartData = await api.getChartData(chartWidth)
      // 渲染图表
    }
    
    onMounted(() => {
      fetchChartData()
    })
    
    return {
      data,
      chartRef
    }
  }
}

选择建议

  • 纯数据请求:使用 createdsetup 中的立即执行
  • 需要DOM信息:使用 mounted 周期
  • SSR项目:优先使用 createdsetup
  • 性能敏感:根据具体需求在加载速度和渲染阻塞间权衡
  • 组合式API:优先在 setup 中处理,配合 onMounted 处理DOM相关请求