vue.js - Vue2点击事件为什么要点击两次才生效?

查看:4388
本文介绍了vue.js - Vue2点击事件为什么要点击两次才生效?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问 题

有一个button,效果是点击后出现日期选择控件,可是为啥我需要点击两次button才能出来日期控件呢?求大神解疑。。控件是jquery的datetimepicker时间控件

下面是官方手册里那个列表渲染的例子我改了一下

HTML:

<div id="todo-list-example">
          <input
            v-model="newTodoText"
            v-on:keyup.enter="addNewTodo"
            placeholder="Add a todo"
          >
          <ul>
            <li
              is="todo-item"
              v-for="(todo, index) in todos"
              v-bind:title="todo"
            ></li>
          </ul>
        </div>

JS:

Vue.component('todo-item', {
      template: '\
        <li>\
          {{ title }}\
          <button v-on:click="selectDate($event)">X</button>\
        </li>\
      ',
      props: ['title'],
      methods: {
        selectDate: function(e){
            // alert(111);如果换成alert点一次即能生效
            this.$emit($(e.target).datetimepicker());
        }
      },
    });
    new Vue({
      el: '#todo-list-example',
      data: {
        newTodoText: '',
        todos: [
          'Do the dishes',
          'Take out the trash',
          'Mow the lawn'
        ]
      },
      methods: {
        addNewTodo: function () {
          this.todos.push(this.newTodoText)
          this.newTodoText = ''
        }
      }
    });

给我的感觉是点击第一次在初始化,点击第二次才生效?怎么一次生效呢?

解决方案

先谢过各位热心大神的回答...给了我很多思路,然而并没解决我的问题

这个问题我自己解决了,昨天才开始看Vue,新人一枚,谈谈我的思路。
首先感谢各位大神的热心解答。
一开始出现这个问题的时候,我在想是不是不能像过去写Jquery一样直接在<script></script>中绑定该控件?

$(document).on('click','#datetimepicker',function(){
    ....
})

难道像上面这样是绑不上的?于是我就在Vue实例中写了一个selectDate方法,点击按钮即触发它,然后再执行绑定。

selectDate: function(){
    $(document).on('click','#datetimepicker',function(){
        ...
    })
}

用这种方式的确能实现了,点击该元素后出现了日期控件。可是问题来了,怎么还需要点击两次?这谁受得了,不知道的还以为点了没反应呢。于是开始各种找问题,上百度搜了个遍,又来segament提问。

无奈开始找bug,怀疑是不是jquery和vue不兼容啊,然后把vue引用删了,的确好使。。。这就尴尬了,看来是Vue影响了控件的正常使用,可我还想用Vue啊,那只能继续翻Vue手册了。

然后猜想有可能是我点击后控件才开始初始化,所以点击第二次才生效?我一直确信应该是这么个情况,所以我就研究在哪里能提前把它初始化了或者说与元素绑定了。
于是看到了Vue的生命周期,Created、Updated、Mounted,全试了一个遍,发现的确是生命周期的问题,但只有Updated有效果,在Updated中绑定元素的话点击一次即可生效,到这里已经解决了我的问题,但是!Updated是数据有任何变化时候都会更新,也就是说假设打十个字,里面的函数会执行10次(可以console.log(123)看一下,确实执行了10遍),官方在手册中也提及了注意事项:

由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子。
当这个钩子被调用时,组件 DOM 已经更新,所以你现在可以执行依赖于 DOM的操作。然而在大多数情况下,你应该避免在此期间更改状态,因为这可能会导致更新无限循环。

对于我这个小网页来说对性能其实影响不大,但这肯定不是我想要的结果。所以我继续看看Vue手册中还有没有类似我这种情况的案例。
Updated 不行,我又想到了$on和$emit,是Vue自带的事件监听和执行方法,试了一下,效果和之前selecDate方法的效果是一样的没卵用。

这问题已经困扰我两天了,想到最后,觉得这个问题归根到底还是和DOM的出现时间点也就是Vue的生命周期有关系,不管Vue怎么处理DOM,肯定是datetimepicker一定要挂载到DOM出现后才能生效,还是翻文档,偶然间看到生命周期里还有一个$nextTick方法。

用法参考Vue异步更新队列,它是这么说的:

将回调延迟到下次 DOM 更新循环之后执行。在修改数据之后立即使用它,然后等待 DOM 更新。它跟全局方法 Vue.nextTick 一样,不同的是回调的 this 自动绑定到调用它的实例上。

简单理解就是DOM更新完后执行回调,于是我调用这个方法,然后在这个回调里执行datetimepicker,由于DOM已经被加载到了网页,所以也不需要绑定了,直接执行即可,果然得到了预期的效果。

事后我觉得费这么大劲虽然解决了这个问题,但是我的思路应该还是不对,起码和Vue数据驱动、虚拟DOM的思想不契合,到现在我还没转变过来,日后等转变了再来谈谈这个问题吧。

这篇关于vue.js - Vue2点击事件为什么要点击两次才生效?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆