美文网首页vue2 世界
052_末晨曦Vue技术_处理边界情况之程序化的事件侦听器

052_末晨曦Vue技术_处理边界情况之程序化的事件侦听器

作者: 前端末晨曦吖 | 来源:发表于2022-08-19 08:58 被阅读0次

    程序化的事件侦听器

    点击打开视频讲解更详细

    现在,你已经知道了 $emit 的用法,它可以被 v-on 侦听,但是 Vue 实例同时在其事件接口中提供了其它的方法。我们可以:

    • 通过 $on(eventName, eventHandler) 侦听一个事件
    • 通过 $once(eventName, eventHandler) 一次性侦听一个事件
    • 通过 $off(eventName, eventHandler) 停止侦听一个事件

    你通常不会用到这些,但是当你需要在一个组件实例上手动侦听事件时,它们是派得上用场的。它们也可以用于代码组织工具。例如,你可能经常看到这种集成一个第三方库的模式:

    // 一次性将这个日期选择器附加到一个输入框上
    // 它会被挂载到 DOM 上。
    mounted: function () {
      // Pikaday 是一个第三方日期选择器的库
      this.picker = new Pikaday({
        field: this.$refs.input,
        format: 'YYYY-MM-DD'
      })
    },
    // 在组件被销毁之前,
    // 也销毁这个日期选择器。
    beforeDestroy: function () {
      this.picker.destroy()
    }
    

    这里有两个潜在的问题:

    • 它需要在这个组件实例中保存这个 picker,如果可以的话最好只有生命周期钩子可以访问到它。这并不算严重的问题,但是它可以被视为杂物。
    • 我们的建立代码独立于我们的清理代码,这使得我们比较难于程序化地清理我们建立的所有东西。

    你应该通过一个程序化的侦听器解决这两个问题:

    mounted: function () {
      var picker = new Pikaday({
        field: this.$refs.input,
        format: 'YYYY-MM-DD'
      })
    
      this.$once('hook:beforeDestroy', function () {
        picker.destroy()
      })
    }
    

    使用了这个策略,我甚至可以让多个输入框元素同时使用不同的 Pikaday,每个新的实例都程序化地在后期清理它自己:

    mounted: function () {
      this.attachDatepicker('startDateInput')
      this.attachDatepicker('endDateInput')
    },
    methods: {
      attachDatepicker: function (refName) {
        var picker = new Pikaday({
          field: this.$refs[refName],
          format: 'YYYY-MM-DD'
        })
    
        this.$once('hook:beforeDestroy', function () {
          picker.destroy()
        })
      }
    }
    

    注意,即便如此,如果你发现自己不得不在单个组件里做很多建立和清理的工作,最好的方式通常还是创建更多的模块化组件。在这个例子中,我们推荐创建一个可复用的 <input-datepicker> 组件。

    完整案例:

    <template>
      <div id="app">
        <!-- 比如,在页面挂载时定义计时器,需要在页面销毁时清除定时器。这看起来没什么问题。但仔细一看 this.timer 
        唯一的作用只是为了能够在beforeDestroy 内取到计时器序号,除此之外没有任何用处。 -->
      </div>
    </template>
    
    <script>
    export default {
      name: 'App',
      data(){
        return {
          timer:''
        } 
      },
      mounted() {
        // this.timer
        // 如果可以的话最好只有生命周期钩子可以访问到它。这并不算严重的问题,但是它可以被视为杂物。
        // 我们可以通过 $on 或 $once 监听页面生命周期销毁来解决这个问题
    
        // this.timer = setInterval(() => {
        //   console.log(Date.now())
        // }, 1000)
    
        this.creatInterval('hello')  //在mounted中创建多个生命周期函数。
        this.creatInterval('world')  //即使我们同时创建多个计时器,也不影响效果。因为它们会在页面销毁后程序化的自主清除。
    
      },
      // beforeDestroy() {
      //   clearInterval(this.timer)
      // },
      methods:{
        creatInterval(msg) {
            let timer = setInterval(() => {
                console.log(msg)
            }, 1000)
            this.$once('hook:beforeDestroy', function() {
                clearInterval(timer)
            })
        }
      }
    }
    </script>
    
    <style scoped>
     
    </style>
    

    相关文章

      网友评论

        本文标题:052_末晨曦Vue技术_处理边界情况之程序化的事件侦听器

        本文链接:https://www.haomeiwen.com/subject/avvegrtx.html