程序员踩坑小记录

399 阅读4分钟

个人的踩坑小记录

VUE

1. this.$nextTick

因为vue中的异步DOM渲染机制,Vue实现响应,并不是数据发生变化之后视图立即变化。
在同一事件中,vue观察到数据变化启动渲染的时候,会生成一个队列,把观察到的变化推送到队列里面。
当同一事件重复进行的时候,数据会被缓冲掉,只会被推送一次。
这也是我们有时候遇到的,我的数据明明改变了,为啥dom层却没有什么动静呢。
例如下图

               console1: 0,
               
               console2: 2

2. 浅拷贝,深拷贝,赋值

开发中,避免不了数据的重复使用,当你想声明一个新变量来'继承'你的原有变量,却又不想改变你的原有变量的时候,深拷贝和浅拷贝 就会发生作用。 因为平常的使用中 例如let arr1 = [1,2,3]; let arr2 = arr1; arr2[0] = 2; 这时候 因为引用的指向没有改变,只是单纯的赋值,arr2和arr1 指向统一对象,arr2改变,arr1也会跟着改变。如何避免呢:

 分析一下深拷贝,浅拷贝和赋值的区别:
 浅拷贝(shallowCopy)复制基本类型的属性;引用类型的属性复制,复制栈中的变量 和 变量指向堆内存中的对象的指针,不复制堆内存中的对象。
 深拷贝(deepCopy)是增加了一个指针并且申请了一个新的内存,使这个增加的指针指向这个新的内存,

解释一下:

浅拷贝的结果是和原对象不在指向同一对象,重新对新对象赋值,不会改变原对象的第一层数据,而内部深层的对象是会发生改变的。 深拷贝的结果是和原对象不在指向同一对象,重新对新对象赋值,不会改变第一层数据,也不会改变内部深层数据。

    // 浅拷贝例子
      const obj1 = {
        name: 'haha',
        size: {
          height: 180,
          weight: 120,
        },
        sex: 'male',
      };
      const obj2 = Object.assign({}, obj1);
      obj2.name = 'hehe';
      obj2.size.height = 175;
      obj2.size.height = 150;
      console.log(obj2); 
      console.log(obj1);

打印结果如下:

浅拷贝后 obj2第一层重新赋值的name并没有影响到obj1的name,而obj2的size里面的weight和height重新赋值后,影响到了obj1的size。

    // 深拷贝例子
    const obj1 = {
        name: 'haha',
        size: {
          height: 180,
          weight: 120,
        },
        sex: 'male',
      };
      const obj2 = JSON.parse(JSON.stringify(obj1)); // 深拷贝
      obj2.name = 'hehe';
      obj2.size.height = 175;
      obj2.size.height = 150;
      console.log(obj2);
      console.log(obj1);

打印结果如下:

深拷贝后赋值不会对原对象产生任何影响。

    // 赋值例子
    const obj1 = {
        name: 'haha',
        size: {
          height: 180,
          weight: 120,
        },
        sex: 'male',
      };
      const obj2 = obj1; // 深拷贝
      obj2.name = 'hehe';
      obj2.size.height = 175;
      obj2.size.height = 150;
      console.log(obj2);
      console.log(obj1);

打印结果如下:

赋值会对原对象产生任何影响。

常用的深拷贝的方法: JSON.parse(JSON.stringify());递归函数;

JSON.parse(JSON.stringify()) 不能用于存在function的对象,如果存在,则走正常的递归深拷贝

常用的浅拷贝:Object.assign(); {...}, concat, slice

3.addEventListener 和 removeEventListener

我们在页面中做事件绑定监听的时候,需要用到addEventListener,一般的用法,大家应该都明白。 但是这里面有一个小小的坑,在使用的时候,例如,我们一般window.addEventListener('scroll', () => {}, false), 我们在使用的时候 滚动监听到了全局,如果想要移除绑定,这时候我们在用window.removeEventListener('scroll', () => {}, false); 就会没有效果,因为removeEventListener无法删除addEventListener所追加的事件,因为两个方法并不相等,内存地址已经是不同的,所以,这时候就得给双方添加一个具名函数,使其指向的内存地址不发生改变, 如图,

这样就可以移除绑定了。

click 和 mousedown

有一个需求,如图

这个智能客服需要既可点击,也可拖动到任意位置,因为拖动效果和点击事件绑定到一个元素上,所有这里会有一个问题,PC上发生一次click事件,实际上它是发生了三次事件,mousedown -> mouseup -> click, 这其中的事件发生的三次,如果我们单纯的想实现两个功能在一起,确实是不可能的。这时候我们就要监听他们的触发流程,这里打印一下点击的过程来证明一下:

click 事件是在最后触发的,所以需要我们特殊处理一下事件流程。 一般的方法是 首先是定时器的方法,在你捕获down事件的时候,设定一个flag,设置一个定时器,如果超出一定时间范围,再去进行move的操作,如果在范围内,则进行点击事件。