首页
更多应用
Search
1
修改iview的标签为i-的形式而不是驼峰的形式
2,791 阅读
2
PHP微信和企业微信签名
2,522 阅读
3
在VUE中怎么全局引入sass文件
2,223 阅读
4
vscode硬件占用较高解决方案
2,017 阅读
5
解决Macos下storm系列IDE卡顿的问题
1,975 阅读
默认分类
JS
VUE
CSS
mac使用技巧
React
fastmock
登录
/
注册
Search
标签搜索
react
js
vue
vscode
nodejs
项目
代码
webpack
工具
nginx
小程序
css
fastmock
eslint
npm
http
vue-cli3
git
浏览器
const
fastmock技术社区
累计撰写
102
篇文章
累计收到
26
条评论
首页
栏目
默认分类
JS
VUE
CSS
mac使用技巧
React
fastmock
页面
更多应用
搜索到
102
篇与
的结果
2019-03-03
小程序wxs中的时间格式化以及格式化时间和date时间互转
WXS(WeiXin Script)是小程序的一套脚本语言,wxs 与 javascript 是不同的语言,有自己的语法,并不和 javascript 一致。其中包括了很多日常使用的javascript函数,在wxs中都是不能同样使用的。最近在做一个列表的时候,涉及到时间格式化操作。就遇到了这个问题,以前写好了的格式化工具函数直接拷贝到小程序项目的wxs文件中,函数不能正常执行。其中包括了下面的几个错误正则表达式在字符串的replace函数中的使用方法不一样,不能直接使用var a = /[0-9]/这种方式声明使用。正确的方式为var reg = getRegExp("-", "g");获取当前时间不能通过new Date()获取,而是通过getDate方法获取。getDate('2018/12/12')可以获取对应日期的date类型的时间。按照上面的异同,修改过后的时间格式化函数代码为var formatNumber = function (n) { n = n.toString() return n[1] ? n : '0' + n } var regYear = getRegExp("(y+)", "i"); var dateFormat = function (timestamp, format) { if (!format) { format = "yyyy-MM-dd hh:mm:ss"; } timestamp = parseInt(timestamp); // 通过getDate()方法获取date类型的时间 var realDate = getDate(timestamp); function timeFormat(num) { return num < 10 ? '0' + num : num; } var date = [ ["M+", timeFormat(realDate.getMonth() + 1)], ["d+", timeFormat(realDate.getDate())], ["h+", timeFormat(realDate.getHours())], ["m+", timeFormat(realDate.getMinutes())], ["s+", timeFormat(realDate.getSeconds())], ["q+", Math.floor((realDate.getMonth() + 3) / 3)], ["S+", realDate.getMilliseconds()], ]; var reg1 = regYear.exec(format); // console.log(reg1[0]); if (reg1) { format = format.replace(reg1[1], (realDate.getFullYear() + '').substring(4 - reg1[1].length)); } for (var i = 0; i < date.length; i++) { var k = date[i][0]; var v = date[i][1]; // getRegExp初始化一个正则表达式对象 var reg2 = getRegExp("(" + k + ")").exec(format); if (reg2) { format = format.replace(reg2[1], reg2[1].length == 1 ? v : ("00" + v).substring(("" + v).length)); } } return format; }把格式化的日期时间字符串转换成时间戳function parse(fmt) { fmt1 = fmt.substring(0, 19); var reg = getRegExp("-", "g"); fmt2 = fmt1.replace(reg, '/'); var timestamp = getDate(fmt2).getTime(); return timestamp; }调用方法如下function getDateByDateTimeFmt(dateTimeFmt) { return dateFormat(parse(dateTimeFmt), 'MM月dd日'); } getDateByDateTimeFmt('2012-12-12 13:12:12') // => 12月12日
2019年03月03日
760 阅读
0 评论
0 点赞
2019-02-01
HTTP常见状态码
HTTP常见状态码200 OK 服务器成功处理了请求(这个是我们见到最多的)204 No Content 请求成功处理,没有实体的主体返回206 Partial Content GET范围请求已成功处理301/302 Moved Permanently(重定向)请求的URL已移走。Response中应该包含一个Location URL, 说明资源现在所处的位置303 See Other 临时重定向,期望使用GET定向获取304 Not Modified 发送的附带条件请求未满足307 Temporary Redirect 临时重定向,POST不会变成GET400 Bad Request 请求报文语法错误或参数错误401 Unauthorized 需要通过HTTP认证,或认证失败403 Forbidden 请求资源被拒绝404 Not Found(页面丢失)未找到资源500 Internal Server Error 服务器故障或Web应用故障501 Internal Server Error服务器遇到一个错误,使其无法对请求提供服务503 Service Unavailable 服务器超负载或停机维护HTTP状态码(HTTP Status Code)是用以表示网页服务器HTTP响应状态的3位数字代码。 状态码响应类别原因短语 1XX信息性状态码(Informational)服务器正在处理请求 2XX成功状态码(Success)请求已正常处理完毕 3XX重定向状态码(Redirection)需要进行额外操作以完成请求 4XX客户端错误状态码(Client Error)客户端原因导致服务器无法处理请求 5XX服务器错误状态码(Server Error)服务器原因导致处理请求出错 1开头 (请求已被接受,需要继续处理)这类响应是临时响应,只包含状态行和某些可选的响应头信息,并以空行结束。100 (部分接受) 客户端应当继续发送请求。这个临时响应是用来通知客户端它的部分请求已经被服务器接收,且仍未被拒绝。 101 (已了解) 服务器已经理解了客户端的请求,并将通过Upgrade 消息头通知客户端采用不同的协议来完成这个请求。102 (已接收) 由WebDAV(RFC 2518)扩展的状态码,代表处理将被继续执行。2开头 (请求成功)表示成功处理了请求的状态代码。200 (成功) 服务器已成功处理了请求。 通常,这表示服务器提供了请求的网页。 201 (已创建) 请求成功并且服务器创建了新的资源。 202 (已接受) 服务器已接受请求,但尚未处理。 203 (非授权信息) 服务器已成功处理了请求,但返回的信息可能来自另一来源。 204 (无内容) 服务器成功处理了请求,但没有返回任何内容。 205 (重置内容) 服务器成功处理了请求,但没有返回任何内容。206 (部分内容) 服务器成功处理了部分 GET 请求。3开头 (请求被重定向)表示要完成请求,需要进一步操作。 通常,这些状态代码用来重定向。300 (多种选择) 针对请求,服务器可执行多种操作。 服务器可根据请求者 (user agent) 选择一项操作,或提供操作列表供请求者选择。 301 (永久移动) 请求的网页已永久移动到新位置。 服务器返回此响应(对 GET 或 HEAD 请求的响应)时,会自动将请求者转到新位置。302 (临时移动) 服务器目前从不同位置的网页响应请求,但请求者应继续使用原有位置来进行以后的请求。303 (查看其他位置) 请求者应当对不同的位置使用单独的 GET 请求来检索响应时,服务器返回此代码。304 (未修改) 自从上次请求后,请求的网页未修改过。 服务器返回此响应时,不会返回网页内容。 305 (使用代理) 请求者只能使用代理访问请求的网页。 如果服务器返回此响应,还表示请求者应使用代理。 307 (临时重定向) 服务器目前从不同位置的网页响应请求,但请求者应继续使用原有位置来进行以后的请求。4开头 (请求错误)这些状态代码表示请求可能出错,妨碍了服务器的处理。400 (错误请求) 服务器不理解请求的语法。 401 (未授权) 请求要求身份验证。 对于需要登录的网页,服务器可能返回此响应。 403 (禁止) 服务器拒绝请求。404 (未找到) 服务器找不到请求的网页。405 (方法禁用) 禁用请求中指定的方法。 406 (不接受) 无法使用请求的内容特性响应请求的网页。 407 (需要代理授权) 此状态代码与 401(未授权)类似,但指定请求者应当授权使用代理。408 (请求超时) 服务器等候请求时发生超时。 409 (冲突) 服务器在完成请求时发生冲突。 服务器必须在响应中包含有关冲突的信息。 410 (已删除) 如果请求的资源已永久删除,服务器就会返回此响应。 411 (需要有效长度) 服务器不接受不含有效内容长度标头字段的请求。 412 (未满足前提条件) 服务器未满足请求者在请求中设置的其中一个前提条件。 413 (请求实体过大) 服务器无法处理请求,因为请求实体过大,超出服务器的处理能力。 414 (请求的 URI 过长) 请求的 URI(通常为网址)过长,服务器无法处理。 415 (不支持的媒体类型) 请求的格式不受请求页面的支持。 416 (请求范围不符合要求) 如果页面无法提供请求的范围,则服务器会返回此状态代码。 417 (未满足期望值) 服务器未满足"期望"请求标头字段的要求。5开头(服务器错误)这些状态代码表示服务器在尝试处理请求时发生内部错误。 这些错误可能是服务器本身的错误,而不是请求出错。500 (服务器内部错误) 服务器遇到错误,无法完成请求。 501 (尚未实施) 服务器不具备完成请求的功能。 例如,服务器无法识别请求方法时可能会返回此代码。 502 (错误网关) 服务器作为网关或代理,从上游服务器收到无效响应。 503 (服务不可用) 服务器目前无法使用(由于超载或停机维护)。 通常,这只是暂时状态。 504 (网关超时) 服务器作为网关或代理,但是没有及时从上游服务器收到请求。 505 (HTTP 版本不受支持) 服务器不支持请求中所用的 HTTP 协议版本。转载原文:https://blog.csdn.net/lhjuejiang/article/details/79474199
2019年02月01日
1,189 阅读
0 评论
0 点赞
2019-01-29
基于es6 proxy的单向数据绑定
看了一些关于vue3.0的更新内容,主要是围绕性能方面的提升和对MVVM数据绑定的完全重写。3.0中不再使用 Object.defineProperty 而是原生ES6 Proxy,关于ProxyProxy 用于修改某些操作的默认行为,等同于在语言层面做出修改,所以属于一种“元编程”(meta programming),即对编程语言进行编程。Proxy 可以理解成,在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。Proxy 这个词的原意是代理,用在这里表示由它来“代理”某些操作,可以译为“代理器”。在vue2.x中,使用Object.defineProperty实现数据劫持。一般的做法如下:let obj = {}; // 遍历data的所有属性 let dataKeys = Object.keys(data); dataKeys.map(key => { // 为data的所有属性添加set方法 Object.defineProperty(data, key, { set: function(newVal) { // 修改v-text属性对应的data中的key的值 document.querySelector(el + " *[v-text=" + key + "]").textContent = newVal; } }); }); // 将处理好的data赋值给要返回的对象 obj.data = data; return obj;上面的代码中可以看出,主要有两个问题:要为对象的每一个属性添加数据劫持,一般结合Object.keys()遍历对象属性实现。如果对象的层级结构不是简单的层级结构,只能一直遍历处理。不能监听数组的变化,数组的push, pop, shift, unshift, splice, sort, reverse等方法不会触发set的侦听。我们在使用vue修改数组时能触发view的更新是因为vue内部做了变相的处理。针对Vue 3.0的这个更新,做了一个简单的单向数据绑定的例子,说明3.0中使用Proxy实现数据绑定的基本原理(只是简单的单向绑定,数据的更改会反映到视图上)<div id="app"> <h1 v-text="title"></h1> <p>当前时间:<span v-text="time"></span></p> </div>function ViewBind({ el = 'body', data = {}} = {}) { // 要返回的对象实例 let obj = {}; const proxy = new Proxy(data, { get(obj, property) { return obj[property] }, set(obj, property, newValue) { obj[property] = newValue; const bindEle = document.querySelector(el + " *[v-text=" + property + "]"); if (bindEle) { bindEle.textContent = newValue; } } }); obj.data = proxy; return obj; }; const app = new ViewBind({ el: '#app', data: { count: 0, title: '这是标题', time: +new Date() } }); setInterval(() => { // 定时修改页面上<span v-text="time">元素中的内容 app.data.time = +new Date(); app.data.count = app.data.count + 1; app.data.title = '这是标题' + app.data.count; }, 1000)上面的代码中通过ViewBind实例化了一个对象,定时修改对象的属性,视图上通过v-text绑定的内容就会自动更新,效果如下
2019年01月29日
276 阅读
0 评论
0 点赞
2019-01-29
推荐一个js常用工具函数库
etools常用js函数整理安装和使用使用npm安装:npm install -s etools通过es6模块引入,如import _ from "etools";console.log(_.extend(true,{},{"age":23}));下载并在页面引入etools.js直接调用ETool对象中得方法,如console.log(ETools.extend(true,{},{"age":23}));Git 仓库地址 https://github.com/MarvenGong/ETools版本说明1.2.8 新增datetime下根据身份证号码获取年龄的方法getAgeByIDCard1.2.7 新增datetime下根据出生日期获取年龄的方法getAgeByBirthday1.2.5 新增async相关函数用来处理异步函数常用方法1.2.3 修正了部分bug,新增array数组扩展,增加Array.filterBy方法1.2.2 修正了部分bug,新增string下的generateUUID和addNum方法1.0.9 修正了deparam函数依赖jquery的$.each函数的问题详细文档对象相关ETools.extend(deep,obj1,obj2)作用:类似于jquery.extend方法,合并json对象,并将合并后的对象保存到obj1中作为返回值参数: 1. deep,是否深度复制,设为true,会复制对象中嵌套的对象。 2. obj1,obj2,要合并的对象 案例:ETools.extend(true,{"name":"zhangsan",gender:"male"},{"age":12}) 输出结果`{"name":"zhangsan",gender:"male","age":12}` 说明,我们可以将obj1设为空{},用这个方法克隆一个对象,解决引用类型赋值的问题url请求相关ETools.deparam(str)将jquery序列化表单之后得到的参数字符串转换成标准的json对象str,即要格式化的字符串ETools.deparam("aaa=bbb&ccc=ddd")输出结果{aaa:bbb,ccc:ddd}查看演示>>ETools.urlParamToObj(url)将连接中的get请求参数转换成json对象url:链接ETools.deparam("www.baidu.com?aaa=bbb&ccc=ddd")输出结果{aaa:bbb,ccc:ddd}事件ETools.stopPropagation(event)阻止事件向上冒泡,点击某元素不会触发父元素的事件event:事件对象ETools.stopPropagation(event)异步函数相关ETools.async.wait(timestamp)在异步函数中等待指定的时间timestamp 等待的时间的毫秒数async getUserList() { await ETools.async.wait(2000)}时间日期相关ETools.datetime.compareDate(starate,endDate)比较两个日期的大小日期格式"yyyy-mm-dd",如果返回值为-1,则前者大于后者,为0两者相等,为1,后者大于前者ETools.datetime.compareDate("2015-12-11","2015-12-12")ETools.datetime.compareTime(startTime,endTime)比较两个时间的大小日期格式"yyyy-mm-dd h:mi:s",如果返回值为-1,则前者大于后者,为0两者相等,为1,后者大于前者ETools.datetime.compareDate("2015-12-11 12:10:00","2015-12-12 12:10:00")ETools.datetime.arriveTimerFormat(s)将秒数转换成对应的多少小时,多少分多少秒(用于倒计时的显示)s:要计算的秒数ETools.datetime.arriveTimerFormat(52010)->[0, 14, 26, 50, "14:26:50"]ETools.datetime.format(date,formatStr)将Date类型的时间转换成指定格式的字符串date:日期类型的对象(如:new Data())formatStr:想要的时间格式如:"yyyy-mm-dd h:m:s 星期w"ETools.datetime.Format(new Date(),"yyyy-MM-dd h:m:s 星期w")->"2015-16-24 15:16:15 星期四"ETools.datetime.parse(timeStr)将时间字符串转换成对应的时间戳timeStr:时间字符串(如:"2015-16-24 15:16:15")ETools.datetime.parse("2015-16-24 15:16:15")->1461482175ETools.datetime.getNewDay(dataStr,addNumber)日期加上天数得到新的日期dateTemp 需要参加计算的日期,days要添加的天数,返回新的日期,日期格式:YYYY-MM-DD参数:dataStr原来的日期(如:“2014-12-1”)addNumber要增加或减少的天数,减少就给负数值如:ETools.datetime.getNewDay("2017-12-1",2) -- "2017-12-3"ETools.datetime.getNewDay("2017-12-1",-2) -- "2017-11-29"ETools.datetime.getAgeByBirthday(birthdatStr)根据出生日期获取年龄birthdatStr 出生日期标准格式的字符串 如:1991-08-20ETools.datetime.getAgeByBirthday("1991-08-20") -- 27ETools.datetime.getAgeByIDCard(idcard)根据出生日期获取年龄 如果传入的不是标准的身份证则返回falseidcard 身份证号 如:"*19951208x"ETools.datetime.getAgeByIDCard("*19951208x") -- 23html格式操作ETools.html.htmlEncode(str)把html中的常见符号转换成特殊符号码,如"<"转换成"<"参数str,要转换的html代码ETools.html.htmlDecode(str)把html代码转换成html元素参数str,要转换的html字符串页面操作ETools.page.addFavorite(url,title)将页面添加到浏览器收藏夹url:要添加的地址信息。title:在收藏夹中的名字ETools.page.addFavorite("www.baidu.com","百度")ETools.page.addHome(url)将页面设为浏览器的首页url:要添加的地址信息。ETools.page.addFavorite("www.baidu.com")动态加载ETools.loadStyle(styleUrl)动态加载样式表styleUrl:要加载的样式文件的地址ETools.loadStyle("css/style.css")浏览器信息获取ETools.getExplorerInfo()返回浏览器的名称以及版本信息{browerName:"google",version:"3.10.101.1"}字符串操作ETools.string.getStrLength(str)获取字符串长度,中文字符按两个长度计算str:要计算的字符串ETools.string.getStrLength("ilove你")->7ETools.string.trim(str)去掉字符串左右的空格str:要去空格的字符串ETools.string.getStrLength(" aaa ")->"aaa"ETools.string.number2String(number)参数 number : 要转换的数字把1,2,3,4....,99999 类型的数字转换成中文字符串如:ETools.string.number2String(123) -> “一百二十三”ETools.string.generateUUID()生成一个唯一标识的字符串(UUID算法)ETools.string.addNum(number1, number2)参数 number1;number2 : 要相加的两个数字包含浮点数的两个数相加,解决丢失精度的问题如:ETools.string.addNum(1.1, 1.2) -> “2.3” 如果直接执行1.1+1.2会出现等于2.299999999999999999999的情况表单验证ETools.vertify.isURL(str)验证url地址ETools.vertify.isURL("www.baidu.com")->trueETools.vertify.isEmpty(str)验证是否为空ETools.vertify.isEmpty(" ")->trueETools.vertify.isDigit(str)验证是否是数字ETools.vertify.isDigit("2.0")->falseETools.vertify.isTelephone(str)验证固定电话ETools.vertify.isTelephone("023-55813950")->trueETools.vertify.isMobile(str)验证手机号码ETools.vertify.isMobile("15696544221")->trueETools.vertify.isQQ(str)验证QQ号ETools.vertify.isQQ("1634251421")->trueETools.vertify.isEmail(str)验证邮箱地址ETools.vertify.isEmail("2542152@qq.com")->trueETools.vertify.isIDCard(str)验证身份证号码ETools.vertify.isIDCard("500235199008205570")->true ETools.vertify.isPlusDigit(str)验证是否是无符号正整数ETools.vertify.isPlusDigit("52")->trueETools.vertify.isChinese(str)验证中文字符ETools.vertify.isChinese("我爱你")->true ETools.vertify.isDate(str)验证日期ETools.vertify.isDate("2015-12-12")->trueETools.vertify.isPostalCode(str)验证邮政编码ETools.vertify.isPostalCode("400521")->trueETools.vertify.isRegisterUserName(str)验证登录名,只能输入5-20个以字母开头、可带数字、“_”、“.”的字串ETools.vertify.isRegisterUserName("gong163")->true ETools.vertify.isTrueName(str)校验用户姓名:只能输入1-30个以字母开头的字串ETools.vertify.isTrueName("龚明华")->trueETools.vertify.isPassword(str)校验密码:只能输入6-20个字母、数字、下划线ETools.vertify.isPassword("gong1632542142")->true数组相关Array.filterBy(key, value) 从对象数组中根据对象的key筛选值等于value的对象,如果键值对唯一则返回对象,如果不唯一则返回对象数组。key: 对象中的键,value: 要筛选的键所对应的值[{name: '张三',age: 12},{name: '张三',age: 33},{name: 'lisi',age: 22}].filterBy('name', '张三') -> [{name: '张三',age: 12},{name: '张三',age: 33}];Cookie操作ETools.cookie.setCookie(name, value, Hours)设置Cookie值name:cookie的key,value:cookie的value,Hours:Cookie的超时时间ETools.cookie.setCookie("username", "xiaoming", 0.5)ETools.cookie.getCookie(name)获取Cookie值name:cookie的keyETools.cookie.getCookie("username")->"xiaoming"ETools.cookie.delCookie(name)删除Cookiename:cookie的keyETools.cookie.delCookie("username")html格式操作ETools.openWindow(url,windowName,width,height)打开一个弹窗窗口url打开的链接,windowName窗口的title,width窗口宽度,height窗口高度ETools.openWindow("www.baidu.com","百度",500,600)jquery插件checkAll()表格的行的全选和反全选$(".checkAll").checkAll();需要给复选框绑定checkAll()事件。为其加上data-table属性,属性值指向要执行全选的table的id。如果有多个复选框共同作用于同一个表格,给这些复选框加上相同的data-table属性值即可
2019年01月29日
928 阅读
0 评论
0 点赞
2019-01-28
推荐一个在线接口Mock工具fastmock
如果想直接进入实战请猛戳这里fastmock线上地址www.fastmock.sitefastmock可以让你在没有后端程序的情况下能真实地在线模拟ajax请求,你可以用fatmock实现项目初期纯前端的效果演示,也可以用fastmock实现开发中的数据模拟从而实现前后端分离。如下面的接口模拟一个用户列表https://www.fastmock.site/mock/871b3e736e653b99374b7713e4011f9f/boss/user/list模拟各种特殊类型的数据https://www.fastmock.site/mock/871b3e736e653b99374b7713e4011f9f/boss/user/list2您可以直接在浏览器打开上面的链接或者用ajax请求查看返回的数据在使用fastmock之前,你的团队实现数据模拟可能是下面的方案中的一种或者多种本地手写数据模拟,在前端代码中产生一大堆的mock代码。利用mockjs或者canjs的can-fixture实现ajax拦截,本地配置必要的json规则。后端在Controller层造假数据返回给前端。上面的方式中,不管哪一种方式,都会要求开发人员写一些跟项目本无任何关联的代码,第一个和第二个方式还会需要前端项目在本地引入不必要的js文件。比如下面的mock数据// 产品配置 { url: '/pms/product/list', on: true, type: 'get', resp: Mock.mock({ 'body': { 'currentPage': 1, 'isMore': 0, 'pageSize': 15, 'resultList|10': [ { 'productNo': '11111', 'productName|1': ['产品名称1', '产品名称2', '产品名称3', '产品名称4', '产品名称5'], 'productType|1': ['1', '2', '3', '4', '5'], 'status|1': ['1', '2'], 'gmtCreate': '@DATETIME("yyyy-MM-dd HH:mm:ss")', 'gmtModified': '@now("yyyy-MM-dd HH:mm:ss")', 'createUserCode': '@name' } ], 'startIndex': 0, 'totalNum': 100, 'totalPage': 1 }, 'reCode': '0000', 'reMsg': '成功', 'success': true }) }, // 产品配置-贷款材料配置 { url: '/pms/cfgLoanDoc/list', on: true, resp: Mock.mock({ 'body': { 'currentPage': 1, 'isMore': 0, 'pageSize': 15, 'resultList|10': [ { 'loanDocCode|+1': 1, 'loanDocName': /[测试字体]{4,30}/ } ], 'startIndex': 0, 'totalNum': 100, 'totalPage': 1 }, 'reCode': '0000', 'reMsg': '成功', 'success': true }) }上面的代码为mockjs的事例代码,更多mockjs相关资料参考链接mockjs文档为此,我们将mock层独立出来,通过中间服务的形式在前端和后端服务之前建立一道围栏,使用fastmock,前端只需要修改自己的XHR请求地址,后端只需要在开发前和前端约定好接口文档即可。等到后端服务开发完成,前端再将XHR请求地址替换回来进行联调测试即可。tip:当然,你也可以通过npm script不同命令加载不同配置文件的形式切换你的XHR地址,这里不作详细介绍。还是不了解fastmock?让我们跟着教程一探究竟吧了解并开始使用fastmock
2019年01月28日
1,316 阅读
0 评论
0 点赞
2019-01-22
强大的Array.prototype.splice()
之所以会单独针对这个api写这么一篇博文,一方面是因为最近在一次面试中聊到了这个API,我没能完全说出它的用法;另一方面则是因为通过熟悉后觉得这个api确实很灵活很强大,充分体现了javascript的灵活性。所以写这么一篇博文,可以让自己更深刻地记住这个方法,也希望能让更多地同仁用这个方法让自己的javascript代码更加简洁,更加有效率。MDN Web Docs中对Array.prototype.splice()的描述信息如下splice(start, deleteCount, item1, item2, ...) 方法通过删除或替换现有元素和/或添加新元素来更改数组的内容。传参信息如下1. start 从什么位置开始修改当前数组,这个参数有如下几种情况0到数组长度-1,即当前数组的任意位置。大于数组长度-1,不报错,但是不会删除当前数组的元素,第二个参数无效。但是,如果这个时候传入了第三个,以及第四个。。。参数,那么,这些参数值会被添加到数组的末尾位置,也就类似于push方法。小于0,如果开始位置为负数,会从数组的末尾倒着查找,如,-1为最后一个元素,-2为倒数第二个元素。2. deleteCount 要删除的内容的长度,这个参数有如下几种情况0或负数 不删除数组元素。大于0并且小于start指定位置到数组最后一个元素的长度,则删除指定长度的元素。大于start指定位置到数组最后一个元素的长度,删除从start位置后面所有的元素,如splice(0, 99999999)会晴空长度小于99999999的数组3. 在start位置开始要添加或者替换的元素,可以有多个。针对上面的描述,我们一一验证它的所有用法。删除元素(第二个参数不为0,后续参数不传入,只删除)let ary = ['a', 'b', 'c', 'd', 'e', 'f']; ary.splice(1, 1); // 从第二个位置开始删掉一个元素 console.log(ary); // ['a', 'c', 'd', 'e', 'f']let ary = ['a', 'b', 'c', 'd', 'e', 'f']; ary.splice(1, 2); // 从第二个位置开始删掉两个元素 console.log(ary); // ['a', 'd', 'e', 'f']let ary = ['a', 'b', 'c', 'd', 'e', 'f']; ary.splice(-2, 1); // 删掉倒数第二个元素‘e’ console.log(ary); // ['a', 'b', 'c', 'd', 'f']let ary = ['a', 'b', 'c', 'd', 'e', 'f']; ary.splice(0, ary.length); // 删掉所有元素 console.log(ary); // []添加元素(第二个参数为0,后续参数不为空,则只增加不删除)let ary = ['a', 'b', 'c', 'd', 'e', 'f']; ary.splice(ary.length, 0, 'x'); // 在数组末尾追加一个元素 console.log(ary); // ['a', 'b', 'c', 'd', 'e', 'f', 'x']let ary = ['a', 'b', 'c', 'd', 'e', 'f']; ary.splice(1, 0, 'x'); // 在数组第二个元素前插入一个元素 console.log(ary); // ['a','x', 'b', 'c', 'd', 'e', 'f']let ary = ['a', 'b', 'c', 'd', 'e', 'f']; ary.splice(-2, 0, 'x'); // 在数组倒数第二个元素前插入一个元素 console.log(ary); // ['a', 'b', 'c', 'd', 'x', 'e', 'f']let ary = ['a', 'b', 'c']; let ary2 = ['d', 'e', 'f'] ary.splice(ary.length, 0, ...ary2); // 数组拼接 console.log(ary); // ['a', 'b', 'c', 'd', 'e', 'f']更新/替换元素(第二个参数不为0,后续参数不为空,这里需要注意的是,传入的替换元素的个数可以等于前面的长度,也可以不等于前端的长度)替换元素其实执行的是先删除再插入,所以一定要清楚传入参数的意义let ary = ['a', 'b', 'c', 'd', 'e', 'f']; ary.splice(1, 1, 'x'); // 替换第二个元素‘b’为‘x’ (长度和传入的替换元素个数都为一) console.log(ary); // ['a', 'x', 'c', 'd', 'e', 'f']let ary = ['a', 'b', 'c', 'd', 'e', 'f']; ary.splice(1, 2, 'x'); // 删掉第二个和第三个元素‘b’ ‘c’,插入一个元素‘x’ (长度大于传入的替换元素个数) console.log(ary); // ['a', 'x', 'd', 'e', 'f']let ary = ['a', 'b', 'c', 'd', 'e', 'f']; ary.splice(1, 2, 'x', 'y', 'z'); // 删掉第二个和第三个元素‘b’ ‘c’,插入三个元素‘x’,‘y’, ‘z’ (长度小于传入的替换元素个数) console.log(ary); // ['a', 'x','y', 'z', 'd', 'e', 'f']上面这些就是我目前总结的常用的splice的用法,如有更多使用方法,欢迎留言讨论
2019年01月22日
851 阅读
0 评论
0 点赞
2019-01-12
一个来自create-react-app脚手架警告的思考
最近在开发一个react项目,项目是用create-react-app脚手架创建的,当我在我的项目的菜单栏中添加了一个打开一个外链的a标签时,我收到了一个来自create-react-app的警告信息,信息内容如下意思就是说“在没有rel="noopener noreferrer"属性的a标签中使用target="_blank"存在一定的风险”这个提示瞬间把我吸引了,以前关于a标签收到的提示都是没有设置alt属性啊什么的,但是也只是提示我说为了显示的友好什么的,这次竟然提示我有风险,面对这种问题,必须一探究竟啊。查阅了一些资料得到了如下关于a标签一个介绍当一个外部链接使用了target=_blank的方式,这个外部链接会打开一个新的浏览器tab。此时,新页面会打开,并且和原始页面占用同一个进程。这也意味着,如果这个新页面有任何性能上的问题,比如有一个很高的加载时间,这也将会影响到原始页面的表现。如果你打开的是一个同域的页面,那么你将可以在新页面访问到原始页面的所有内容,包括document对象(window.opener.document)。如果你打开的是一个跨域的页面,你虽然无法访问到document,但是你依然可以访问到location对象。不看不知道一看吓一跳有木有。主要是两个点是我以前从未在意的用target="_blank"方式打开的tab和原始页面占用同一个进程(UI进程)新打开的页面能获取到原始页面的document。第一个问题不用我说都知道是非常需要注意的,新的页面中的所有行为都会间接影响到原始页面的性能。这里主要研究第二个问题。为此,我做了小小的实验。上图解释:首先打开了第一个页面,第一个页面只有一个“打开一个新页面”的a标签点击这个链接,打开了一个新页面。新页面中有一个按钮,“告诉打开我的那个页面,我喜欢林志玲”。点击新页面的按钮然后回到第一个页面,发现第一个页面多出来了一排红色的文字“我喜欢林志玲”。停在第一个页面5s钟,第一个页面自动跳转到了百度首页。上面两个页面的代码分别如下:opener-test.html<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> </head> <body> <a target="_blank" href="test-opener-2.html">打开一个新页面</a> </body> </html>opener-test-2.html<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> </head> <body> <h1>我是新打开的页面</h1> <button type="button" id="btn">告诉打开我的那个页面,我喜欢林志玲</button> <script> document.getElementById('btn').addEventListener('click', function() { var _opener = window.opener; var p = _opener.document.createElement('p'); p.innerHTML = "我喜欢林志玲"; p.style.color = "#f33"; _opener.document.body.appendChild(p); setTimeout(function() { _opener.location.href = "//www.baidu.com"; }, 5000) }); </script> </body> </html>新的页面不仅往原始页面添加了一段话,而且还让他离开了原来的页面。注:在上面的例子中,两个页面位于同一个域下面,如果两个页面位于不同的域,那上面的第一个效果就是不行的,因为不同域的情况下,新页面拿不到opener对象的document,但是location对象是可以拿到的,所以第二个效果任然有效。怎么禁止上面的行为呢?按照create-react-app的提示信息,给连接加上rel属性,如下:<a rel="noopener noreferrer" target="_blank" href="https://marvengong.github.io/fastmock-docs/book/">上面的rel属性值多了一个noreferrer它的作用和noopener是一样的,只是适用于低版本的浏览器。这样处理后,新打开的页面的window对象上就没有opener和referrer对象了。
2019年01月12日
1,018 阅读
0 评论
0 点赞
2019-01-07
nodejs ORM框架sequelize.js实体常用配置
请输入图片描述const sequelize = require('../db/sequelize'); const Sequelize = require('sequelize'); const User = sequelize.define('user', { id: { type: Sequelize.INTEGER, field: 'id', primaryKey: true, autoIncrement: true }, username: Sequelize.STRING, password: Sequelize.STRING, email: Sequelize.STRING, nickname: Sequelize.STRING, createdAt: { type: Sequelize.DATE, field: 'created_at' }, updatedAt: { type: Sequelize.DATE, field: 'updated_at' }, }, { // 实例对应的表名 tableName: 'user', // 如果需要sequelize帮你维护createdAt,updatedAt和deletedAt必须先启用timestamps功能 timestamps: true, // 将createdAt对应到数据库的created_at字段 createdAt: 'created_at', // 将updatedAt对应到数据库的updated_at字段 updatedAt: 'updated_at', // And deletedAt to be called destroyTime (remember to enable paranoid for this to work) deletedAt: false, //'deleted_at', // 删除数据时不删除数据,而是更新deleteAt字段 如果需要设置为true,则上面的deleteAt字段不能为false,也就是说必须启用 paranoid: false }); module.exports = User;
2019年01月07日
914 阅读
0 评论
0 点赞
2019-01-03
linux环境下redis安装和启动
redis安装redis下载方式进入到/usr/local目录后使用wget从网上下载redis安装包wget http://download.redis.io/releases/redis-4.0.1.tar.gz从官网下载 https://redis.io/download 拷贝到/usr/local 目录解压下载下来的压缩包cd /usr/local tar redis-4.0.1.tar.gz!进入目录安装cd /usr/local/redis-4.0.1 make test make install执行完上诉命令安装后,redis所有的相关文件都会安装到当前目录下,其中,可执行文件redis-server或者redis-cli等都位于src目录下。启动redis服务. 在src目录下直接执行redis-server即可启动服务,这种方式启动的redis服务是在前台运行的,退出命令行工具后,redis服务就停止了。我们希望redis在后台运行。[root@redis_01 redis]# redis-server /etc/redis/sentinel.conf --sentinel 7980:X 23 Nov 18:02:41.348 * Increased maximum number of open files to 10032 (it was originally set to 1024). _._ _.-``__ ''-._ _.-`` `. `_. ''-._ Redis 3.0.5 (00000000/0) 64 bit .-`` .-```. ```\/ _.,_ ''-._ ( ' , .-` | `, ) Running in sentinel mode |`-._`-...-` __...-.``-._|'` _.-'| Port: 26379 | `-._ `._ / _.-' | PID: 7980 `-._ `-._ `-./ _.-' _.-' |`-._`-._ `-.__.-' _.-'_.-'| | `-._`-._ _.-'_.-' | http://redis.io `-._ `-._`-.__.-'_.-' _.-' |`-._`-._ `-.__.-' _.-'_.-'| | `-._`-._ _.-'_.-' | `-._ `-._`-.__.-'_.-' _.-' `-._ `-.__.-' _.-' `-._ _.-' `-.__.-' 7980:X 23 Nov 18:02:41.355 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128. 7980:X 23 Nov 18:02:41.355 # Sentinel runid is 43de323d55627d896b2caf1da2e305f0eb59dcee 7980:X 23 Nov 18:02:41.356 # +monitor master mymaster 127.0.0.1 6379 quorum 1 ^C7980:signal-handler (1448273325) Received SIGINT scheduling shutdown... 7980:X 23 Nov 18:08:45.618 # User requested shutdown... 7980:X 23 Nov 18:08:45.618 # Sentinel is now ready to exit, bye bye... . 通过nohub方式启动,nohub redis-server /etc/redis/sentinel.conf --sentinel >> /var/log/redis.log&启动服务后,命令行会退出,并且将日志文件输出到/var/log目录下的redis.log文件中. 修改配置文件在sentinel.conf文件中加入下面的配置daemonize yes logfile "/var/log/sentinel_log.log"然后通过sentinel启动redis-server /usr/local/redis-4.0.1/sentinel.conf --sentinel后面的两种启动方式都会以后台的方式启动。如果不需要--sentinel通过sentinel启动,修改的配置文件就是redis.conf
2019年01月03日
754 阅读
0 评论
0 点赞
2019-01-02
nodemon+cross-env+config实现支持热更新的能根据不同环境加载不同配置的nodejs环境
nodejs项目中我们经常会用到nodemon启动项目以使我们的项目在开发时支持热更新,修改了代码后不需要手动重启服务器;使用npm 的config模块实现不同的环境(一般是develop,production,test);nodemon和config的使用方法这里不做详细介绍。cross-env的作用是不需要全局配置NODE_ENV在scripts脚本中修改NODE_ENV的值从而实现不同环境中proccess.env.NODE_ENV的不同,而config的工作原理就是基于NODE_ENV这个值的,所以推荐两者结合使用。先上三个工具结合使用后的配置文件。/package.json"scripts": { "dev": "nodemon ./bin/www --exec babel-node --presets es2015,stage-2", "start": "cross-env NODE_ENV=production babel-node ./bin/www --presets es2015,stage-2" }, "dependencies": { // ... other dependencies "config": "^3.0.1", "cross-env": "^5.2.0", // ... other dependencies }, "devDependencies": { // ... other devDependencies "nodemon"/nodemon.json{ "restartable": "rs", "ignore": [ ".git", "f2e", "node_modules/**/node_modules" ], "verbose": true, "execMap": { "js": "node --harmony" }, "events": { "restart": "osascript -e 'display notification \"App restarted due to:\n'$FILENAME'\" with title \"nodemon\"'" }, "env": { "NODE_ENV": "develop" }, "ext": "js,json" }nodemon的配置文档介绍的可以在scripts中一一配置,也可以在上面的配置文件中配置,我们建议在配置文件中配置,清晰明了还好管理。nodemon.json中跟本文相关的配置就是env->NODE_ENV配置项,他的值就对应设置了node环境中proccess.env.NODE_ENV的值,当执行npm run dev 时,proccess.env.NODE_ENV对应的是nodemon的配置文件中的值当执行npm run start 时, proccess.env.NODE_ENV对应的是cross-env设置的参数的值
2019年01月02日
878 阅读
0 评论
0 点赞
1
...
7
8
9
...
11