第三期:前端九条bug分享

本期

由于须要写这方面的文章, 致使我如今工做中很期待有趣bug的出现, 看到测试给我提bug还有点高兴...css

1:element-ui的form表单组件敲'Enter'默认刷新页面

bug现象:
如题所说, 咱们须要作的无非是禁掉默认的提交事件, element自己没有禁用提交属性, 下面是一块有bug的代码.html

<template>
<el-form ref="form" :model="form" label-width="80px">
  <el-form-item label="活动名称">
    <el-input v-model="form.name"></el-input>
  </el-form-item>
  <el-form-item>
    <el-button type="primary" @click="onSubmit">当即建立</el-button>
    <el-button>取消</el-button>
  </el-form-item>
</el-form>
</template>

<script>
  export default {
    data() {
      return {
        form: {
          name: '',
        }
      }
    },
    methods: {
      onSubmit() {
        console.log('submit!');
      }
    }
  }
</script>

解决方式:
在form层多了个onsubmit="return false;"
<el-form ref="form" :model="form" label-width="80px" onsubmit="return false;">前端

更好的解决方式:
这种默认提交功能项目中基本不会使用了, 因此基本是要禁止掉的, 咱们若是全局有5个form表单就要改5个地方, 因此程序员确定会想要作一个公共的处理方式, 第一时间想到的就是二次封装, 可是虽然二次封装, 我仍然但愿这个组件叫el-form, 那么会遇到什么问题那?vue

  1. 必须还叫 <el-form>
  2. 我按需引入的element-ui组件, 那么我不把它的form组件放在全局定义
  3. 我是直接彻底引入的element-ui组件, 我不想换成按需引入
  4. 避免循环引入的bug

main.js代码以下:node

import Vue from 'vue';
import App from './App.vue';
import ElementUI from 'element-ui';
import Form from './components/form.vue';
import 'element-ui/lib/theme-chalk/index.css';

// 这里咱们不改变本来的组件定义, 这里定义组件并非当即渲染, 因此能够被顶掉.
Vue.use(ElementUI);
// 这里使用咱们本身的组件, 名字仍是使用element-ui本来的名字.
Vue.component(ElementUI.Form.name, Form);

new Vue({
  render: h => h(App),
}).$mount('#app')

./components/form.vue里面咱们仅需包裹一下:python

<template>
  <x-form onsubmit="return false;"  v-bind="$attrs" v-on="$listeners" >
    <slot />
  </x-form>
</template>

<script>
import { Form } from "element-ui";

export default {
  components: {
    XForm: Form
  }
};
</script>

上面要注意, 之因此我起名为XForm就是要避免循环调用, 由于当vue识别这个组件的时候,全局是有一个el-form组件的, 不更名会报错Uncaught RangeError: Maximum call stack size exceeded爆栈.程序员

2: intersectionObserver元素是否出如今视野内

bug现象:
我以前写过一个图片懒加载的插件, 第七集: 从零开始实现一套pc端vue的ui组件库( 懒加载v-lazy )与'骨架屏模板' 组件, 这个里面我判断图片是否出如今屏幕视野内的方式是, 计算图片相对于窗口的位置, 好比说用图片的宽减去他距离左侧的距离就能够知道它左边是否出现以及出现的百分比, 可是... 当有了这个属性一切都不同了, 能够说以前本身写的是'错'的了.
代码呈现
你们能够直接拿去玩一下, 简直太好用了.web

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    #ks{
      position: absolute;
      border: 1px solid red;
      left: 10px;
      width: 100px;
      height: 100px;
    }
  </style>
</head>
<body>
  <div id="ks">我来了</div>
  <script>
    const ks = document.getElementById('ks');
    // IntersectionObserver是浏览器原生提供的构造函数,接受两个参数:callback是可见性变化时的回调函数,option是配置对象(该参数可选)。
    var io = new IntersectionObserver((res)=>{
      // intersectionRatio 是可见的范围, 均可见为1, 都不可见为0
      console.log('隐藏了么',res[0].intersectionRatio)
    });
    // 开始观察
    io.observe(ks);
    var n =0;
    ks.onclick=function(){
       this.style.left = n + 'px';
       n -=5
    }
    setInterval(()=>{
      ks.style.left = n + 'px';
       n -=5
    },100)
    // 中止观察
    // io.unobserve(element);

    // 关闭观察器
    // io.disconnect();
  </script>
</body>
</html>

具体的详细解读你们能够看看阮一峰老师对这个方法的介绍, 这条只能算是api知识点, 可是在不知道这个api的状况下确实对我形成了困扰.npm

3: 项目名也就是main对应的字段, 须要避免与内部的包名重复

bug现象
我建立了一个名为xxx的项目, 而且在项目里面引入了一个叫xxx的包, 这就会致使项目报错.element-ui

bug解决
改掉package.json文件中的name属性.

bug回味

  1. 项目起名也是须要有必定章法的, npm包的起名也是要有必定章法的, 好比bable的命名就挺棒的@babel/core @babel/preset-env 这两个包第一眼看去就是围绕着babel产生的包显得很专业.
  2. 咱们发布包也要避免污染npm的总体环境, 命名分为核心包与围绕核心包的扩展功能包, 由于一旦发布就很差撤回了, 并且包的名字是不可重复的.

4: flow-root 清除浮动最友好的方式, 不会影响元素自己 也很少写元素

解决的主要问题
清除浮动dispaly:flow-root造成"BFC"

为何要用它?

  1. 能够说之前用的方式都不是专门针对清除浮动的, 而它才是专业.
  2. 不用新增元素, 哪怕只是占用个伪元素, 没准伪元素须要去作其余的事.
  3. 不用新增属性, 也就是不用多写一条样式, 直接把自身的'display'改了就好.
  4. 不影响父级属性, 好比你用overflow: hidden;实际上是影响了自身的属性,内部元素无法出去了.

意义何在
我看到了css的坚持, 现阶段用浮动布局的人很少了, 但css不会由于这样就无论, 它依然想作到更好的解决办法, 可让咱们感受到前端会一直进步下去.

推荐:
推荐没看过的同窗看下我写的布局相关的文章, 跟浮动说拜拜记一次grid布局实战应用分享会

5: 兼容ie11 报错 script1006: 缺乏 ')'

别看已经到11了,兼容性仍是不行

bug描述
这个问题是同组的同窗遇到的, 临时决定兼容ie11出现了下面的错误:
30116AB5-917F-4ef8-9EF1-0B27DC6B8483.png

点击这个bug:
cw.png

bug分析
这个bug是因为ie11监测到了不懂的语法, 可是ie直接这样指出问题的所在开发人员也很差定位,那咱们须要解决的核心问题就是把全部es5之后的语法转义为es5应该就能解决问题.
连let都不认识? 我几乎不玩ie.
ii.png

bug定位
zhaobao.png
细心观察的话就会发现, 这个出问题的包的名字在上面.
在配置文件里面没有搜索到这个包, 那么这个包极可能是在依赖的依赖中, 甚至更深!

bug解决
vue.config.js里面配置指定解析项:transpileDependencies: ['resize-detector'],

transpileDependencies:中文意思是跨文件依赖项, 官网的描述以下:
gwnb.png

6: 尝试使用postcss-bem插件

故事陈述
想要进步的前端同窗必定不甘于固有的模式, 因此一个同窗学习了这篇文章(友情连接):PostCSS深刻学习: 结合BEM和SUIT方法使用PostCSS.
你们有时间能够看一看挺有意思的想法, 当时咱们的第一印象就是能够玩一玩.

介绍插件
为了懒得看上面的文章的同窗我来介绍一下, 这个插件可使咱们项目更好的使用'bem'的结构来写css, 注意:只是css, 好比声明一个hello的盒子, 里面有hello-header元素.
看起来是否是还挺舒服的.

@component hello {
  @descendent header {
    border: 1px solid #ccc;
  }
}

bug1描述
他的文章里没说怎么配置进vue项目里面, 多是由于文章是2015年写的太早了, 因此具体怎么弄进去你们能够自行研究, 网上资料挺少的就看你们的学习能力了, 我是写在了postcss.config.js文件里面.

module.exports = {
  plugins: [
    require('postcss-bem')({}),
    require('postcss-nested')({}),
  ],
};

运行就报错:
zhaobus.png

bug1解决
真是挺坑的问题, 但仍是找到了解决方案:
老版本moveto方法变成append方法才管用, 因此咱们须要把源码下载到本地替换掉全部的moveto方法....

bug2描述
问题基本解决了能够很爽的开始写了么?? no...
仍是下面的结构, 好比我想取hello-header元素下面的p标签, 这样是取不到的, 必须给p标签一个名字, 而且这个名字必须是符合上面层级关系的规范'bem'命名...不然疯狂报错.

@component hello {
  @descendent header {
    border: 1px solid #ccc;
  }
}

bug2解决
没找到解决方法

问题分析
这个插件想法颇有趣, 可是弊端也挺多, 整体来讲思想值得respect, 相应的问题以下:

  1. 无人维护没法放心使用.
  2. 限制太多反而限制了css代码的厉害之处.

不会为了使用新技术而使用新技术, 这个技术并非那么好, 那咱们索性就学习他的思想与玩法, 并不必定要使用它,要懂得取舍.

7: 1.toString() 报错是由于 1. 至关于 1.0 ?

保持好奇心
有些时候吧, 书上或者视频上也不必定全对

原由
咱们常说像1这种数字不能直接.toString(), 由于他是基本值, 只有进行了包装类变成object才能进行'.'的操做, 好比new Number(1).toString(), 这类说法很主流, 可是接下来的一段代码怎么解释?

hq.png

问题猜测...
数字不能够直接用'.'来取属性是由于系统认为这个'.'是小数点, 而不是操做符,那么咱们只要不让引擎觉得咱们写的是小数点就ok了, 下面的方法我来解释一下:

  1. 1.123.toString() 一个普通的数字只能有一个小数点, 那么第二个'.'也就会被解析为取属性.
  2. 若是咱们明确告诉系统咱们在取属性, console.log(1.123['toString']())那么系统也就会正确解析.

llc.png

将来展望
我写代码时间过短能力还不足, 期待明年的本身能够从v8引擎的角度来分析问题.

8: element-ui表格table的懒加载封装

bug描述
后端同窗一下给我返回3万条列表数据, 致使页面'假死', 无奈的是产品不容许作成分页的.

bug分析
显而易见dom太多了, 可是element-ui自己没有这种table的懒加载, 他只有table内部树形结构的懒加载, 那么咱们本身封装一个能够懒加载的表格吧, 刚好element-ui自己有个懒加载组件(不记得的同窗能够撸撸官网):
bs.png

bug解决
单独封装懒加载的table, 利用一个能够无限滚动的外壳dom,每次触底帮助用户处理一下显示的数据, 这里我就展现一下大致的核心代码.
./components/ScrollTable.vue文件

<template>
<!-- 可变的都当作参数传进来就行了, 这里我只演示一下思想 -->
  <div
    class="scroll-box"
    ref="scrollBox"
    v-infinite-scroll="load"
    :infinite-scroll-delay="200"
    :infinite-scroll-distance="100"
  >
    <el-table border style="width: 300px" :data="list">
      <slot></slot>
    </el-table>
  </div>
</template>

<script>
export default {
  props:{
    reslist:Array
  },
  data() {
    return {
      list: [],
      count: 0 // 初始值可传
    };
  },
  methods: {
    load() {
      if (this.$refs.scrollBox) {
        this.count += 10; // 这个10也可让用户本身传, 每次触底加载几条
        this.$refs.scrollBox.scrollTop -= 30;
        // 这里能够作一下已到底的处理
        this.list = this.reslist.slice(0, this.count);
      }
    }
  }
};
</script>

<style>
.scroll-box {
  overflow: auto;
  /* 这些当作参数传进来就行了 */
  width: 300px;
  height: 260px;
  padding-bottom: 20px;
}
</style>

使用:

<template>
  <div id="app">
    <el-scroll-table :reslist="list">
      <el-table-column type="index" width="50" label="序号" />
      <el-table-column prop="name" label="参数" />
    </el-scroll-table>
  </div>
</template>

<script>
import ElScrollTable from "./components/ScrollTable.vue";
export default {
  name: "App",
  components: {
    ElScrollTable
  },
  data() {
    return {
      list: []
    };
  },
  mounted(){
    for(let i=0;i<90;i++){
      this.list.push({
        name:'金毛'+ i
      })
    }
  }
};
</script>

问题回顾

  1. this.$refs.scrollBox.scrollTop -= 30这段莫名其妙的代码它解决了无限触底加载的bug, 由于每次触底以后虽然加载新数据, 可是滚动条位置还停留在最底部, 这样就会一直加载.
  2. 咱们能够再加一段代码用来重置参数, 或者每次用户本身去出发重置方法, 或是监听用户传值的变化而重置.
  3. 这种方式比较适合后端把全部数据都给到咱们, 好比我此次遇到的就是一次拿到3万条, 用户不可能每次下拉十条一直看一万条, 后端非要返给我那就我接到数据后进行了截断, 毕竟放内存里也是会占空间的.
  4. 使用起来很简单, 效果也还不错, 可是在pc端大部分仍是用分页器作的, 这种需求挺少但不是没有, 彻底体的组件时间关系我暂时没有去作, 有兴趣的同窗根据本身的需求能够玩一玩.

9: vue项目icon错乱与引入scss文件失效

bug描述
忽然有一天夜里同事发觉新上线的版本icon是错乱的, 只在少数电脑上能够复现, 而且icon并非一开始就错乱而是正常显示2s后开始错乱.

bug解决
查了好多地方都没找到,由于他有2s钟是正常的, 这个现象影响了个人思路, 另外一个同窗发现打包出来的icon代码好像是混乱的, 那么咱们就把vue里面的style标签上的lang="scss"去掉, 原本我不信但结果还真的好了....,罪魁祸首是dart-sass.

dart-sass是啥
引用官网的一段话:
Dart Sass 是 Sass 的主要实现版本,这意味着它集成新 功能要早于任何其它的实现版本。Dart Sass 速度快、易于安装,而且 能够被编译成纯 JavaScript 代码,这使得它很容易集成到现代 web 的开发流程中。, 好比咱们平时下载node-sass会出现失败或者是缺乏python2的报错, 而dart-sass就没有这样的问题, 而且速度很快.

bug2描述
咱们以前引入的一个scss文件不生效了, 就是没有code格式报错,没有控制台报错, 就是文件里面的内容不生效了.

bug2解决
原来是因为咱们取消了app.vue文件里面style的lang="scss", 再次引入scss文件并不会走scss解析器, 而这个scss文件里面的第一行我用// 这样的注释写明了这个文件的功能, 致使下面的代码所有失效, 解决方式就是把//更改成/**/下面的文件就ok了, 固然若是你下面的代码是scss规范书写的那也没法解析出来, 因此要谨慎使用dart-sass.
但我如今仍是不明白为何会有2s钟正常显示, 这个等我年末研究v8的时候再来从底层的角度搞定它.

end:

此次遇到的bug让我体会到我如今没法理解的问题不表明不会发生, 只是我能力还不够加油提升吧! 本次的分享就是这样,欢迎交流, 祝天天进步

相关文章
相关标签/搜索