分类:Javascript / vue

ES6关于数组操作forEach,map,filter,find,some,every,reduce学习理解和使用

首先说明:数组操作forEach(),map(),filter(),find(),some(),every(),reduce()所有方法,只要是return回来的,均不改变原数组。

forEach()

参数item, index
遍历数组全部元素使用,相当于用for循环吧

var arr = [1,2,3,4,5,] ;
arr.forEach(function(item,index){
    console.log(item);
}); 

/*
1
2
3
4
5
*/

map ()

一项一项更新数组内容,有return的话,返回一个新数组

var arr = [1,2,3,4,5] ;
arr.map((item,index)=>{ return item*2})
//  [2, 4, 6, 8, 10]

filter()和find()的区别

filter,find 一般都用于筛选数组,filter返回一个新数组,find则返回第一个符合return后判断内容的单个item

var arr = [1,2,3,4,5] ;
arr.filter(item=>item>2)
// (3) [3, 4, 5]
arr.find(item=>item>2)
// 3

includes()

判断数组是否包含一项内容

var arr = [1,2,3,4,5] ;
arr.includes(4)
// true
arr.includes(6)
// false

some()和every()的区别

some(), every()都是用来判断用的,只会返回true和false
其中some()只有一项满足就会返回true, every()只有一项不满足就会返回false

var arr = [1,2,3,4,5] ;
arr.some(item=>item>4)
// true
arr.some(item=>item>6)
// false
arr.every(item=>item>4)
// false
arr.every(item=>item>0)
// true

reduce()

reduce()一般用于计算,合并,叠加等等

//求和计算
var arr1 = [1,2,3,4,5] ;
var new1 = arr1.reduce(function(sum,next,index){
        return sum+next ;    
        /*
         *第一次:pre-->1  next-->2  index-->1
         *遍历计算return得结果为pre+next=1+2=3
         *第二次:pre-->3  next-->3  index-->2
         *遍历计算return得结果为pre+next=3+3=6
         *第三次:pre-->6  next-->4  index-->3
         *遍历计算return得结果为pre+next=6+4=10
         *第四次:pre-->10  next-->5  index-->4
         *遍历计算return得结果为pre+next=10+5=15
        */
})

//扁平化数组
var arr2 = [[1,2,3],[4,5],[6,7]] ;
var new2 = arr2.reduce(function(pre,next,index){
        return pre.concat(next);    //前数组拼接后数组 .concat()
})

//对象数组叠加计算
var arr3 = [{price:10,count:1},{price:15,count:2},{price:10,count:3}];
var new3 = arr3.reduce(function(pre,next,index){
        return pre+next.price*next.count;
        //当需要对第一项进行操作时,后面pre使用上一项操作结果,不再需要操作
        //所以当需要操作第一项的时候,利用reduce(callbreak(){},往数组第一项前添加一项,如:0)
},0)    //在原数组第一项添加为0,不改变原数组,则可不操作第一项

console.log(new1);
console.log(new2);
console.log(new3);
// 15
// [1, 2, 3, 4, 5, 6, 7]
// 70

chrome浏览器配置跨域问题

问题出现:
因为访问某个后端接口碰到了跨域问题,然后vue这边又因为一些客观原因无法配置跨域,接口端配置跨域又出现了错误,这个时候就陷入了僵局。
所以,我想到了通过浏览器来配置跨域。

以下讲的都是windows下的chrome浏览器跨域配置:
1、C盘根目录下,建一个 MyChromeDevUserData 文件夹
2、复制浏览器快捷方式,改名为DEV,在DEV上右键,进入属性
3、在属性的目标输入框 尾部加上 --disable-web-security --user-data-dir=C:\MyChromeDevUserData
4、应用,并双击DEV的浏览器快捷方式,打开chrome
5、跳出 您使用的是不受支持的命令行标记:--disable XXXXXXX,说明配置成功
以后你用DEV的快捷方式打开浏览器,将永远不需要处理跨域问题

前端通过meta设置各种模式等

<!-- 设置缩放 -->
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no, minimal-ui" />
<!-- 可隐藏地址栏,仅针对IOS的Safari(注:IOS7.0版本以后,safari上已看不到效果) -->
<meta name="apple-mobile-web-app-capable" content="yes" />
<!-- 仅针对IOS的Safari顶端状态条的样式(可选default/black/black-translucent ) -->
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
<!-- IOS中禁用将数字识别为电话号码/忽略Android平台中对邮箱地址的识别 -->
<meta name="format-detection"content="telephone=no, email=no" />

<!-- 启用360浏览器的极速模式(webkit) -->
<meta name="renderer" content="webkit">
<!-- 避免IE使用兼容模式 -->
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!-- 针对手持设备优化,主要是针对一些老的不识别viewport的浏览器,比如黑莓 -->
<meta name="HandheldFriendly" content="true">
<!-- 微软的老式浏览器 -->
<meta name="MobileOptimized" content="320">
<!-- uc强制竖屏 -->
<meta name="screen-orientation" content="portrait">
<!-- QQ强制竖屏 -->
<meta name="x5-orientation" content="portrait">
<!-- UC强制全屏 -->
<meta name="full-screen" content="yes">
<!-- QQ强制全屏 -->
<meta name="x5-fullscreen" content="true">
<!-- UC应用模式 -->
<meta name="browsermode" content="application">
<!-- QQ应用模式 -->
<meta name="x5-page-mode" content="app">
<!-- windows phone 点击无高光 -->
<meta name="msapplication-tap-highlight" content="no">

整理解决node-sass依赖错误的问题

最近因为某些原因,MAC系统重装了,然后运行老项目时,出现了各种水土不服的问题,花了不少时间解决,特此记录。

解决方案:查看自己的node版本是否过高,node-sass@4.x.x系列的依赖在过高版本的node下不能顺利运行的。我是通过n控制node版本,降低node@v10.24.1得以解决。

因为习惯使用CNPM淘宝源来进行依赖安装,即cnpm i,发现老项目老是报错:

npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! node-sass@4.14.1 postinstall: `node scripts/build.js`

网上搜索后,很多人说是通过淘宝源解决,但我尝试后问题依旧,不过我已经锁定是node-sass的版本问题。

故尝试了cnpm i,翻墙 npm i,或者设置

npm config set sass_binary_site=https://npm.taobao.org/mirrors/node-sass

以上都没有效果。

也自己尝试删除package.json中的

"node-sass": "^4.8.3",
"sass-loader": "^7.0.1",
"style-loader": "^0.21.0",

然后重新cnpm i node-sass sass-loader style-loader -D,依赖倒是都可以安装上了,但运行npm run dev时,会报错:

Module build failed: TypeError: this.getOptions is not a function
或者
TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string。

然后解决方案搜索后,说是node-sass版本太高了,因为这时自动加载的node-sass已经到了6.0.1还是多少。
后来想到,可能是node的版本问题,所以查了下NODE版本,

node-v16.10.0

确实太高了,已经接近最新版本,估计node-sass@4.8.3依赖和node版本之间的问题了。

随即,安装n来控制node多版本,安装node 10系列的版本

root@zhujindeMacBook-Pro ~ # n list
node/16.10.0
root@zhujindeMacBook-Pro ~ # n 10
  installing : node-v10.24.1
       mkdir : /usr/local/n/versions/node/10.24.1
       fetch : https://nodejs.org/dist/v10.24.1/node-v10.24.1-darwin-x64.tar.xz
   installed : v10.24.1 (with npm 6.14.12)
root@zhujindeMacBook-Pro ~ # n
   installed : v10.24.1 (with npm 6.14.12)
root@zhujindeMacBook-Pro ~ # node -v
v10.24.1

之后回到项目,删除node_modules,重新运行cnpm i,问题解决。

vue-cli3构建的vue项目使用babel-polyfill兼容安卓低版本浏览器

vue-cli2构建的项目有很多教程写babel-polyfill,而最近我用了一个新的vue-cli3构建的项目,在兼容低版本安卓浏览器时遇到的问题,做一下记录。

一、babel-polyfill
IE 11版本浏览器不支持ES6百分之85%的语法规范,在vue项目中选择使用babel-polyfill兼容语法。

(1)安装babel-polyfill

npm install babel-polyfill --save-dev

(2)main.js

import 'babel/polyfill'

或者

import '@babel/polyfill'

这里尽可能在首行引入;注意一下node_module中polyfill的文件路径,有的可能是 import '@babel/polyfill' 这种情况。

(3)babel.config.js
配置内容如下:

module.exports = {
  presets: [
    ['@vue/app', {
      useBuiltIns: 'entry'
    }]
  ]
}

(4)vue.config.js
链式webpack配置函数,配置内容如下:

// module.exports内添加
chainWebpack (config) {
  config.entry('main').add('babel-polyfill')
}

vue项目实战:封装websocket请求(转载)

项目中需要用到websocket,网上找到一个简单又感觉还不错的封装,怕丢失了,特转载如下:
本文转载链接:https://blog.csdn.net/m0_38134431/article/details/105794108

前言:
如果项目中多个组件都使用到WebSocket请求,那么我们需要对WebSocket进行封装,方便我们使用。
下面我根据我的项目结构来创建文件和引入文件,大家注意一下自己项目结构。

一、在utils目录下创建websocket.js文件

import { Message } from 'element-ui'
import { getToken } from '@/utils/authToken' // 与后端的协商,websocket请求需要带上token参数
let websock = null
let messageCallback = null
let errorCallback = null
let wsUrl = ''

// 接收ws后端返回的数据
function websocketonmessage (e) { 
  messageCallback(JSON.parse(e.data))
}

/**
 * 发起websocket连接
 * @param {Object} agentData 需要向后台传递的参数数据
 */
function websocketSend (agentData) {
  // 加延迟是为了尽量让ws连接状态变为OPEN   
  setTimeout(() => { 
    // 添加状态判断,当为OPEN时,发送消息
    if (websock.readyState === websock.OPEN) { // websock.OPEN = 1 
      // 发给后端的数据需要字符串化
      websock.send(JSON.stringify(agentData))
    }
    if (websock.readyState === websock.CLOSED) { // websock.CLOSED = 3 
      console.log('websock.readyState=3')
      Message.error('ws连接异常,请稍候重试')
      errorCallback()
    }
  }, 500)
}

// 关闭ws连接
function websocketclose (e) {  
  // e.code === 1000  表示正常关闭。 无论为何目的而创建, 该链接都已成功完成任务。
  // e.code !== 1000  表示非正常关闭。
  if (e && e.code !== 1000) {
    Message.error('ws连接异常,请稍候重试')
    errorCallback()
  }
}
// 建立ws连接
function websocketOpen (e) {
  // console.log('ws连接成功')
}

// 初始化weosocket
function initWebSocket () { 
  if (typeof (WebSocket) === 'undefined') {
    Message.error('您的浏览器不支持WebSocket,无法获取数据')
    return false
  }

  const token = 'JWT=' + getToken()
  // ws请求完整地址
  const requstWsUrl = wsUrl + '?' + token
  websock = new WebSocket(requstWsUrl)

  websock.onmessage = function (e) {
    websocketonmessage(e)
  } 
  websock.onopen = function () {
    websocketOpen()
  }
  websock.onerror = function () {
    Message.error('ws连接异常,请稍候重试')
    errorCallback()
  }
  websock.onclose = function (e) {
    websocketclose(e)
  } 
}

/**
 * 发起websocket请求函数
 * @param {string} url ws连接地址
 * @param {Object} agentData 传给后台的参数
 * @param {function} successCallback 接收到ws数据,对数据进行处理的回调函数
 * @param {function} errCallback ws连接错误的回调函数
 */
export function sendWebsocket (url, agentData, successCallback, errCallback) { 
  wsUrl = url
  initWebSocket()
  messageCallback = successCallback
  errorCallback = errCallback
  websocketSend(agentData)
}

/**
 * 关闭websocket函数
 */
export function closeWebsocket () {
  if (websock) {
    websock.close() // 关闭websocket
    websock.onclose() // 关闭websocket
  }
}

二、在vue组件中使用WebSocket封装好的功能

<template>
  <div>
    <button @click="requstWs">点击发起websocket请求</button>
  </div>
</template>
<script>
import { sendWebsocket, closeWebsocket } from '@/utils/websocket.js'

export default {
  beforeDestroy () {
    // 页面销毁时关闭ws。因为有可能ws连接接收数据尚未完成,用户就跳转了页面
    // 在需要主动关闭ws的地方都可以调用该方法
    closeWebsocket()
  },
  methods: {
    // ws连接成功,后台返回的ws数据,组件要拿数据渲染页面等操作
    wsMessage (data) {
      const dataJson = data
      console.log(dataJson)
      // 这里写拿到数据后的业务代码
    },
    // ws连接失败,组件要执行的代码
    wsError () {
      // 比如取消页面的loading
    },
    requstWs () {
      // 防止用户多次连续点击发起请求,所以要先关闭上次的ws请求。
      closeWebsocket()
      // 跟后端协商,需要什么参数数据给后台
      const obj = {
        monitorUrl: 'xxxxxxxxxxxxx',
        userName: 'xxxxxxxxxx'
      }
      // 发起ws请求
      sendWebsocket('ws://test.ws.com', obj, this.wsMessage, this.wsError)
    }
  }
}
</script>

介绍WebSocket对象中的readyState属性
WebSocket的readyState属性用来定义连接状态,该属性的值有下面几种:

0 :对应常量 CONNECTING
正在建立连接连接,还没有完成。
1 :对应常量 OPEN
连接成功建立,可以进行通信。
2 :对应常量 CLOSING
连接正在进行关闭握手,即将关闭。
3 : 对应常量 CLOSED
连接已经关闭或者根本没有建立。

介绍WebSocket断开连接onclose的重要信息错误状态码
WebSocket断开时,会触发CloseEvent, CloseEvent会在连接关闭时发送给使用 WebSockets 的客户端. 它在 WebSocket 对象的 onclose 事件监听器中使用。CloseEvent的code字段表示了WebSocket断开的原因。可以从该字段中分析断开的原因。

CloseEvent有三个字段需要注意, 通过分析这三个字段,一般就可以找到断开原因。

CloseEvent.code: code是错误码,是整数类型
CloseEvent.reason: reason是断开原因,是字符串
CloseEvent.wasClean: wasClean表示是否正常断开,是布尔值。一般正常断开时,该值为true

如下是在关闭ws连接的时候打印出来的CloseEvent对象:

关闭状态码表
下面标红的状态码是我在项目中测试遇到过的。

状态码 描述
0–999 保留段, 未使用
1000 正常关闭; 无论为何目的而创建, 该链接都已成功完成任务.
1001 终端离开, 可能因为服务端错误, 也可能因为浏览器正从打开连接的页面跳转离开.
1002 由于协议错误而中断连接.
1003 由于接收到不允许的数据类型而断开连接 (如仅接收文本数据的终端接收到了二进制数据).
1004 保留. 其意义可能会在未来定义.
1005 保留. 表示没有收到预期的状态码.
1006 保留. 用于期望收到状态码时连接非正常关闭 (也就是说, 没有发送关闭帧).
1007 由于收到了格式不符的数据而断开连接 (如文本消息中包含了非 UTF-8 数据).
1008 由于收到不符合约定的数据而断开连接. 这是一个通用状态码, 用于不适合使用 1003 和 1009 状态码的场景.
1009 由于收到过大的数据帧而断开连接.
1010 客户端期望服务器商定一个或多个拓展, 但服务器没有处理, 因此客户端断开连接.
1011 客户端由于遇到没有预料的情况阻止其完成请求, 因此服务端断开连接.
1012 服务器由于重启而断开连接.
1013 服务器由于临时原因断开连接, 如服务器过载因此断开一部分客户端连接.
1014 由 WebSocket标准保留以便未来使用.
1015 保留. 表示连接由于无法完成 TLS 握手而关闭 (例如无法验证服务器证书).
1016–1999 由 WebSocket标准保留以便未来使用.
2000–2999 由 WebSocket拓展保留使用.
ps: 其他注意事项
如果你的服务所用的协议是HTTPS的,那么使用的WebSocket协议也必须是wss, 而不能是ws

参考资料链接:
https://www.cnblogs.com/scott-j/p/9306197.html
https://segmentfault.com/a/1190000014582485?utm_source=tag-newest
https://blog.csdn.net/qq_39186346/article/details/81941664

vue watch 同时监听对象多个属性,调用同一个方法

比如说有个对象:

let form = {
    name: "xx",
    sex: "yy",
    type: "aa"
}

要求是修改name或者aa的时候,都调用 AABBCC 方法,但type修改的时候不能调用。
如果直接watch,那么肯定不能直接deep监听form对象了,因为type修改时不能调用。所以只能这样:

watch:{
    'form.name'(){
        this.AABBCC()
    },
    'form.sex'(){
        this.AABBCC()
    }
}

对象多的话,会感觉很难受,所以我们可以借用computed换换脑子:

computed:{
    formWatch: function(){
        let _arr = []
        _arr.push(this.form.name)
        _arr.push(this.form.sex)
        return _arr.join(",")
    }
},
watch:{
    formWatch(){
        this.AABBCC()
    }
}

这显然感觉舒服多了,哈哈

转载:JS二维数组排列组合,列出所有结果

最近做一个项目,碰到一个根据数组,列出所有相关排列组合的内容的需求。
百度搜出如下解决方案,非常精简强悍,比自己罗里吧嗦写了一堆的好太多了,记录分享。

let array1 = [
    ['红', '绿', '蓝'],
    ['A', 'B', 'C'],
    ['S', 'M', 'L'],
]

let array2 = [
    ['红', '蓝'],
    ['A', 'B', 'C'],
    ['S'],
]

let array3 = [
    ['红', '绿', '蓝'],
]

function calc(transArr) {
    let resultArr = [];
    function get(array, index, val) {
        if(!array[index]) {
            resultArr.push(val);
            return;
        };

        array[index].forEach((v, i) => {
            get(array, index + 1, index === 0 ? [v] : [...val, v])
        })
    }
    get(transArr, 0);
    return resultArr;
}

console.log(calc(array1));
console.log(calc(array2));
console.log(calc(array3));

原文链接:https://blog.csdn.net/qq1073830130/article/details/101017851

禁止chrome谷歌浏览器表单自动填充,新版chrome的autocomplete设置无效的处理方法

网上最常见的方式,是设置autocomplete='off',但这种方式已经无效啦。

还有种方式是:

<input type="text"  style="display: none;" autocomplete = "off"/>
<input type="password"  style="display: none;" autocomplete = "off"/>

每个表单都要配置,特别麻烦。而且最近也失效了。

经过很长时间测试,我发现可以在vue、react、angular的情况下,可以用一个一劳永逸的方式,就是再入口文件,如vue的App.vue文件下,写这么一段:

    <!-- 防止chrome自动填充 -->
    <div style="position:absolute;top:-999999px">
      <input type="text" />
      <input type="password" />
    </div>

然后你页面上所有的表单都不会被填充啦,超赞的