开发过程采坑记录

  • Sorzen
  • 5 Minutes
  • May 3, 2018

起因

最近开发中遇到一些不太常遇到的问题,心血来潮记录一下他们产生的原因,有些问题找了很久才发现问题所在,也给需要的人一些帮助。

问题1:Form表单提交bug

当form表单中只含有一个input输入框时,并且输入框获取焦点然后点击enter时会触发form表单的默认提交事件(input为textarea时不会触发),产生的后果是页面刷新,但是当页面包含两个以上input输入框时不会触发form表单的默认提交。

问题定位过程

当发现这个现象时想到的产生这个现象原因可能是组件自身遗留问题,因为开发采用的是iview,是在使用Tag+Input组件时发现这个bug,因为Input组件使用的enter事件是经过封装之后暴露出来的事件,因此怀疑是组件自身问题,于是使用原生事件去替代,还是会触发表单默认提交动作,后经查阅才发现是form表单中有单个input框造成的原因,之后便对症下药寻找解决之法。

解决方法

一、避免form中有单个input输入框

当页面中无法避免使用单个input输入框时,再添加一个input框并使用v-show=”false”使其隐藏。
这个方法虽然可以很简便解决问题,但是页面中无故多出一些元素,不仅代码不美观而且使代码可读性大大降低,因此不太推荐使用此方法。

二、禁用input的enter事件

为防止input在form表单中无故被提交,因此最好的办法就是禁止🚫enter事件,在页面加载时即mounted()添加form表单阻止事件。

1
2
3
4
5
6
// 阻止表单的默认提交事件,当页面只有一个input并且focus后点击会触发form表单的默认
document.getElementsByTagName('form')[0].addEventListener('keypress', (event) => {
if (event.keyCode === 13 && event.target.tagName !== 'TEXTAREA') {
event.preventDefault();
}
});

三、禁用form中所有的enter事件

利用事件委托原理,直接在父级元素上添加事件,即可使页面中所有input元素禁用enter事件

1
<form @keypress.enter.native="$event.preventDefault()”></form>

缺点:
虽然这个方法可以解决遇到的问题,但是当页面中某些input需要enter事件,会容易形成误伤,因此推荐第二种方法进行分类解决,可以避免误伤的情况。

问题2:vue中父组件对子组件设置v-if属性导致watch不起作用

一、比如 :

1
<add-roles  v-if="flag"  :id="current_id" ></add-roles>

有个函数把flag 设置为true 子组件显示

1
2
3
4
look_role(id) {
this.flag = true;
this.current_id =id;
},

子组件:

1
2
3
4
5
6
props:["id"],
watch:{
'id': function(newVal,oldVal){
console.log("sdfsadf",newVal);
}
},

你会发现根本监听不到 id 的变化
这是因为v-if会影响子组件的生命周期导致watch不起作用

二、原因

我们可以从这两者区别来探讨原因:
v-if 是’真正的’条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建.

v-if 也是惰性的,如果在初始渲染时条件为假,那么什么都不做,直到条件第一次为真的时候才会开始渲染条件块,
相比之下,v-show就简单得多,不管初始条件是什么,元素总会被渲染,并且只是简单的基于css进行切换.

一般来说,v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销.因此,如果需要非常频繁的切换,那么使用v-show好一点;如果在
运行时条件不太可能改变,则使用v-if 好点.

因此当v-if=”false”时,页面并没有渲染此DOM元素,当设置为true时才开始渲染,因此当v-if=’true’时父组件开始渲染子组件,因此子组件不能及时watch父组件传来的值的变化。
当使用v-show时只是在css样式上的显示和隐藏,而DOM元素一直存在于页面中,子组件可以一直监测父组件传递来的值的变化。