开发常见问题
- 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取数组中的第二个值。
- echarts图表做成自适应,必须满足所有父元素的宽高都是百分比表示。即能通过百分比算出echarts元素的大小。
- 不同分辨率的屏幕自适应解决方案:calc(100vw/1920*470),和.postcssrc.js文件。
- 对于dialog组件,想修改其中内部样式,需要在主体中进行设置,在外部设置无效,(因为dialog会改变div原有层级。)
echarts相关
- 对于echarts中标题样式的改变:
text: ["{a|}", "{b|大坝安全鉴定}"].join(""),
textStyle: {
color: "#23FFD9",
rich: {
a: { width: 4, backgroundColor: "#23FFD9",fontSize: 16, },
b: {
padding: [0, 0, 2, 10],
fontSize: 16,
}
}
}
- webstorm或idea中项目目录树形结构变化或者其他配置出错,删除.idea文件夹,重启即可解决。
- 文字颜色渐变的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 这样设置,会导致各种莫名其妙的错误。
视频直播点播相关
- 视频传输协议主要有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>
- 对于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/"
- 对于下载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插件
- 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",
- 常见视频格式:
- flv格式是加入关联扩展名:.flv,内容类型:application/octet-stream,流式
- f4v格式是扩展名:.f4v,内容类型:application/octet-stream,流式
- mp4格式是扩展名:.mp4,内容类型:video/mp4,非流式
- ogv格式是扩展名:.ogv ,内容类型:video/ogg ,非流式
- webm格式是扩展名:.webm,内容类型:video/webm,非流式
- 当执行setInterval(arrow(),2000)这条代码的时候,arrow()这个函数只执行一次的原因: arrow()这是一个函数调用,应该是一个具有函数定义属性的值。更改为:setInterval(arrow,2000)。还有列子:在echarts中,自定义legend文字,使用的是formatter函数,此时应该以函数名赋值(不带括号和参数):
this.riverOption.legend.formatter = this.riverLegendFormatter;
- 对于定时器setInterval,需增加在组件销毁时手动清除,具体如下:
destroyed () {
this.layer.dispose()
this.imgIntervalFlag = null
}
- 常见的媒体格式类型如下:
- 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格式发送到服务器(表单默认的提交数据的格式) , 常见
- npm 命令的概括: 格式:npm command [args],其中npm说明命令类型,command是npm中的具体命令(可包含子命令:如:npm config set,也就是子方法),可以理解为函数名称,[args]是需要的参数,可以理解为函数需要的参数,其中额外参数全写用--,简写(一般大写首字母)为-,如:-S ,--save。 注:npm help 获取可用命令的列表,npm command --help查看命令参数
- webstorm可用的预定义文件模板变量是(可任意自定义模板):
- ${PROJECT_NAME} -当前项目的名称。
- $ {NAME} -你在指定新文件的名称新文件文件的创建过程对话框。
- $ {USER} -当前用户的登录名。
- $ {DATE} -当前系统日期。
- $ {TIME} -当前系统时间。
- $ {YEAR} -当前年份。
- $ {MONTH} -当前月份。
- $ {DAY} -该月的当前日期。
- $ {HOUR} -当前时间。
- $ {MINUTE} -当前分钟。
- $ {PRODUCT_NAME} -在该文件将被创建IDE的名字。
- $ {MONTH_NAME_SHORT} -月份名称的前3个字母。例如:一月,二月,等等。
- $ {MONTH_NAME_FULL} -一个月的全名。例如:一月,二月,等等。
- border-collapse属性为合并table边框,防止出现边框合并的问题。具体如下:
table
{
border-collapse:collapse;
}
- 对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为域名解析服务器,这个不作赘述。
- js的展开语法只对一级数组或对象进行扩展,是深拷贝。
var arr = [1, 2, 3];
var arr2 = [...arr]; // like arr.slice()
arr2.push(4);
// arr2 此时变成 [1, 2, 3, 4]
// arr 不受影响
和Object.assign()类似。
- Vue中引入图片路径的几种书写方式:相对路径或者require('./image.png'。绝对路径,文件需放置在public文件夹下面,例如 /images/foo.png。使用绝对路径时,当部署目录不在根目录时,需要在vue.config.js中配置publicPath,因为绝对路径编译后默认放置的位置就是根目录。详细内容可参:segmentfault.com/a/119000001…
- 求数组最大值:
var arr = [-1, 1, 101, -52, 10, 1001, 1001]
Math.max(...arr)
创建值相同的数组:
new Array(4).fill(max)
- 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对象的所有方法和属性。
- vue的dom更新是异步的,js中异步的执行原理如下:
- (1)所有同步任务都在主线程上执行,形成一个执行栈(execution context stack)。
- (2)主线程之外,还存在一个"任务队列"(task queue)。只要异步任务有了运行结果,就在"任务队列"之中放置一个事件。
- (3)一旦"执行栈"中的所有同步任务执行完毕,系统就会读取"任务队列",看看里面有哪些事件。那些对应的异步任务,于是结束等待状态,进入执行栈,开始执行。
- (4)主线程不断重复上面的第三步。
- mounted 不会承诺所有的子组件也都一起被挂载。如果你希望等到整个视图都渲染完毕,可以用 vm.$nextTick 替换掉 mounted
- 在echarts中想要图标实现自适应,需要确保最顶层父元素的宽高是确定的(可设置为width: 100vw; height: 100vw;),此外每级父元素的的宽高都用百分比表示(此时百分比也就是具体的值),在把本元素设置为百分比。需要注意一个问题:在echarts绑定的元素上设置为100%的时候会出现实际渲染出来的是100px,此时就是因为在vue中mounted的原因,此时需要设置
mounted() {
this.$nextTick(() => {
this.drawChart();
});
},
- 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,所以常用于接口返回数据的赋值操作。
- js常用对象如下
其中Math是一个静态类,不可实例化,其方法都是静态方法,通过Math.methodName调用,其包含基本的数学运算方法。其他都为普通类,包含实例方法和静态方法,其中静态方法多为类型判断和类型转化(比较少),如
还有全局方法,属于Window对象直接调用,主要是基本类型的转化与url的操作。
- 更改html注释样式
将line comment at first column取消勾选。
- 在单个文件上面写/* eslint-disable */,可以去除eslint检查
- 在MDN-运算符优先级上,后置自增a++比前置自增++a有更高的优先级,这是什么原因?解释如下,虽然都是自增运算,但是其内部实现是屏蔽的,后置递增表现出来的就是所有运算都完成再进行自增操作,即本语句中并没有进行自增操作。
- 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都是用百分比
-
3d地图的简单实现
-
模拟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时,可能会出现相互影响的情况,此时需要设置:
- 颜色渐变的代码:
{
type: "linear",
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [
{
offset: 0,
color: "#644FFE" // 0% 处的颜色
},
{
offset: 1,
color: "#009CFF" // 100% 处的颜色
}
]
},
- 对于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)');
- router-view实现路由的嵌套,需要在router-view路由下的子路由设置路由。如:index页面包含导航菜单,需要添加item页面,则路由应该为/index/item,则会自用嵌套在router-view处。
48.鼠标查询css技巧
持续更新(后期进行分类完善).......