hook/once

  • 在Vue组件中,可以用过$on,$once去监听所有的生命周期钩子函数
  • 如监听组件的updated钩子函数可以写成 this.$on('hook:updated', () => {})

监听组件生命周期

  • hookEvent
export default {
  mounted() {
    this.chart = echarts.init(this.$el)
    // 请求数据,赋值数据 等等一系列操作...

    // 监听窗口发生变化,resize组件
    window.addEventListener('resize', this.$_handleResizeChart)
    // 通过hook监听组件销毁钩子函数,并取消监听事件
    this.$once('hook:beforeDestroy', () => {
      window.removeEventListener('resize', this.$_handleResizeChart)
    })
  },
  updated() {},
  created() {},
  methods: {
    $_handleResizeChart() {
      // this.chart.resize()
    }
  }
}

<template>
  <!--通过@hook:updated监听组件的updated生命钩子函数-->
  <!--组件的所有生命周期钩子都可以通过@hook:钩子函数名 来监听触发-->
  <custom-select @hook:updated="$_handleSelectUpdated" />
</template>
<script>
import CustomSelect from '../components/custom-select'
export default {
  components: {
    CustomSelect
  },
  methods: {
    $_handleSelectUpdated() {
      console.log('custom-select组件的updated钩子函数被触发')
    }
  }
}
</script>

处理组件内定时器的步骤。通常我们一般都是这样操作的:

<script>
  export default {
    mounted() {
      this.timer = setInterval(() => { ... }, 1000);
    },
    beforeDestroy() {
      clearInterval(this.timer);
    }
  };
</script>
<script>
  export default {
    mounted() {
      const timer = setInterval(() => { ... }, 1000);
      this.$once('hook:beforeDestroy', () => clearInterval(timer);)
    }
  };
</script>

设想一个场景

  • 如果我们需要在数据渲染到页面的之前让页面 loadingmounted 之后停止 loadingbeforeUpdata 时开始 loadingupdatad 之后停止 loading
  • 最简单的方法就是改写组件的生命周期函数,使其在 mounted/beforeUpdata /updatad 时通知父组件显示或者隐藏 loading
  • 这样做显示不好,因为侵入了自组件的逻辑,增加的逻辑也和组件本身的功能好不关联。最好的办法就是使用 v-on="hook:xxx"的方式:
<v-chart
    @hook:mounted="loading = false"
    @hook:beforeUpdated="loading = true"
    @hook:updated="loading = false"
    :data="data"
/>

这样,就实现了对子组件生命周期的监听。对任意的组件都有效果,包括引入的第三方组件。

v-once

只渲染元素和组件一次。随后的重新渲染,元素/组件及其所有的子节点将被视为静态内容并跳过。这可以用于优化更新性能。

对于部分在首次渲染后就不会再有响应式变化的元素,可以用v-once属性去标记,如下:

<el-select>
  <el-option
    v-for="item in options"
    v-once
    :key="item.value"
    :label="item.label"
    :value="item.value"
    >{{i}}</el-option
  >
</el-select>
 

如果上述例子中的变量options很大且不会再有响应式变化,那么如例子中用上v-once对性能有提升。