首页
更多应用
Search
1
修改iview的标签为i-的形式而不是驼峰的形式
3,201 阅读
2
PHP微信和企业微信签名
2,949 阅读
3
在VUE中怎么全局引入sass文件
2,614 阅读
4
解决Macos下storm系列IDE卡顿的问题
2,484 阅读
5
vscode硬件占用较高解决方案
2,278 阅读
默认分类
JS
VUE
CSS
mac使用技巧
React
fastmock
登录
/
注册
Search
标签搜索
react
js
vue
vscode
nodejs
项目
代码
webpack
工具
nginx
小程序
css
fastmock
eslint
npm
typescript
http
vue-cli3
git
浏览器
fastmock技术社区
累计撰写
107
篇文章
累计收到
25
条评论
首页
栏目
默认分类
JS
VUE
CSS
mac使用技巧
React
fastmock
页面
更多应用
搜索到
107
篇与
的结果
2019-09-26
为什么要使用CDN(内容分发网络)
CDN是将源站内容分发至最接近用户的节点,使用户可就近取得所需内容,提高用户访问的响应速度和成功率。解决因分布、带宽、服务器性能带来的访问延迟问题,适用于站点加速、点播、直播等场景。好处:多域名加载资源 一般情况下,浏览器都会对单个域名下的并发请求数(文件加载)进行限制,通常最多有4个,那么第5个加载项将会被阻塞,直到前面的某一个文件加载完毕。因为CDN文件是存放在不同区域(不同IP)的,所以对浏览器来说是可以同时加载页面所需的所有文件(远不止4个),从而提高页面加载速度。文件可能已经被加载过并保存有缓存一些通用的js库或者是css样式库,如jQuery,在网络中的使用是非常普遍的。当一个用户在浏览你的某一个网页的时候,很有可能他已经通过你网站使用的CDN访问过了其他的某一个网站,恰巧这个网站同样也使用了jQuery,那么此时用户浏览器已经缓存有该jQuery文件(同IP的同名文件如果有缓存,浏览器会直接使用缓存文件,不会再进行加载),所以就不会再加载一次了,从而间接的提高了网站的访问速度高效率你的网站做的再NB也不会NB过百度NB过Google吧?一个好的CDNs会提供更高的效率,更低的网络延时和更小的丢包率。分布式的数据中心假如你的站点布置在北京,当一个香港或者更远的用户访问你的站点的时候,他的数据请求势必会很慢很慢。而CDNs则会让用户从离他最近的节点去加载所需的文件,所以加载速度提升就是理所当然的了。使用情况分析一般情况下CDNs提供商(如百度云加速)都会提供数据统计功能,可以了解更多关于用户访问自己网站的情况,可以根据统计数据对自己的站点适时适当的做出些许调整。有效防止网站被攻击一般情况下CDNs提供商也是会提供网站安全服务的本文转载自掘金文章https://juejin.im/post/5d8989296fb9a06b1f147070
2019年09月26日
772 阅读
0 评论
0 点赞
2019-09-26
提升首屏加载速度的方法简要总结
js外联文件放到body底部,css外联文件放到head内http静态资源尽量用多个子域名服务器端提供html和http静态资源时最好开启gzip在js,css,img等资源响应的http headers里设置expires,last-modified尽量减少http requests的数量js/css/html/img资源压缩使用css spirtes,可以减少img请求次数大图使用lazyload懒加载避免404,减少外联js减少cookie大小可以提高获得响应的时间减少dom elements的数量使用异步脚本,动态创建脚本
2019年09月26日
746 阅读
0 评论
0 点赞
2019-05-17
vscode中支持vue-cli3构建的项目eslint对vue文件的检测
在vue-cli中为了能让vscode能提示.vue文件中的js代码,我们引入了eslint-plugin-html这个eslint插件(使用方法参考VSCode环境下配置ESLint 对Vue单文件的检测)最近开始使用vue-cli3构建项目,主要目的是为了简化项目代码结构和提高编译性能。当我们使用以前的方案去实现vscode对.vue文件的eslint检测时却发现始终无法识别,而且提示以下内容提示信息很容易理解,eslint没有把当前文件当做vue文件处理,而是当做了普通的js文件处理,当然,js文件的外层代码肯定不能含有html标记。最后,我们找到了eslint-plugin-vue,这个插件能完美处理.vue文件,而且还预置了很多可复用的rules(eslint规则)。使用方法如下:第一步: npm install --save-dev eslint-plugin-vue 安装eslint vue支持插件第二步: .eslintrc.js文件中添加plugin说明注:vue-cli3默认不会在根目录创建.eslintrc.js文件,因为vue-cli3除了这种方法配置eslint以外还可以在package.json中通过eslintConfig属性去配置,但是这种方式需要严格遵守json语法规则,我们建议如果您的eslint配置较为复杂,还是在根目录自己创建一个.eslintrc.js文件,这样就可以按照js语法规则去写配置项,也方便注释module.exports = { // ...其他配置项 plugins: [ 'vue' ] // ...其他配置项 }第三步:使用eslint-plugin-vue中预置的eslint规则让其支持.vue文件的基本结构和通用语法规则增加一个文件检测说明配置extends: [ module.exports = { root: true, // https://github.com/standard/standard/blob/master/docs/RULES-en.md extends: [ 'plugin:vue/base' ], }这里我们使用的是base里面的规则,更多的预置规则可以参考文档(eslint-plugin-vue Available rules)[https://eslint.vuejs.org/rules/]关于eslint规则复用可以参考文档https://cn.eslint.org/docs/developer-guide/shareable-configs第四步:如果配置中最外层已经存在解析器说明配置parser: 'babel-eslint',将其移至parserOptions中module.exports = { root: true, parserOptions: { parser: 'babel-eslint', sourceType: 'module' } // ...其他配置项 }第五步:vscode中添加对vue文件支持的设置让vscode可以高亮vue文件中的js代码eslint问题代码"eslint.validate": [ "javascript", "javascriptreact", { "language": "vue", "autoFix": true } ] 附完整的.eslintrc.js文件// https://eslint.org/docs/user-guide/configuring module.exports = { root: true, parserOptions: { parser: 'babel-eslint', sourceType: 'module' }, env: { browser: true }, // https://github.com/standard/standard/blob/master/docs/RULES-en.md extends: [ 'plugin:vue/base' ], // required to lint *.vue files plugins: [ 'vue' ], // add your custom rules here 'rules': { // allow paren-less arrow functions 'indent': [2, 2], // 两个空格的缩进 'quotes': [2, 'single'], // js必须使用单引号 'linebreak-style': [2, 'unix'], // 换行风格 unix/windows 'semi': [2, 'always'], // 语句强制分号结尾 'no-console': [1], // 不允许console语句 'no-unused-vars': [1], // 声明了变量但是没有使用检测 'space-unary-ops': [1, { 'words': true, 'nonwords': false }], // 一元运算符的前/后要不要加空格 'brace-style': [2, '1tbs', { 'allowSingleLine': false }], // 大括号风格 'comma-spacing': [2, { 'before': false, 'after': true }], // 逗号后有空格,前没有空格 'comma-style': [2, 'last'], // 逗号跟在结尾 'key-spacing': [2, { 'beforeColon': false, 'afterColon': true }], // 对象字面量中冒号的前后空格 'lines-around-comment': [ // 行前/行后备注 2, { 'beforeBlockComment': false, // 段注释的前后 'beforeLineComment': false, // 行注释的前面 'afterBlockComment': false, // 块注释的后面 'afterLineComment': false, // 行注释的后面 'allowBlockStart': true, 'allowObjectStart': true, 'allowArrayStart': true }], 'max-depth': [2, 4], // 代码最多允许4层嵌套 'max-len': [1, 160, 2], 'max-nested-callbacks': [2, 3], // 回调嵌套深度 'max-params': [2, 5], // 函数最多只能有5个参数 'max-statements': [1, 80], // 单个函数最多80条语句 'no-array-constructor': [2], // 禁止使用数组构造器 'no-lonely-if': 2, // // 禁止else语句内只有if语句 'no-multiple-empty-lines': [2, { 'max': 3, 'maxEOF': 1 }], // 空行最多不能超过2行 'no-nested-ternary': 2, // 不使用嵌套的三元表达式 'no-spaced-func': 2, // 函数调用时 函数名与()之间不能有空格 'no-trailing-spaces': 2, // 一行结束后面不要有空格 'no-unneeded-ternary': 2, // 禁止不必要的嵌套 var isYes = answer === 1 ? true : false;简单的判断用三元表达式代替 'object-curly-spacing': [2, 'always', { // 大括号内是否允许不必要的空格 always始终允许;never始终不允许 'objectsInObjects': false, 'arraysInObjects': false }], 'arrow-spacing': 2, // =>的前/后括号 'block-scoped-var': 2, // 块语句中使用var 'no-dupe-class-members': 2, // 'no-var': 1, // 禁用var,用let和const代替 'object-shorthand': [1, 'always'], // 强制对象字面量缩写语法 'array-bracket-spacing': [2, 'never'], // 是否允许非空数组里面有多余的空格 'operator-linebreak': [2, 'after'], // 换行时运算符在行尾还是行首 'semi-spacing': [2, { 'before': false, 'after': true }], // 分号前后空格 'keyword-spacing': ['error'], 'space-before-blocks': 2, // 不以新行开始的块{前面要不要有空格 'block-spacing': [2, 'always'], 'space-before-function-paren': [2, 'never'], // 函数定义时括号前面要不要有空格 'space-in-parens': [2, 'never'], // 小括号里面要不要有空格 'spaced-comment': [1, 'always', { 'exceptions': ['-', '*', '+'] }], // 注释风格要不要有空格什么的 'arrow-parens': 0, // allow async-await 'generator-star-spacing': 0, // allow debugger during development 'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0 }, globals: { '$': false, 'jquery': false, 'ActiveXObject': false, 'arbor': true, 'layer': false } };
2019年05月17日
999 阅读
0 评论
0 点赞
2019-04-12
vue基于viewer实现的图片查看器
vue2-viewervue2-viewer 是一款强大的图像浏览插件,可以实现图像的放大预览,旋转,任意比例放大和缩小等功能vue2-viewer 是viewer.js vue的实现,效果以及样式完全移植自viewer.js关于viewer.js可以参考链接[http://fengyuanchen.github.io/viewer/]插件中所有的效果均大量地使用了css3的新特性替换了viewer.js中的js动画,所以vue2-viewer主要实用场景是现代浏览器中。使用文档安装npm install --save vue2-viewer在main.js中引入并使用插件import ImageViewer from 'vue2-viewer'; Vue.use(ImageViewer);插件会在全局注册vue-viewer组件使用组件vue2-viewer 提供两种使用模式,单图片模式和多图列表模式。单图片模式props参数说明类型必须thumb要显示的小图的链接stringtruefull点击放大后的大图链接stringtrue示例:<vue-viewer style="display: inline-block" :thumb="image" :full="image"> </vue-viewer> <script> export default { name: 'app', data () { return { msg: 'vue2-viewer-test', image: 'https://ss0.baidu.com/6ONWsjip0QIZ8tyhnq/it/u=3427452369,2586833644&fm=173&app=25&f=JPEG?w=580&h=347&s=908FF35A050626E2428C001E030090D6', } } } </script>效果展示:多图片模式props参数说明类型必须thumb要显示的小图列表的链接数组arraytruefull点击放大后的大图的链接数组arraytruelist-ul-class默认小图的列表外层ul的自定义class 用于自定义列表的样式,包括ul内部的slot的内容的样式都可以通过这个方式自定义stringfalseScoped Slotname说明~列表中的每一个元素中除了默认图以外的内容示例:<vue-viewer multiple :thumb="imageList" list-ul-class="image-list" :full="imageList"> <!--在列表中加入右上角删除按钮--> <template slot-scope="target"> <span class="icon-remove" @click.stop="onRemove(target.index)" style="">×</span> </template> </vue-viewer> <script> export default { name: 'app', data () { return { msg: 'vue2-viewer-test', imageList: [ 'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1550224739247&di=512032866bea6329b1e46c735d50ac8b&imgtype=0&src=http%3A%2F%2Fimglf2.ph.126.net%2FdHH6OM2rD8JucPGAotUfag%3D%3D%2F6608219914074710297.jpg', 'https://ss0.baidu.com/6ONWsjip0QIZ8tyhnq/it/u=488030022,1694816207&fm=173&app=25&f=JPEG?w=580&h=347&s=A08FB35A5E0616C664F5631C030010D6', 'https://ss0.baidu.com/6ONWsjip0QIZ8tyhnq/it/u=2574767313,3929397124&fm=173&app=25&f=JPEG?w=580&h=868&s=B784EEA3460236E17A1F137F0300A058' ] } }, methods: { onRemove(index) { alert(index); } } } </script> <style> .image-list{ margin: 0; padding: 0 } .image-list li { display: inline-block; margin: 0 10px; list-style: none; position: relative; } .image-list li img { box-shadow: 0 0 5px #333; } .icon-remove{ width: 20px; height:20px; text-align: center; line-height: 20px; background:#f33; position:absolute; top:-10px; right:-10px; border-radius: 10px; cursor: pointer; color:#fff; } a { color: #42b983; } </style>效果展示:
2019年04月12日
1,001 阅读
0 评论
0 点赞
2019-03-21
fastmock增加功能根据入参数据动态逻辑返回mock内容
根据入参数据动态返回mock内容某些场景中,我们可能需要根据接口的入参规则,加入适当的逻辑处理后再返回数据。一个简单的场景就是登录场景,需要根据用户名密码,判断是否登录成功。再或者,我们需要根据产品ID动态返回产品信息,等等。现在fastmock提供了这种场景的解决方案,下图中展示了如何如果在mock规则中获取请求中的各个部分的数据然后再返回,其中包括了四种数据。restful链接参数,如/user/:id 当请求/user/1时 对应数据为{id: 1}。获取方式为_req.params.idquery查询参数,如/user?id=1 获取方式为_req.query.idbody请求体数据,在请求的request body中 获取方式为_req.body.idheaders 头部信息,常用的场景是接口的token验证 获取方式为_req.headers.token使用方法在原来的json数据的基础上,需要动态返回的字段对应的值不再是固定值或者固定的mock规则,而是传入一个函数。这个函数接收两个参数,_req和Mock 注意:这两个变量名不能改动在函数体中返回该字段对应的值,在返回之前做相应的逻辑处理_req参数中包含了四个对象,_req.query , _req.params , _req.body , _req.headers可以从这四个对象中获取上述的四种数据。Mock对象就是mock.js 原生对象,可以用它做mock.js中Mock对象可以做的事情,如Mock.mock({name: '@cname'})等等如:上图中的对应接口录入规则为{ "code": "0000", "data": { "token": function({_req, Mock}) { return _req.headers.token; }, "id": function({_req, Mock}) { return _req.params.id; }, "name": function({_req, Mock}) { return _req.body.name; }, "age": function({_req, Mock}) { return _req.query.age; } }, "desc": "成功" }再举一个验证登录信息的例子:{ "code": "0000", "data": { "verifySuccess": function({_req, Mock}) { let body = _req.body; return body.username === 'admin' && body.password === '123456'; }, "userInfo": function({_req, Mock}) { let body = _req.body; if (body.username === 'admin' && body.password === '123456') { return Mock.mock({ username: "admin", email: "@email", address: "@address" }); } else { return null; } }, }, "desc": "成功" }上面的规则中定义了登录接口只有请求体{username: 'admin', password: '123456'}时,才会返回用户信息,且带有mock生成的随机邮箱地址和居住地址
2019年03月21日
1,352 阅读
0 评论
0 点赞
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日
990 阅读
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,326 阅读
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日
450 阅读
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日
1,128 阅读
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,501 阅读
0 评论
0 点赞
1
...
7
8
9
...
11