Vue 生命周期钩子与方法的选择:mounted 与 methods

生命周期 mounted vs 方法 如何选择

1. 时机控制问题

methods 中的方法需要手动调用,而 mounted 是自动执行的特定时机。

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

<script>
export default {
  data() {
    return {
      chart: null
    };
  },
  
  // 错误示例:在 methods 中初始化 DOM 操作
  methods: {
    initChart() {
      // 问题1:什么时候调用这个方法?
      // 问题2:如果调用时 DOM 还没渲染怎么办?
      this.chart = echarts.init(this.$refs.chart); // 可能报错
    }
  },
  
  // 正确示例:在 mounted 中自动执行
  mounted() {
    // 确保此时 DOM 已经渲染完成
    this.chart = echarts.init(this.$refs.chart);
    this.chart.setOption({/*...*/});
  }
}
</script>

2. DOM 可用性保证

<script>
export default {
  methods: {
    // 这个方法可能在 DOM 渲染前被调用
    focusInput() {
      this.$refs.myInput.focus(); // 可能为 undefined
    },
    
    // 这个方法可能在 DOM 渲染后被调用
    safeFocusInput() {
      // 需要先检查 DOM 是否存在
      if (this.$refs.myInput) {
        this.$refs.myInput.focus();
      } else {
        console.warn('DOM 还未准备好');
      }
    }
  },
  
  created() {
    // 在 created 阶段调用方法
    this.focusInput(); // 会报错
  },
  
  mounted() {
    // 在 mounted 阶段调用,安全
    this.$refs.myInput.focus(); //  安全
  }
}
</script>

3. 实际场景对比

场景:初始化一个图表库

<script>
// 错误做法:依赖 methods
export default {
  methods: {
    initECharts() {
      // 问题:这个方法需要在多个地方调用
      const chart = echarts.init(this.$el);
      chart.setOption(this.options);
      
      // 还需要监听窗口变化
      window.addEventListener('resize', () => {
        chart.resize();
      });
      
      // 还需要在组件销毁时清理
      this.$once('hook:beforeDestroy', () => {
        window.removeEventListener('resize', chart.resize);
        chart.dispose();
      });
    }
  },
  
  created() {
    // 不能在这里调用,DOM 不存在
    // this.initECharts(); // 报错
  },
  
  // 需要在模板中调用?
  mounted() {
    // 还是要在这里调用
    this.initECharts(); // 那为什么不在 mounted 里直接写
  }
};
</script>

正确做法:使用 mounted

<script>
export default {
  data() {
    return {
      chart: null
    };
  },
  
  mounted() {
    // 一次性初始化,逻辑集中
    this.chart = echarts.init(this.$el);
    this.chart.setOption(this.options);
    
    // 事件监听
    this.handleResize = () => this.chart.resize();
    window.addEventListener('resize', this.handleResize);
  },
  
  beforeDestroy() {
    // 集中清理
    window.removeEventListener('resize', this.handleResize);
    if (this.chart) {
      this.chart.dispose();
    }
  }
};
</script>

4. 为什么不在 methods 里随意调用的原因

原因说明示例
时机不确定性不知道什么时候 DOM 准备好了可能在 created 中调用,但 DOM 未渲染
重复执行风险可能被多次调用导致重复初始化图表被重复初始化,事件重复绑定
逻辑分散初始化和清理逻辑分散在不同地方初始化在 methods,清理在 beforeDestroy
生命周期关联有些操作需要精确的生命周期时机只在组件挂载时执行一次的操作

5. 什么情况下应该在 methods 中执行

并不是所有操作都不应该在 methods 中,以下情况适合:

<script>
export default {
  mounted() {
    // 初始加载数据
    this.loadData();
    
    // 初始化第三方库
    this.map = new AMap.Map('map');
  },
  
  methods: {
    // 适合在 methods 中:用户交互触发
    handleClick() {
      this.loadData(); // 重新加载数据
    },
    
    // 适合在 methods 中:可重复调用的操作
    loadData() {
      axios.get('/api/data').then(res => {
        this.data = res.data;
      });
    },
    
    // 适合在 methods 中:更新已存在的实例
    updateMap() {
      if (this.map) {
        this.map.setCenter([116.39, 39.9]);
      }
    }
  }
};
</script>

最佳原则

1. 初始化操作放在 mounted

mounted() {
  // DOM 相关初始化
  this.initThirdPartyLibrary();
  
  // 一次性的事件监听
  window.addEventListener('resize', this.handleResize);
  
  // 获取初始数据(如果需要 DOM)
  if (this.needDOM) {
    this.fetchInitialData();
  }
}

2. 可复用的逻辑放在 methods

methods: {
  // 可以被多次调用的方法
  fetchData(params) {
    return axios.get('/api/data', { params });
  },
  
  // 用户交互触发的方法
  handleUserAction() {
    // ...
  }
}

3. 清理操作放在 beforeDestroy

beforeDestroy() {
  // 清理事件监听
  window.removeEventListener('resize', this.handleResize);
  
  // 销毁第三方库实例
  if (this.chart) {
    this.chart.dispose();
  }
}

总结

关键区别:

  • mounted自动执行于特定生命周期,保证 DOM 已存在

  • methods手动调用,调用时机不确定

简单记忆:

  • 如果操作依赖 DOM → 用 mounted

  • 如果操作需要执行一次在组件挂载时 → 用 mounted

  • 如果操作由用户交互触发需要重复调用 → 用 methods

  • 如果操作既要在初始化执行又要能重复执行 → mounted 中调用 methods 的方法

<script>
export default {
  mounted() {
    // 初始化:保证只执行一次,DOM 已存在
    this.init();
  },
  
  methods: {
    // 可复用:既能被 mounted 调用,也能被其他方法调用
    init() {
      // 初始化逻辑
    },
    
    // 用户交互:由事件触发
    handleClick() {
      // 处理点击
    }
  }
};
</script>

所以,之所以选择 mounted 而不是在 methods 里随意调用,主要是为了确保正确的执行时机代码的组织清晰性

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值