Vue性能优化之created 生命周期钩子深入分析

JavaScript性能优化实战 10w+人浏览 423人参与

一、核心定位:组件生命周期的“黄金初始化时机”

created 钩子在 Vue 组件实例被完全创建后同步调用。您可以将其理解为组件​“肉身”已经构造完成,但还未“挂载”到 DOM 上的关键时刻

为了更直观地理解它在整个组件生命周期中的位置,请先参看下图:

从上图可以清晰地看到,created 发生在响应式数据初始化之后,DOM 挂载之前。这个时机点的特性决定了它的核心用途和局限性。


二、深度原理:在初始化链条中的关键作用

要理解 created,必须了解 Vue 实例的完整初始化流程。下图展示了 created 钩子在整个组件初始化流程中的关键作用:

关键解读:​
Init State 阶段,Vue 完成了以下关键操作,这正是 created 中能访问到响应式数据的原因:

  • data 对象变为响应式,并代理到实例上(this.xxx 访问)。
  • 处理 propsmethodscomputedwatch 等选项。
  • 正是这些工作的完成,使得 created 成为第一个可以安全操作数据的生命周期钩子。

三、created 的核心职责与最佳实践

基于其“数据已就绪,DOM 未生成”的特性,created 钩子最适合完成以下几类任务:

1. 异步数据获取(首屏优化)

这是 created 最经典的用途。为了尽快减少用户白屏时间,应尽早发起异步请求。

export default {
  data() {
    return {
      userInfo: null,
      productList: []
    };
  },
  async created() {
    // 并行发起多个异步请求,优化首屏加载
    try {
      const [userResponse, productsResponse] = await Promise.all([
        this.$api.getUserInfo(),
        this.$api.getProducts()
      ]);
      
      this.userInfo = userResponse.data;
      this.productList = productsResponse.data;
      
    } catch (error) {
      console.error('数据获取失败:', error);
    }
  }
};

为什么不在 mounted 中获取?​

  • 更早触发​:createdmounted 执行得更早,能更早获取数据,缩短首屏时间。
  • DOM 非必需​:数据获取是逻辑操作,不依赖 DOM。在 mounted 中获取会无谓地延迟请求。
2. 初始化组件状态与监听事件
export default {
  created() {
    // 基于 props 初始化内部状态
    this.internalValue = this.value || this.defaultValue;
    
    // 初始化非响应式数据(避免不必要的响应式开销)
    this.staticConfig = Object.freeze({ MAX_COUNT: 100 });
    
    // 监听全局事件总线
    this.$eventBus.$on('global-event', this.handleGlobalEvent);
  },
  beforeUnmount() {
    // 必须在组件销毁时移除监听,防止内存泄漏!
    this.$eventBus.$off('global-event', this.handleGlobalEvent);
  }
};
3. 执行一次性的计算或设置
export default {
  created() {
    // 执行一次性的计算,结果缓存到数据中
    this.initialHash = this.calculateInitialHash(this.initialData);
    
    // 设置定时器
    this.autoSaveTimer = setInterval(this.autoSave, 30000);
  },
  beforeUnmount() {
    // 必须清理定时器!
    clearInterval(this.autoSaveTimer);
  }
};

四、组合式 API 中的对应物:setup()

在 Vue 3 的组合式 API 中,created 钩子没有直接的等价物,因为它的逻辑被整合到了 setup() 函数中。

心智模型转换:​

  • 选项式 API​:created 是一个特定的“时间点”。
  • 组合式 API​:setup() 中顶层的同步代码就是 created 的逻辑。
// 选项式 API
export default {
  data() { return { count: 0 }; },
  created() {
    console.log('created:', this.count); // 0
    this.fetchData();
  }
};

// 组合式 API
import { ref, onMounted } from 'vue';

export default {
  setup() {
    const count = ref(0);
    
    // 这里的同步代码相当于 created
    console.log('setup同步代码:', count.value); // 0
    fetchData(); // 相当于在 created 中调用
    
    // 如果需要 mounted 的逻辑,要显式使用 onMounted
    onMounted(() => {
      console.log('mounted');
    });
    
    return { count };
  }
};

五、专家级注意事项与性能优化

1. 内存泄漏风险

created 中创建的监听器、定时器、事件监听等必须beforeUnmount/unmounted 中清理。

export default {
  created() {
    this.intervalId = setInterval(() => {}, 1000);
    window.addEventListener('resize', this.handleResize);
  },
  beforeUnmount() {
    clearInterval(this.intervalId);
    window.removeEventListener('resize', this.handleResize);
  }
};
2. 异步操作与组件卸载的竞争条件

如果组件在数据返回前被销毁,异步回调中设置数据会导致内存泄漏。

export default {
  data() { return { data: null }; },
  created() {
    let isMounted = true; // 标志位
    
    this.$api.getData().then(result => {
      if (isMounted) { // 检查组件是否仍挂载
        this.data = result;
      }
    });
    
    this.$once('hook:beforeUnmount', () => {
      isMounted = false; // 组件卸载时标记为 false
    });
  }
};
3. 避免阻塞渲染

created 是同步执行的,如果其中有繁重的同步计算,会阻塞组件的渲染进程。

// ❌ 避免:繁重同步计算
created() {
  // 这会阻塞组件渲染
  this.heavyData = this.calculateHeavyStuff(); 
}

// ✅ 推荐:使用计算属性(惰性求值)或异步处理
computed: {
  heavyData() { return this.calculateHeavyStuff(); }
}
// 或
async created() {
  // 使用 requestIdleCallback 或拆分为小任务
  this.heavyData = await this.calculateAsync();
}

总结:created 的专家级理解

维度深度分析
定位数据响应式初始化完成,DOM 未生成的“黄金初始化时机”
核心用途异步数据获取、事件监听、一次性初始化、状态设置
优势mounted 更早,适合不依赖 DOM 的逻辑,优化首屏
局限无法操作 DOM,异步回调需处理组件销毁的竞争条件
组合式 API被整合到 setup() 函数的同步执行部分
性能关键避免同步阻塞,及时清理副作用防止内存泄漏

        将 created 视为组件的“数据准备阶段”。在这个阶段完成所有不依赖 DOM 的初始化工作,为后续的渲染和交互打下坚实基础。理解其在 Vue 初始化流程中的精确位置,能帮助您写出更高效、更健壮的 Vue 应用。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值