前端开发常见问题记录

404 阅读12分钟

开发常见问题

  1. Array.prototype.reduce()函数使用说明:reduce()方法对数组中的每个元素执行一个由您提供的reducer函数(升序执行),将其结果汇总为单个返回值。
const array1 = [1, 2, 3, 4];
const reducer = (accumulator, currentValue) => accumulator + currentValue;
// 5 + 1 + 2 + 3 + 4
console.log(array1.reduce((accumulator, currentValue) => accumulator + currentValue, 5));

说明:回调函数第一次执行时,accumulator和currentValue的取值有两种情况:如果调用reduce()时提供了initialValue,accumulator取值为initialValue,currentValue取数组中的第一个值;如果没有提供 initialValue,那么accumulator取数组中的第一个值,currentValue取数组中的第二个值。

  1. echarts图表做成自适应,必须满足所有父元素的宽高都是百分比表示。即能通过百分比算出echarts元素的大小。
  2. 不同分辨率的屏幕自适应解决方案:calc(100vw/1920*470),和.postcssrc.js文件。
  3. 对于dialog组件,想修改其中内部样式,需要在主体中进行设置,在外部设置无效,(因为dialog会改变div原有层级。)

echarts相关

  1. 对于echarts中标题样式的改变:
text: ["{a|}", "{b|大坝安全鉴定}"].join(""),
textStyle: {
  color: "#23FFD9",
  rich: {
    a: { width: 4, backgroundColor: "#23FFD9",fontSize: 16, },
    b: {
      padding: [0, 0, 2, 10],
      fontSize: 16,
    }
  }
}
  1. webstorm或idea中项目目录树形结构变化或者其他配置出错,删除.idea文件夹,重启即可解决。
  2. 文字颜色渐变的css:
background: linear-gradient(to right, #04FFBB, #19FFF7);
-webkit-background-clip: text;
color: transparent;
注:由于兼容性较差(edge以上)所以,建议使用背景图替换。

8. 设置echarts中bar的宽度和间距时,只需要通过grid设置画布大小,在设置barWidth设置宽度,间距就自动设置了。 9. 对于webstorm中搜索关键字(ctrl+shift+f),默认搜索范围是整个project,没有包含依赖包node_modules。想要包含所有,需要选择scope--》all places. 10. eslint的standard config模式没有对vue标签的多个属性进行换行,而prettier模式有。 11. 不能npm config set registry registry.npm.taobao.org 这样设置,会导致各种莫名其妙的错误。

视频直播点播相关

  1. 视频传输协议主要有RTMP,RTSP,和HTTP(HLS),其中RTMP是Adobe公司的,所以代码中需要加入flash插件,并且浏览器也要支持flash并允许,用hls的话,需要安装hls插件。对于video.js,动态切换播放地址需要调用this.src()方法,页面切换时,需手动调用this.dispose()关闭直播。详细代码如下
import video from 'video.js'
import 'video.js/dist/video-js.css'
import 'videojs-contrib-hls'

Vue.prototype.$video = video
//
mounted () {
    this.playerVideo('myVideo')
  },
// 视频播放
playerVideo (id) {
  this.layer = this.$video(id, {
    controls: true,
    autoplay: false,
    muted: true
  }, function onPlayerReady () {
    this.play()
    this.on('ended', function () {
      console.log('Awww...over so soon?!')
    })
  })
  this.layer.src(this.videoSrc)
},
// 组件销毁时停止播放
destroyed () {
    this.layer.dispose()
  }
<video id="myVideo" class="video-js vjs-default-skin">
  <source src="http://112.74.91.72:10001/hls/34020000001110000001_0200000011/34020000001110000001_0200000011_live.m3u8" type="application/x-mpegURL">
</video>
  1. 对于npm库源标准如下(设置成淘宝影像有些包会出错)
D:\workspace\gbsdemo>npm config list
; cli configs
metrics-registry = "http://registry.npmjs.org/"
scope = ""
user-agent = "npm/6.13.4 node/v12.16.1 win32 x64"

; userconfig C:\Users\86132\.npmrc
@ec:registry = "http://10.10.0.17:4873"
registry = "http://registry.npmjs.org/"

  1. 对于下载base64编码格式的图片时,可用代码如下:
getImgURL () {
    this.$axios.get('/api/v1/device/channelsnap', {
      params: {
        serial: this.cameraId,
        realtime: true,
        encode: true
      }
    })
      .then(response => {
        // 这里是获取到的图片base64编码,这里只是个例子哈,要自行编码图片替换这里才能测试看到效果
        const imgUrl = response
        // 如果浏览器支持msSaveOrOpenBlob方法(也就是使用IE浏览器的时候),那么调用该方法去下载图片
        if (window.navigator.msSaveOrOpenBlob) {
          var bstr = atob(imgUrl.split(',')[1])
          var n = bstr.length
          var u8arr = new Uint8Array(n)
          while (n--) {
            u8arr[n] = bstr.charCodeAt(n)
          }
          var blob = new Blob([u8arr])
          window.navigator.msSaveOrOpenBlob(blob, 'chart-download' + '.' + 'png')
        } else {
          // 这里就按照chrome等新版浏览器来处理
          const a = document.createElement('a')
          a.href = imgUrl
          a.setAttribute('download', 'chart-download')
          a.click()
        }
      })
  },

或者使用download.js插件

  1. eslint 严格模式依赖包
   "@vue/cli-plugin-eslint": "~4.3.0",
   "@vue/eslint-config-prettier": "^6.0.0",
   "babel-eslint": "^10.1.0",
   "eslint": "^6.7.2",
   "eslint-plugin-prettier": "^3.1.1",
   "eslint-plugin-vue": "^6.2.2",
   "prettier": "^1.19.1",
  1. 常见视频格式:
  • flv格式是加入关联扩展名:.flv,内容类型:application/octet-stream,流式
  • f4v格式是扩展名:.f4v,内容类型:application/octet-stream,流式
  • mp4格式是扩展名:.mp4,内容类型:video/mp4,非流式
  • ogv格式是扩展名:.ogv ,内容类型:video/ogg ,非流式
  • webm格式是扩展名:.webm,内容类型:video/webm,非流式
  1. 当执行setInterval(arrow(),2000)这条代码的时候,arrow()这个函数只执行一次的原因: arrow()这是一个函数调用,应该是一个具有函数定义属性的值。更改为:setInterval(arrow,2000)。还有列子:在echarts中,自定义legend文字,使用的是formatter函数,此时应该以函数名赋值(不带括号和参数):
this.riverOption.legend.formatter = this.riverLegendFormatter;
  1. 对于定时器setInterval,需增加在组件销毁时手动清除,具体如下:
destroyed () {
    this.layer.dispose()
    this.imgIntervalFlag = null
  }
  1. 常见的媒体格式类型如下:
  • text/html : HTML格式, 常见
  • text/plain :纯文本格式
  • text/xml : XML格式
  • image/gif :gif图片格式 , 常见
  • image/jpeg :jpg图片格式 , 常见
  • image/png:png图片格式, 常见

以application开头的媒体格式类型:

  • application/xhtml+xml :XHTML格式
  • application/xml : XML数据格式
  • application/atom+xml :Atom XML聚合格式
  • application/json : JSON数据格式 , 常见
  • application/pdf :pdf格式
  • application/msword : Word文档格式
  • application/octet-stream : 二进制流数据(如常见的文件下载),视频流播放格式 , 常见
  • application/x-www-form-urlencoded : 中默认的encType,form表单数据被编码为key/value格式发送到服务器(表单默认的提交数据的格式) , 常见
  1. npm 命令的概括: 格式:npm command [args],其中npm说明命令类型,command是npm中的具体命令(可包含子命令:如:npm config set,也就是子方法),可以理解为函数名称,[args]是需要的参数,可以理解为函数需要的参数,其中额外参数全写用--,简写(一般大写首字母)为-,如:-S ,--save。 注:npm help 获取可用命令的列表,npm command --help查看命令参数
  2. webstorm可用的预定义文件模板变量是(可任意自定义模板):
  • ${PROJECT_NAME} -当前项目的名称。
  • $ {NAME} -你在指定新文件的名称新文件文件的创建过程对话框。
  • $ {USER} -当前用户的登录名。
  • $ {DATE} -当前系统日期。
  • $ {TIME} -当前系统时间。
  • $ {YEAR} -当前年份。
  • $ {MONTH} -当前月份。
  • $ {DAY} -该月的当前日期。
  • $ {HOUR} -当前时间。
  • $ {MINUTE} -当前分钟。
  • $ {PRODUCT_NAME} -在该文件将被创建IDE的名字。
  • $ {MONTH_NAME_SHORT} -月份名称的前3个字母。例如:一月,二月,等等。
  • $ {MONTH_NAME_FULL} -一个月的全名。例如:一月,二月,等等。
  1. border-collapse属性为合并table边框,防止出现边框合并的问题。具体如下:
table
  {
  border-collapse:collapse;
  }
  1. 对ip地址,子网掩码,网关,dns重新认识:ip,分为私有ip和共有ip,是32位二进制数,表示为用“.”分割的十进数,内网ip(私有ip)多为192.168.x.y类型;外网ip有网络运营商分配,可在cmd里面输入ipconfig命令进行查看。IP地址分为网络号和主机号两个部分,子网掩码为1的位数为网络号位,剩下为主机号位。如:内网ip为192.168.1.1,子网掩码为255.255.225.0,说明前24位为网络号位。网关也就是路由器,地址一般为192.168.x.1。dns为域名解析服务器,这个不作赘述。
  2. js的展开语法只对一级数组或对象进行扩展,是深拷贝。
var arr = [1, 2, 3];
var arr2 = [...arr]; // like arr.slice()
arr2.push(4); 
// arr2 此时变成 [1, 2, 3, 4]
// arr 不受影响

和Object.assign()类似。

  1. Vue中引入图片路径的几种书写方式:相对路径或者require('./image.png'。绝对路径,文件需放置在public文件夹下面,例如 /images/foo.png。使用绝对路径时,当部署目录不在根目录时,需要在vue.config.js中配置publicPath,因为绝对路径编译后默认放置的位置就是根目录。详细内容可参:segmentfault.com/a/119000001…
  2. 求数组最大值:
var arr = [-1, 1, 101, -52, 10, 1001, 1001]
Math.max(...arr)

创建值相同的数组:

new Array(4).fill(max)
  1. js数据弱类型(不必申明数据类型,在运行时会自动确定)的语言(编程的过程主要是对数据类型操作(内置对象方法与属性和自定义方法),和流程控制的过程),分为基本数据类型(Boolean,number,string,null, undefined,Symbol 。值类型,保存的栈中)和引用数据类型(object,Array。引用数据类型,保存在堆中)。js中有内置的基本类型的封装对象。基本数据类型具有其封装对象的所有方法和属性。通过new关键字创建的都是引用对象类型。
1. var str = 'hello';
2. var str1 = new String('hello');

console.log(typeof str) //string
console.log(typeof str1) // object

注:str具有String对象的所有方法和属性。

  1. vue的dom更新是异步的,js中异步的执行原理如下:
  • (1)所有同步任务都在主线程上执行,形成一个执行栈(execution context stack)。
  • (2)主线程之外,还存在一个"任务队列"(task queue)。只要异步任务有了运行结果,就在"任务队列"之中放置一个事件。
  • (3)一旦"执行栈"中的所有同步任务执行完毕,系统就会读取"任务队列",看看里面有哪些事件。那些对应的异步任务,于是结束等待状态,进入执行栈,开始执行。
  • (4)主线程不断重复上面的第三步。
  1. mounted 不会承诺所有的子组件也都一起被挂载。如果你希望等到整个视图都渲染完毕,可以用 vm.$nextTick 替换掉 mounted
  2. 在echarts中想要图标实现自适应,需要确保最顶层父元素的宽高是确定的(可设置为width: 100vw; height: 100vw;),此外每级父元素的的宽高都用百分比表示(此时百分比也就是具体的值),在把本元素设置为百分比。需要注意一个问题:在echarts绑定的元素上设置为100%的时候会出现实际渲染出来的是100px,此时就是因为在vue中mounted的原因,此时需要设置
mounted() {
    this.$nextTick(() => {
      this.drawChart();
    });
  },
  1. Array.prototype.filter()使用说明:filter()方法创建一个新数组,其包含通过所提供函数实现的测试的所有元素。 filter函数接受回调方法作为参数(一般写成箭头函数),其回调方法的参数是数据的每一个元素,但需要注意的是:filter需要在循环的时候判断一下是true还是false,是true才会返回这个元素

32. 数组循环的常用方法性能比较: for > for-of > forEach > filter > map > for-in。 其中map和filter创建新数据,而map返回所有元素,for-in多用于对象map中的循环,循环的key值,而for-of循环的是value值(主要是简单数组,非对象数组)。

 for (let key in obj) {
}
 for (let value in arr) {
}

33.逻辑运算的妙用:逻辑或 “||”,遇到第一个真值就返回其初始值,否则返回最后一个值。逻辑与“&&”,遇到第一个假值返回其初始值,否则返回最后一个值。“!!”双重非,用于显式地将任意值强制转换为其对应的布尔值。示例如下:

a5 = "Cat" && "Dog"     // t && t 返回 "Dog"
a6 = false && "Cat"     // f && t 返回 false

o5 = "Cat" || "Dog"     // t || t 返回 "Cat"
o6 = false || "Cat"     // f || t 返回 "Cat"

特别的:会被转换为 false 的表达式有:

  • null;
  • NaN;
  • 0;
  • 空字符串("" or '' or ``);
  • undefined。

说明:对于JavaScript,解释器在访问尚未初始化的变量或对象属性时返回undefined,所以常用于接口返回数据的赋值操作。

  1. js常用对象如下

其中Math是一个静态类,不可实例化,其方法都是静态方法,通过Math.methodName调用,其包含基本的数学运算方法。其他都为普通类,包含实例方法和静态方法,其中静态方法多为类型判断和类型转化(比较少),如 还有全局方法,属于Window对象直接调用,主要是基本类型的转化与url的操作。

  1. 更改html注释样式

将line comment at first column取消勾选。

  1. 在单个文件上面写/* eslint-disable */,可以去除eslint检查
  2. 在MDN-运算符优先级上,后置自增a++比前置自增++a有更高的优先级,这是什么原因?解释如下,虽然都是自增运算,但是其内部实现是屏蔽的,后置递增表现出来的就是所有运算都完成再进行自增操作,即本语句中并没有进行自增操作。

  1. echarts中toolTip自动显示代码
 this.autoPlayInterval = setInterval(() => {
        // 取消选中区域
        this.chartInit.dispatchAction({
          type: "downplay",
          seriesIndex: 0
        });
        // 显示toolTip
        this.chartInit.dispatchAction({
          type: "showTip",
          seriesIndex: 0,
          dataIndex: this.intervalIndex
        });
        // 选中区域
        this.chartInit.dispatchAction({
          type: "highlight",
          seriesIndex: 0,
          dataIndex: this.intervalIndex
        });
        this.intervalIndex++;
        if (this.intervalIndex === this.areaMapList.length) {
          this.intervalIndex = 0;
        }
      }, 5 * 1000);

详细方法可在echarts官网的文档--》aip----》action菜单查看。

39.以下6个属性设置在项目上。

    order
    flex-grow
    flex-shrink
    flex-basis
    flex
    align-self

以下6个属性设置在容器上。

    flex-direction
    flex-wrap
    flex-flow
    justify-content
    align-items
    align-content

40. 总结:

  • echarts对3d效果图基本不支持,如果想展示3d效果,hightcharts有部分支持
  • 选择图形时,应该考虑数据的比例关系,可能会出现都是0的情况,所以展示出来的效果可能就不是很理想
  • 对echarts想要做全屏,就应该每一级div都是用百分比
  1. 3d地图的简单实现

  2. 模拟3d地图并添加涟漪效果代:

 geo: {
        map: "贵州",
        aspectScale: 1.3,
        layoutCenter: ["45%", "50%"], //地图位置
        layoutSize: "120%",
        itemStyle: {
          normal: {
            shadowColor: "#276fce",
            shadowOffsetX: 0,
            shadowOffsetY: 15,
            opacity: 0.5
          },
          emphasis: {
            areaColor: "#276fce"
          }
        }
      },
      series: [
        {
          type: "map",
          map: "贵州",
          selectedMode: "single",
          aspectScale: 1.3,
          layoutCenter: ["45%", "50%"], //地图位置
          layoutSize: "120%",
          label: {
            normal: {
              color: "#FFFFFF",
              show: false,
              position: "inside",
              formatter: function(params) {
                let stationNum =
                  (params.data.station.level1 || 0) +
                  (params.data.station.level2 || 0) +
                  (params.data.station.level3 || 0);
                let riverNum =
                  (params.data.flow.level1 || 0) +
                  (params.data.flow.level2 || 0) +
                  (params.data.flow.level3 || 0);
                return `{a|${stationNum}}\n{b|${riverNum}}`;
              },
              rich: {
                a: {
                  backgroundColor: {
                    image: stationImg
                  },
                  fontSize: 16,
                  width: 50,
                  height: 50,
                  align: "center"
                },
                b: {
                  backgroundColor: {
                    image: riverImg
                  },
                  width: 50,
                  height: 50,
                  fontSize: 16,
                  align: "center"
                }
              }
            }
          },
          itemStyle: {
            color: "#22B2FE",
            borderColor: "#46F8DC",
            borderWidth: 0.5,
            fontSize: 18
          },
          emphasis: {
            label: {
              show: false
            },
            itemStyle: {
              areaColor: "#146CFF"
            }
          },
          tooltip: {
            show: true,
            trigger: "item",
            axisPointer: {
              type: "shadow"
            },
            textStyle: {
              fontSize: 18
            },
            formatter: function(params) {
              return `${params.name}<br/>
              水库安全预警:<span style="margin-left: 10px;color: #ea1418">${params
                .data.station.level1 || 0}</span>
              <span style="margin-left: 10px;color: #FFF713">${params.data
                .station.level2 || 0}</span>
              <span style="margin-left: 10px;color: #46B0FF">${params.data
                .station.level3 || 0}</span>
              <br/>生态流量预警:<span style="margin-left: 10px;color: #ea1418">${params
                .data.flow.level1 || 0}
              <span style="margin-left: 10px;color: #FFF713">${params.data
                .flow.level2 || 0}
              <span style="margin-left: 10px;color: #46B0FF">${params.data
                .flow.level3 || 0}`;
            }
          },
          data: []
        },
        {
          name: "预警数",
          type: "effectScatter",
          coordinateSystem: "geo",
          symbol: "circle",
          symbolSize: 30,
          label: {
            normal: {
              show: true,
              formatter: function(value) {
                return value.value[2] + (value.value[3] || 0);
              },
              textStyle: {
                color: "#fff",
                fontSize: 16
              }
            }
          },
          itemStyle: {
            color: "#bb2e2e"
          },
          data: []
        }
      ]           

** 注意**:当设置多个series时,可能会出现相互影响的情况,此时需要设置:

  1. 颜色渐变的代码:
{
    type: "linear",
    x: 0,
    y: 0,
    x2: 0,
    y2: 1,
    colorStops: [
      {
        offset: 0,
        color: "#644FFE" // 0% 处的颜色
      },
      {
        offset: 1,
        color: "#009CFF" // 100% 处的颜色
      }
    ]
  },
  1. 对于echarts地图的js文件echarts.registerMap注册方法说明如下: 其中重要的参数是geojson格式的数据

对geojson格式说明,对于数据有压缩的:

对于格式没有压缩的

geojson的中文文档地址:my.oschina.net/u/4286318/b… 参考文档:juejin.cn/post/684490…

45.你不是知道的UMD:

JavaScript在模块化的发展过程中出现和很多概念,比如CommonJS,AMD (Asynchronous Module Definition),CMD (Common Module Definition)等,后来CommonJs规范被Node.js采用,我们可以在Node.js中通过var http = require('http')这种写法来引入模块,通过module.exports来导出自定义的模块,AMD和CMD也是requirejs和seajs推广过程中的规范化产出,因此让一个模块可以同时支持这么多的规范,就需要在模块定义时进行判断处理。这个判断处理的代码在流行的库和框架中随处可见,不过今天才知道,其实这种模式叫做UMD (Universal Module Definition)。

这个repo规范了UMD API和的定义和实现,让这些模块可以在客户端(浏览器),服务端或其他地方工作。README里面的一些变体(Variations)规定了各种常规模块的写法,比如amdWeb.js规定了可以运行在AMD规范下(即使用requirejs)和浏览器全局下的模块的写法,点进去会发现其实是一小段示例代码:

(function (root, factory) {
  if (typeof define === 'function' && define.amd) {
    // AMD. Register as an anonymous module.
    define(['b'], factory);
    } else {
      //Browser globals
      root.amdWeb = factory(root.b);
    }
  }(this, function (b) {
    return {};
}));

可以看出是一段自执行函数,接收root和factory两个参数,root为全局对象,factory则为工厂函数,用来返回一个模块的实例化对象。这段代码先通过typeof define === 'function' && define.amd来判断当前环境是否遵循AMD规范(因为requirejs和seajs都是使用define来定义模块,所以需要define.amd进一步区分两者),如果是,通过define(['b'], factory)就可以对模块进行定义,如果不是,就执行root.amdWeb = factory(root.b),此时root === window,这时window上就挂载了一个factory执行完返回的对象,这个模块就可以全局调用了。

其他的常规模块的定义也都是一个道理,比如returnExports定义了一个在nodejs,AMD,browser global下工作的模块,判断AMD环境仍然是通过typeof define === 'function' && define.amd,判断nodejs环境则通过typeof module === 'object' && module.exports,一般的模块都是判断了所有环境后,如果没有符合条件的就默认为浏览器环境,直接挂在在window上。

46.WKT转GeoJSON,使用terraformer-wkt-parser。

var geojson = WKT.parse('LINESTRING (30 10, 10 30, 40 40)');

  1. router-view实现路由的嵌套,需要在router-view路由下的子路由设置路由。如:index页面包含导航菜单,需要添加item页面,则路由应该为/index/item,则会自用嵌套在router-view处。

48.鼠标查询css技巧

持续更新(后期进行分类完善).......