小蝌蚪传记通过隧道技术击穿内网

背景2019年6月9号,星期天,晴,33度 今天的bug格外的难解 对面商店的小姐姐,依然是我不敢奢求的梦 进入商店小蝌蚪:您好,我想买两包妹子她:嗯?小蝌蚪:错了,买两包烟她:一共20块。小蝌蚪:太贵了,23块行不行?她:行,还有什么需要的吗?小蝌蚪:有需要,我有一场恋爱需要和妳谈谈话音刚落就被姑娘的拳击男友爆揍了一顿 小蝌蚪拖着受伤的身躯蹲在路边微风吹过我的脸庞,我很迷茫 多希望有个富婆能看穿我的逞强 让我卸下所有伪装,走进她的心房话音刚落就被包工头在电话里骂了一顿因为线上出现了bug (以下为技术部分,非技术人员请略过,直接看结尾) 通过隧道技术击穿内网由于电脑不在身边,小蝌蚪直接进了间网吧,这个bug的问题出在公司内网数据库中,只要调整数据数据就能解。 可是,没有vpn,怎么连接到内网数据库呢? 小蝌蚪发出了诡异的笑声,为了应付紧急情况,小蝌蚪早就做好了准备, 通过隧道技术,在内网打穿了一个洞,击穿了内网。以便不时之需。 假设,小蝌蚪个人服务器叫server1,公司的对外网站服务器叫server2,公司内网的数据库叫MySQL. 公司的对外网站服务器server2能通过ssh连接到小蝌蚪的server1, 但server1不能通过ssh连接server2。 并且只有公司的对外网站服务器server2能连接数据库。 他们的关系图如下: server1的端口是6666,数据库MySQL端口是3306,那么只需要在server2服务器上执行: ssh -R 6666:MySQL:3306 server1 即可,这样小蝌蚪直接去连接server1的6666端口,就相当于连接了公司内网的数据库,完美的解决掉了bug。 这个就是利用了ssh的隧道去实现的内网击穿。 我们在平时开发的时候,还有可能会遇到一种场景 在内网环境要连接跳板机,然后再通过跳板机才能连接到数据库。 这样要想在本地开发的时候操作数据库,非常的麻烦。 那么我们如何解决这个问题呢? 假设小蝌蚪在公司的个人电脑叫server1,需要用跳板机才能连接的数据叫MySQL,关系图如下: server1的端口是6666,数据库MySQL端口是3306,那么只需要在server1上执行: ssh -L server1:6666:MySQL:3306 root@跳板机 即可,这样小蝌蚪直接连接本地电脑的6666,就相当于连接上了线上数据库MySQL,非常方便和简单。 以上的两个技能分别叫ssh的本地端口转发和远程端口转发。 远程端口转发建议慎用,因为如果你在大公司工作,基本上公司的安全策略组都会监听 如果有员工使用了远程端口转发,会被检测到并处罚和通告批评的 所以建议慎用,重要的事情说三遍。 慎用远程端口转发 慎用远程端口转发 慎用远程端口转发 结尾解决完这个bug,已经是晚上十二点楼下的夜店响起了战歌站在物欲横流的街 小蝌蚪对其中一家夜店着了迷因为门口站着一排黑丝大长腿黑丝对程序员来说是一种圣物,同时也是个迷黑丝套在头上,你就是劫匪黑丝套在腿上,妳就是神明 就在这时,天边突然响起了师傅的佛音:“小蝌蚪,美色是你职业道路上的绊脚石还在意女人,你就成为不了江湖第一的程序员 ”小蝌蚪狠狠扇了自己一巴掌一个真正厉害的程序员应该是心无旁骛 ,只有代码 心中有码,到哪里都是比基尼 小蝌蚪的师傅是一个高级前端工程师离至尊级程序员就差一步在一次修炼中,为了突破到至尊级孤身一人进入夜店后来就再也没有回来 消失前一小时他在微信群留下了两个字:“黑丝” 那天晚上师傅到底经历了什么小蝌蚪决定进店探个究竟 深夜中的男男女女,在舞池中央群魔乱舞小蝌蚪身上穿着公司十周年发的屎黄色战服在舞池里蹦起来就好像一个小儿麻痹 平时习惯了昏暗的办公室,见不得光被夜店里的聚光灯一照,差点亮瞎了狗眼 随着音乐摇到一半 突然看到后排有个面黄肌瘦的男人小蝌蚪:师傅!是你吗师傅:小。。。小蝌蚪?你为什么会在这里小蝌蚪:师傅~!终于找到你了。快跟我回去师傅:走不了,我的灵魂中毒了。小蝌蚪:中毒?师傅:我要找到一个女孩,她是我唯一的解药小蝌蚪:怎样才能找到她师傅:她的代号叫“黑丝”,传说中的夜店女皇,她藏的很深,几乎没有人能找到她。小蝌蚪:她是个什么样的女人师傅:黑丝是一个极度危险的女人,所有被她撩过的男人,都会瞬间沉沦,然后日渐消瘦,思念至死。师傅:三年前,她亲吻了我一下,然后、然后、然后。。。。。。黑丝、黑丝、黑丝、黑丝、黑丝、黑丝、黑丝、黑丝、黑丝、黑丝。。。话还没说完,师傅就像毒瘾发作疯狂乱抓自己头发口里不断重复着“黑丝”两个字。。。。。。小蝌蚪发誓一定要找到黑丝于是闭上眼睛,气运丹田,动用“心眼”去感受身边每个人的蠕动“心眼”是程序员的一个高阶技巧它能让程序员在短时间内找到万行代码中的bug所在 过了许久,最终锁定人群九点钟方向那里坐着一个低着头的妹纸 女性在夜店都是尽可能穿得妖艳可她只穿了一件简单白色短袖与周围环境形成强烈反差“心眼”感受到了她倾世容颜下一颗躁动的野心 显然,她只是看起来纯洁一个真正的高手,她的外表看起来永远都不像一个高手高富帅就偏偏喜欢这样清纯简单的女人因为高富帅已经厌倦了庸脂俗粉和妖艳贱货 终于找到了黑丝,可是要怎么撩她呢小蝌蚪急中生智,在屎黄色的公司战服上,用圆珠笔画了一个“supreme”,逼格瞬间爆炸 进入蹦迪的舞池后,不会摇摆怎么办?师傅曾说过:“如果你在夜店里不会摇摆,那就用脸在天上画一个<粪>字” 头在摇摆的时候,手应该怎么晃动呢?师傅又曾经说过:“如果在夜店里你的手不知道怎么晃,就想象天花板是一个巨大的键盘,将手举过头顶对着天空一顿盲敲那样你就是夜店里最厉害的仔” 为了让自己看起来更像一个夜店高手小蝌蚪一面摇晃着脑袋一面将程序员的加班战歌《no-sex(无性繁殖)》大声唱了出来歌词大意如下:“药药 切克闹 哟哟 嘿V够 i don't need sex, the code 发可 me everyday大声跟我一起念 i don't need sex, the code 发可 me everyday发可!发可!me!me!eve!ry!Day!”小蝌蚪一边rap一边嘲讽旁边的年轻人,不懂得什么才是真正的music 才用不到半小时,小蝌蚪已经是整个夜店里最狂的仔 ...

June 23, 2019 · 1 min · jiezi

如何从零开始定义一个类似websocket的即时通讯协议

深南大道镇楼定义一个自己的通讯协议并不难,关键在于这个协议的可用性,可拓展性,复杂业务场景的实用性即时通讯应用中,客户端和服务器端都可以看成一个服务器一起复习一下websocketWebSocket是一种在单个TCP连接上进行全双工通信的协议。WebSocket通信协议于2011年被IETF定为标准RFC 6455,并由RFC7936补充规范。WebSocket API也被W3C定为标准。WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据,在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。说说ws协议的优点:说到优点,这里的对比参照物是 HTTP 协议,概括地说就是:支持双向通信,更灵活,更高效,可扩展性更好。支持双向通信,实时性更强。更好的二进制支持。较少的控制开销。连接创建后,ws 客户端、服务端进行数据交换时,协议控制的数据包头部较小。在不* 包含头部的情况下,服务端到客户端的包头只有 2~10 字节(取决于数据包长度),客户端到服务端的的话,需要加上额外的 4 字节的掩码。而 HTTP 协议每次通信都需要携带完整的头部。支持扩展。ws 协议定义了扩展,用户可以扩展协议,或者实现自定义的子协议。(比如支持自定义压缩算法等)我们先看看web socket协议的实现具体过程,再用代码抽象,定义自己的即时通讯协议:连接握手过程 关于WebSocket有一句很常见的话: Websocket复用了HTTP的握手通道, 它具体指的是:客户端通过HTTP请求与WebSocket服务器协商升级协议, 协议升级完成后, 后续的数据交换则遵照WebSocket协议客户端: 申请协议升级首先由客户端换发起协议升级请求, 根据WebSocket协议规范, 请求头必须包含如下的内容 GET / HTTP/1.1 Host: localhost:8080 Origin: http://127.0.0.1:3000 Connection: Upgrade Upgrade: websocket Sec-WebSocket-Version: 13 Sec-WebSocket-Key: w4v7O6xFTi36lq3RNcgctw请求头详解 请求行: 请求方法必须是GET, HTTP版本至少是1.1请求必须含有Host如果请求来自浏览器客户端, 必须包含Origin请求必须含有Connection, 其值必须含有"Upgrade"记号请求必须含有Upgrade, 其值必须含有"websocket"关键字请求必须含有Sec-Websocket-Version, 其值必须是13请求必须含有Sec-Websocket-Key, 用于提供基本的防护, 比如无意的连接1.2 服务器: 响应协议升级服务器返回的响应头必须包含如下的内容 HTTP/1.1 101 Switching ProtocolsConnection:UpgradeUpgrade: websocketSec-WebSocket-Accept: Oy4NRAQ13jhfONC7bP8dTKb4PTU=响应行: HTTP/1.1 101 Switching Protocols响应必须含有Upgrade, 其值为"weboscket"响应必须含有Connection, 其值为"Upgrade"响应必须含有Sec-Websocket-Accept, 根据请求首部的Sec-Websocket-key计算出来Sec-WebSocket-Key/Accept的计算规范提到:Sec-WebSocket-Key值由一个随机生成的16字节的随机数通过base64编码得到的Key可以避免服务器收到非法的WebSocket连接, 比如http请求连接到websocket, 此时服务端可以直接拒绝Key可以用来初步确保服务器认识ws协议, 但也不能排除有的http服务器只处理Sec-WebSocket-Key, 并不实现ws协议Key可以避免反向代理缓存在浏览器中发起ajax请求, Sec-Websocket-Key以及相关header是被禁止的, 这样可以避免客户端发送ajax请求时, 意外请求协议升级最终需要强调的是: Sec-WebSocket-Key/Accept并不是用来保证数据的安全性, 因为其计算/转换公式都是公开的, 而且非常简单, 最主要的作用是预防一些意外的情况WebSocket通信的最小单位是帧, 由一个或多个帧组成一条完整的消息, 交换数据的过程中, 发送端和接收端需要做的事情如下:发送端: 将消息切割成多个帧, 并发送给服务端接收端: 接受消息帧, 并将关联的帧重新组装成完整的消息数据帧格式详解 ...

June 23, 2019 · 7 min · jiezi

对移动端兼容适配的分析

一、思考 在移动端越来越重要的背景下,每位web开发者对移动适配都有自己的想法。是移动优先,还是PC优先,还是两者兼得?在实际开发中这个问题是和项目产品定位有关的,也涉及到UI的设计,不是开发者能决定。但不管产品如何定位,作为开发者总是要提供最优的解决方案,是用一套样式还是多套样式?网上一搜,有静态布局、流式布局,响应式布局,自适应布局,弹性布局等一堆,云里雾里,到底要怎么选呢?看完这篇文章相信心中就有数了。 二、viewport的使用1、最常见的设置,大多数的框架(如bootstrap)和知名的站点基本是这个配置 <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no" />2、这个配置重点在width=device-width,就是让视窗口等于设配宽度,也就是我们开发中能用document的宽度,其它几个“初始缩放大小”“最大缩放大小”“最小缩放大小”和“是否允许用户缩放”可以理解为用来“固定”这个设置不被破坏的。3、这个设置很简单,但同时也会带来一些需要解决的问题。 a、现在的手机都是两倍三倍的Retina高清屏,1px实际的效果是不止一个像素的,对不同的设备设置不同 的initial-scale可以有比较好的效果,比如在2倍Retina的iphone6(6s,7,8)中设置为0.5。一旦 动态设置这个,也就意味这视窗口不同了,需要不同样式适配。这也是分配样式的一套基准,如何分配样式 后面会有更详细的讲解。 b、在PC端如果有最小宽度的限制,同样需要配置不同的width值。 三、单位的使用1、css中单位很多,这里只介绍最常用的几种: (1) px:这个可以理解为“基准”单位,就是不管在什么设备中其值是不会变的,就像cm,kg这些一样 (2) em:这个是相对父容器的单位,一般用在字体font-size中比较好。如父容器font-size为16px,则 1em=16px(3) rem:相对于根元素html的单位,如html的font-size为16px,则1rem=16px (4) vw/vh: 视口宽高为100vw/100vh,这个和百分比类似,只是百分比是相对于父容器,其相对于视口2、移动适配最常用的应该是rem,很多框架和淘宝的flexible适配都是基于这个单位,而自己做的话,一般 在首页加载时全局js设置html的font-size即可,代码如下: (function (doc, win) { var docEl = doc.documentElement, resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize', recalc = function () { var clientWidth = docEl.clientWidth; if (!clientWidth) return; //这里根据设计稿为750,设置1rem=100px, docEl.style.fontSize = 100 * (clientWidth / 375) + 'px'; }; // Abort if browser does not support addEventListener if (!doc.addEventListener) return; win.addEventListener(resizeEvt, recalc, false); doc.addEventListener('DOMContentLoaded', recalc, false);})(document, window);3.如果用了sass/less等预编译语言可以更灵活的配置的,在上面方法内配置(设计稿为750的情况下): docEl.style.fontSize = 40 * (clientWidth / 750) + 'px'; 在编译函数中配置: @function px2rem($px, $base-font-size: 20px) { ...

June 23, 2019 · 2 min · jiezi

PC软件web网站小程序手机APP产品如何增加个人收款接口

接入前准备通过 XorPay 注册个人收款接口,原理是帮助你签约支付宝和微信(不需要营业执照)支持个人支付宝和个人微信支付接口,大概几分钟可以开通,开通后即可永久使用PC 网站接入效果:用户点击支付后,前端ajax 请求你的后台,你后台再请求 xorpay 支付接口返回支付二维码到前台,页面展示微信或者支付宝二维码,用户用手机微信或支付宝扫码支付接口:可以使用 JSAPI / Native / 收银台 / 支付宝当面付 支付接口JSAPI 支付,通过构造二维码,用户微信扫码后在打开自己服务器的页面,再在这页面通过 JSAPI 拉起微信支付收银台支付,效果和 JSAPI 一样,更简单,不用自己请求获取 openid,直接在 xorpay 的页面下发起支付Native 支付,前端 ajax 请求自己后端的接口,后端接口请求 xorpay 支付接口,返回支付二维码,用户微信扫码后支付支付宝当面付,方法同 Native 接口PC 软件效果:用户点击支付后,前端网络请求你的后台,你后台再请求 xorpay 支付接口返回支付二维码到前台,页面展示微信或者支付宝二维码,用户用手机微信或支付宝扫码支付接口:可以使用 JSAPI / Native / 收银台 / 支付宝当面付 支付接口JSAPI 支付,通过构造二维码,用户微信扫码后在打开自己服务器的页面,再在这页面通过 JSAPI 拉起微信支付收银台支付,效果和 JSAPI 一样,更简单,不用自己请求获取 openid,直接在 xorpay 的页面下发起支付Native 支付,前端 ajax 请求自己后端的接口,后端接口请求 xorpay 支付接口,返回支付二维码,用户微信扫码后支付支付宝当面付,方法同 Native 接口手机网站接入效果:因为个人的微信接口没有 h5 功能(个人支付宝当面付可以 h5),所以只能扫码接口:可以使用 JSAPI / 收银台 / 支付宝当面付 支付接口JSAPI 支付 ...

June 23, 2019 · 1 min · jiezi

jQuery源码解析之queuedequeue和jQueryCallbacks

前言:queue()方法和dequeue()方法是为 jQuery 的动画服务的,目的是为了允许一系列动画函数被异步调用,但不会阻塞程序。 所以这篇是为jQuery的动画解析做准备的。 一、$.queue()、$.dequeue() 和 $().queue()、$().dequeue() 的区别(1)$().queue()和$().dequeue()这俩是jQuery.fn.extend()中的方法,也就是供开发者使用的方法,其内部会分别调用 $.queue()和$.dequeue()方法。 //源码4686行jQuery.fn.extend( { queue: function( type, data ) { xxx return jQuery.queue( this[ 0 ], type ) }, dequeue: function( type, data ) { return jQuery.dequeue( this, type ) },})(2)$.queue()和$.dequeue()这俩是jQuery.extend()中的方法,也就是 jQuery 内部使用的方法。 //源码4594行 jQuery.extend( { queue: function( elem, type, data ) {}, dequeue: function( elem, type ) {}, })二、$().queue()作用1:作为setter,将function(){}存进特定队列中。 <div id="A" style="background-color: deeppink">这是A</div><script> function a() { console.log('a','a34') } function b() { console.log('b','b37') } //将a、b方法存在类型为type的队列里 //jQuery.fn.queue 给jQuery对象$("A") /*setter*/ $("#A").queue('type', a) $("#A").queue('type', b)</script>作用2:作为getter,取出特定队列中function(){}的数组。 ...

June 23, 2019 · 8 min · jiezi

记录vuecli脚手架引入弹出层layer插件

如何引入 在vue-cli里,引入文件有几钟方法 一种是用npm或者cnpm指令去下载对应的插件,然后在main.js里用import方法引入,这里不讨论这种方法 我比较喜欢采用的是直接下载对应的js,然后引入到vue项目中去 问题来了,如何引入呢方法如下: 下载对应的js文件或者css文件,一般下载插件相关联的都会在一起进入vue-cli项目工程里的index.html文件,分别引入css文件和js文件 在这里,分别是 <link rel="stylesheet" href="./static/layer.css" /> <script src="./static/jquery.js"></script> <script src="./static/jquery.min.js"></script> <!-- 必须先引入上面jq 1.8版本以上的才能引layer --> <script src="./static/layer.js"></script> 这样在全局文件里都可以使用layer弹出层插件了,需要注意,必须先引入jq 1.8以上的版本才可以使用layer噢。 2.弹出层显示不出 作为一个java开发小菜鸟,踩前端的坑基本是面向百度进行尝试解决,经历了时常两个半小时的挣扎,解决了几个问题:第一个是前端控制台报错,印象里是i is not a function 还有什么layer.open is not a function等,这些问题基本是出于引入的问题,解决途径:检查是否在之前引入了1.8以上的jq第二个是弹出层只有文字显示,但是缺乏样式,没有弹出层的feel。经过大量百度和分析,最后还是依靠调试前端样式看出端倪,问题在于里面用到的class在我引入的css文件里并不存在。经过检查,导入的css文件错误(注意有手机的css样式和另一个css,这里要用另一个,名称一样)。最终问题解决。

June 23, 2019 · 1 min · jiezi

关于ECharts折线图非节点的点击事件

ECharts官网教程 详情请看官网教程 前言:相信很多人有这种需求,在点击折线图非节点的时候不能触发点击事件,而官网又没有这方面的教程,只能自己默默的研究了 解决方案如下: // 基于准备好的dom,初始化echarts实例 var mychart = echarts.init(document.getElementById('main')); // 指定图表的配置项和数据 var option = { title: { text: 'ECharts 入门示例' }, tooltip: {}, legend: { data:['销量'] }, xAxis: { data: ["衬衫","羊毛衫","雪纺衫","裤子","高跟鞋","袜子"] }, yAxis: {}, series: [{ name: '销量', type: 'bar', data: [5, 20, 36, 10, 10, 20] }] }; // 使用刚指定的配置项和数据显示图表。 mychart.setOption(option); //绑定点击事件 mychart.getZr().on("click", function(params) { const pointInPixel = [params.offsetX, params.offsetY]; if (mychart.containPixel("grid", pointInPixel)) { let xIndex = mychart.convertFromPixel({ seriesIndex: 0 }, [ params.offsetX, params.offsetY ])[0]; /*事件处理代码书写位置*/ } });实现的代码解释如下: ...

June 21, 2019 · 1 min · jiezi

Deeplink深度链接如何提高App转化率留存率

移动互联网时代,信息的分享传播无疑是 App 引流增长的关键,与其花费大量精力和成本找渠道、硬推广,不如从细节下手,用最快最简便的方法实现 Deeplink(深度链接)技术,打破信息孤岛、缩短分享路径、优化用户体验,最终提高流量转化率和留存率。 什么是 DeepLink(深度链接)技术 如果把 App 看成网站,那么 DeepLink 就是网站中的深入页面,比如商品购物页面、活动促销页面。简单理解,就是当用户点击手机中的某个链接时,可以帮他跳转到 App 内部中的目标页面,直接实现场景还原,而不是 App 首页,这是一种无障碍场景还原技术。 DeepLink 通常运用于App社交分享、App广告引流、App裂变活动、Web to App、分享效果统计、沉默用户唤醒等场景,对广告引流、活动推广、新闻类、电商类、游戏类、视频直播类App的引流推广和转化都有着奇效。 升级版 Deferred deeplink(延迟深度链接)技术 相比 Deeplink,Deferred deeplink 增加了一个判断,能在用户点击链接时判断设备是否安装了目标App,如果没有安装,则跳转应用市场或者浏览器中引导下载,用户安装后再次实现 Deeplink 的场景还原功能。 是否使用这两项技术的差别: 可以看到,使用了深度链接后,用户操作成本明显降低了一至两步,做运营的小伙伴都知道,在用户转化的漏斗中,每多一个步骤,漏斗的路径就会多一层,用户流失率也就随之增加。 怎样为App快速实现这两项技术 我们以 openinstall 的一键拉起功能为例,这项功能集成了深度链接中的scheme,universal link等核心技术,能完美实现 Deeplink、Deferred deeplink 的所有技术场景效果,主要特点如下: 一键拉起功能同时兼容 Android、iOS 系统,不存在操作系统技术障碍;适配了大量主流社交平台和浏览器,如微信、QQ、新浪微博、钉钉、支付宝等;用户已安装该 App 的情况下,点击页面链接可直接拉起本地 App,并自动进入目标页面;用户未安装该 App 的情况下,点击页面链接会引导到应用商店或默认浏览器下载,安装后首次打开将自动进入目标页面;该功能目前以及免费开放给所有开发者。openinstall:https://www.openinstall.io/pu... 不仅如此,在深度链接的基础上,还能完善出更多定制化场景需求,比如: 能够根据需求满足开发者业务逻辑,如:既可实现下载优先,也可以实现拉起优先;在社交分享页面上,openinstall 还能同时实现携带参数安装,帮助开发者实现渠道来源统计,具体到用户是被哪篇文章吸引来的、哪个广告页面的转化率最高、哪件产品付费效果最好;甚至可以在业务上实现【社交平台快速下载 App、免填邀请码、App 安装后自动加群加好友、下载 App 后自动登录账号】等功能,进一步完善用户体验和关系链。哪些产品或场景非常适合深度链接 社交平台我们以微信为例,产品以电商类京东 App、资讯类今日头条 App 为例,可以参考他们的结合效果: 显而易见,电商类、资讯类、旅游类、服务类 App 结合社交分享传播具有非常大的价值,此外,游戏类 App 甚至可以利用一键拉起功能点击分享链接直接进入 App 内的游戏房间。 ...

June 21, 2019 · 1 min · jiezi

http-status为401时避免浏览器弹出认证框

Basic认证失败时,接口返回的http status code = 401时,大部分浏览器会弹出下图的认证窗口来辅助用户完成认证。 这时,要点击取消才能进入到axios catch function。解决到方法很简单,在response headers中去除 WWW-Authenticate: Basic realm="Realm" 即可。

June 21, 2019 · 1 min · jiezi

BFC块级格式化上下文的特点和应用场景

BFC(Block Formatting Context)的特点是元素拥有独立的渲染区域,元素内部的内容(边距,浮动元素等)不会影响到外部元素。哪些情况下会触发BFC设置overflow属性,值不为visible设置float属性,值不为none设置position属性,值为absolute或fixed设置display属性,值为inline-block, table-cell, table-caption, flex, inline-flex, grid,或者inline-gridBFC的典型应用场景: 解决块级元素的塌陷问题(Collapsing)块级元素的垂直塌陷: 当两个相邻的块级元素拥有上下方向相邻的边距时(例如:上面的元素拥有margin-bottom值,下面的元素拥有margin-top值),此时上下元素之间的间隙不是两者边距之和,而是两者之中的值较大的一个块级元素的包含塌陷: 当块级父元素没有boder,padding值,块级子元素有margin-top值时,子元素的margin-top值会在父元素的外部生效,也就是整个父元素区域会向下偏移,这个偏移值由子元素的margin-top值决定此外,BFC还可以用于清除浮动带来的影响等

June 21, 2019 · 1 min · jiezi

再谈前端项目的组件化

再谈前端项目的组件化之前详细聊过的前端项目的组件化,可以参考 组件化 与 私有 npm 仓库,今天来更进一步的说说前端项目的组件化。 1. 之前的组件化目录结构: -project1 # 项目1-project2 # 项目2-component1 # 组件1-component2 # 组件2project1 的 package.json: { "dependencies": { "@yourCompany/component1": "^0.0.1", "@yourCompany/component2": "^0.0.1" }}在代码中使用: import component1 from '@yourCompany/component1';2. 之前的组件化方式存在的问题更新组件比较麻烦,特别是对于一些与业务耦合比较深的组件,频繁更新会比较头疼组件太多的时候,管理起来就感觉比较累,因为每个组件都是一个单独的项目,都有一套独立的构建环境对于有些代码量小的组件,做一个单独的项目,实在有点大才小用3. 另外的项目组件化方式针对上面讲到的问题,另一种方式可以很好的解决: 目录结构: -project1 # 项目1-project2 # 项目2-components # 组件集合项目components 组件集合项目的目录结构: - src/ # 源代码目录 - component1 # 组件1 - component2 # 组件2 - component3 # 组件3 - ...- package.json- README.md- CHANGELOG.md- .eslintrc.js- .stylelintrc.js- .prettierrc.js- ...把 components 目录软链接 project1 目录下: ...

June 20, 2019 · 1 min · jiezi

移动端图片裁剪器安装即用

h5-cropper移动端图片裁剪器,基于 cropperjs 制作的简单裁剪器 项目地址https://github.com/sayll/h5-cropper 案例演示HTML部分: <!DOCTYPE html><html lang="cn"><head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no" /> <title>裁剪案例</title></head><script src="./h5-cropper.js"></script><body style="font-size: 14px"> <img id="image" src="http://placekitten.com/g/720/400" width="100%" alt=""> <div> <button style="width: 100%; font-size: 18px;" id="button">开始裁剪</button> </div></body><script src="./index.js"></script></html>JS部分: const img = document.getElementById('image')document.getElementById('button').onclick = function () { var cropper = new window.H5Cropper(img.src, function (base64) { img.src = base64 })}演示案例:https://sayll.github.io/h5-cropper/index.html 手机模式查看,效果更佳。使用方式直接下载使用通过下载,直接引用dist/index.js,通过全局的window对象访问。 const cropper = new window.H5Cropper('http://placekitten.com/g/300/200', function (base64) { // to do something console.log(base64)})npm 下载使用下载方式: npm i -S h5-cropper使用方式: import H5Cropper from 'h5-cropper'const cropper = new H5Cropper('http://placekitten.com/g/300/200', function (base64) { // to do something console.log(base64)})接口定义调用方式: ...

June 20, 2019 · 1 min · jiezi

lodoparttemplate实现web端漂亮的小票样式打印

一. 现状由于之前采用Lodop打印控件(商业版付费,可以使用免费版 但是会有水印)去打印小票,是一行一行的打印,但是不满足UI给到复杂布局的小票样式,所以得重新考虑如何来实现。 二. 介绍art-template介绍art-template 是一个简约、超快的模板引擎。 它采用作用域预声明的技术来优化模板渲染速度,从而获得接近 JavaScript 极限的运行性能,并且同时支持 NodeJS 和浏览器。在线速度测试。 中文文档:art-template中文文档跟着文档首先熟悉一下,然后看一下语法,跟着语法去实践一下,很快就可以上手完成功能。 Lodop打印控件介绍Lodop是支持浏览器端的web打印控件, 功能挺强大的。 官网地址:http://www.lodop.net/目前客户端有很多是基于浏览器内核套的壳,那么在需要特殊打印的场景下,可以试下这个控件。 三. 方案选择方案一:用html+css进行网页布局,html2canvas.js 来实现将网页转换成图片,然后直接用Lodop打印图片, 但是经过测试,打印出来的图片模糊不清,而且html2canvas.js的兼容性IE>8,所以不符合方案二:将这部分功能让后端去完成模板+数据渲染并生成图片去打印,但是发现跟方案一有相似的地方,解决不了图片打印模糊不清,但是可以解决兼容性问题,依然不符合方案三:采用html+css进行网页布局,用art-template进行模板渲染后生成html字符串,然后采用Lodop打印控件来直接打印网页。经过实际测试,打印出来的字迹清晰,而且art-template的兼容性在IE5下的功能也是正常的。所以最终就采用该方案四. 方案落地art-template模板编写 <!-- 58小票打印样式 --><script id="print58-tpl" type="text/html"> <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <style type="text/css"> body { margin: 0; padding: 0; width: 100%; } .clearfloat { overflow: hidden; } .left{ float:left; } .right{ float:right; } .font10 { font-size: 14px; } .fontW { font-weight:bold; } .font8 { font-size: 12px; } .margin2{ margin: 2px 0; } .margin5{ margin: 5px 0 !important; } .printer{ width: 174px; } .title { text-align: center; width:90%; margin:auto; padding: 5px 0; } .divide { text-align:center; margin:auto; } .detail { margin: 2px 0; } .detail>.left { margin-left: 10px; } .quan>.left { margin-left: 10px; } .bottom{ width:100%; height:200px; background:pink; clear:both;/* 位于上方写了float的div,下面这个div必须加这一句 */ } </style> </head> <body> <div class="printer"> <div class="title font10 fontW"> <div>{{shopName}}</div> <div style="margin-top:2px;">交易汇总</div> </div> <div class="divide">===================</div> <div class="haha clearfloat font8"> <span class="left">开始日期:</span> <span class="right">{{startTime}}</span> </div> <div class="haha clearfloat font8"> <span class="left">结束日期:</span> <span class="right">{{endTime}}</span> </div> <div class="content"> <div class="divide">-----------------------------</div> <div class="head font8 clearfloat fontW"> <span class="left">总收款:</span> <span class="right">{{totalAmount | toFixed}}元({{totalCount}}笔)</span> </div> {{each tradeList temp}} <div class="detail font8 clearfloat"> <span class="left">{{temp.pay_type_desc}}:</span> {{if depositState == 1 && temp.pay_type != 2}} {{if temp.tradeLogCount > 0}} <span class="right">{{temp.consume_money | toFixed}}元({{temp.tradeLogCount}}笔)</span> {{/if}} {{else}} <span class="right">{{temp.money | toFixed}}元({{temp.tradeLogCount}}笔)</span> {{/if}} </div> {{/each}} {{if depositState == 1}} <div class="detail font8 clearfloat"> <span class="left">押金:</span> <span class="right">{{depositMoney | toFixed}}元</span> </div> {{/if}} <div class="divide margin5">>>>>>>>>>>>>>>>>>></div> <div class="font8 clearfloat margin2"> <span class="left">打印人:</span> <span class="right">{{printer}}</span> </div> <div class="font8 clearfloat margin2"> <span class="left">打印时间:</span> <span class="right">{{printTime}}</span> </div> </div> <div> </body></html></script>上面的可以按照自己的样式效果,先写好静态页面,然后在根据art-template的语法动态设置 ...

June 20, 2019 · 2 min · jiezi

JavaScript展开操作符Spread-operator介绍

本文介绍JavaScript的展开操作符(Spread operator)...。本文适合ES6初学者。你可以通过展开操作符(Spread operator)...扩展一个数组对象和字符串。展开运算符(spread)是三个点(…),可以将可迭代对象转为用逗号分隔的参数序列。如同rest参数的逆运算。 用于数组以数组为例,首先创建一个数组, const a = [1, 2, 3], b = [4,5,6];你可以轻松赋值一个数组: const c = [...a] // [1,2,3]你还可以轻松拼接两个数组: const d = [...a,...b] // [1,2,3,4,5,6]也可以如下拼接 const d = [...a,4, 5, 6] // [1,2,3,4,5,6]如果要把一个数组b的元素全部插入到数组a的后面(不生成新数组),可以这样操作: const a = [1,2,3];a.push(...b);如果要把一个数组b的元素全部插入到数组a的前面(不生成新数组),可以这样操作: const a = [1,2,3];a. unshift(...b);类数组对象变成数组可以通过展开运算符把类数组对象变成真正的数组: var list=document.getElementsByTagName('a');var arr=[..list];用于对象展开操作符同样可以用于对象。可以通过以下方式clone一个对象: const newObj = { ...oldObj }注意: 如果属性值是一个对象,那么只会生成一个指向该对象的引用,而不会深度拷贝。也就是说,展开运算符不会递归地深度拷贝所有属性。并且,只有可枚举属性会被拷贝,原型链不会被拷贝。还可以用于merge两个对象。 const obj1 = { a: 111, b: 222 };const obj2 = { c: 333, d: 444 };const merged = { ...obj1, ...obj2 };console.log(merged); // -> { a: 111, b: 222, c: 333, d: 444 }当然也可以适用于以下的情况: ...

June 20, 2019 · 2 min · jiezi

IphoneX底部适配

1.判断是否是IPhoneX手机let isIphone = /iphone/gi.test(window.navigator.userAgent) let windowW = window.screen.width let windowH = window.screen.height let pixelRatio = window.devicePixelRatio let isIPhoneX = isIphone && pixelRatio && pixelRatio === 3 && windowW === 375 && windowH === 812 let isIPhoneXSMax = isIphone && pixelRatio && pixelRatio === 3 && windowW === 414 && windowH === 896 let isIPhoneXR = isIphone && pixelRatio && pixelRatio === 2 && windowW === 414 && windowH === 896 if (isIPhoneX || isIPhoneXSMax || isIPhoneXR) { // 底部增加fix-iphonex-bottm 样式 $(".contact-box").addClass('fix-iphonex-bottom') // 底部增加iphone-footer-bg样式 初始none,条件满足block $(".iphone-footer-bg").addClass('iphonexshow') }2.增加fix-iphonex-bottom样式.fix-iphonex-bottom { bottom: 34px !important;}如果想更改IPhoneX底部34像素的背景颜色怎么办呢?3.增加iphone-footer-bg样式.iphone-footer-bg { height: 34px; background: #6D6D6D; width: 100%; position: absolute; bottom: -33px; display: none;}.iphonexshow { display: block !important;}

June 20, 2019 · 1 min · jiezi

postman使用说明

本文主要描述postman的功能与使用方法Postman是404大厂的基于javascript语言完成的一款超级强大的插件,名字也很亲近(邮递员)。可以用于做API请求测试。前端后台测试使用Postman都可以提供很多帮助,使用方便而且功能全面。最赞的是还有接口文档在线生成,一边测试一边就可以完成文档的编写。 环境Postman有各种版本Mac,windows,linux上都能运行。此文主要介绍windows上的。安装1.可以选择在postman官网免费下载安装。2.如果怕麻烦可以直接点击右方下载 下载地址安装postman如果有不懂的小伙伴 可以传送至postman详细安装教程 功能模块 Collections:在postman初始化启动时,可以选择创建Collections。Collections就是项目所有的接口集合,可以分别存放各个模块的请求。通过collection的归类,良好的支持了分类测试软件所提供的API。Collection 还支持一键导入和分享,节约开发团队沟通成本。最厉害的是它还可以设置程序的环境,设置全局变量。提供json格式一键导入,让我们可以区分测试环境与正式环境的环境变量不同。也可以从面板将请求创建Collections: Workspace:postman对合作开发非常友好,在postman中可以通过邀请好友加入团队来共同协作完成测试与编写。点击Invite即可邀请成员加入团队。也可以创建自己的独立Workspace来隔离不同的项目。一个分布式的项目管理系统。 personal里是自己的工作空间,Team是你创建的团队或所加入的团队。 Built-in Tools:postman提供了一系列的工具方便测试,主要体现在面包板右侧的builder区。 点击send发送请求以验证您的API是否200。预请求脚本(pre-request Script)可以设置环境参数且可以先从其他接口获取数据再传入变量,可以使你的调试更加有效强大。在面板下方显示栏中,可以检查API的响应。点击右上角齿轮按钮可以配置环境,可以设置在其中的多个位置保存和重用值。postman可以配置proxy代理。Postman支持Markdown作为请求,Collection 和文件夹设置文本描述样式的方法。您还可以嵌入屏幕截图和其他图像,获得更具描述性的风格的API文档。Postman提供mockServer功能,模拟服务器自定义接口返回数据。目前只支持http请求 (未完待续。。。)

June 20, 2019 · 1 min · jiezi

ETM首席科学家DrAaron-YuanFacebook并不是在做一件与区块链有关的事

对于Facebook发布Libra白皮书一事,ETM首席科学家Dr.Aaron Yuan表示:首先,不可否认,这对于整个区块链行业而言,是里程碑事件,因为Facebook做了BAT一直想做但没能做的事。但行业预期也不要过高,还要考虑到实际金融政策、技术落地等现实条件。 看了Libra的白皮书,严格意义上来说,Facebook并不是在做一件与区块链有关的事,而是试图建立一个全球性的伪银行和支付网络。在其白皮书所披露的内容中,并没有详尽地介绍与区块链技术有关的细节,比如它所采用的共识机制许可链+BFT,具体的操作模式是什么,落地场景和应用准备怎么做,白皮书并没有讲得很清楚。 从它白皮书中金融方面的描述来看,感觉Facebook试图在全球范围支付中占有一席之地,类似于PayPal,或者中国的微信支付,但这件事,其实不需要以”区块链”的名义,也不需要发行Token就能做。“区块链”是不是它PR的一个部分?我们不得而知。 当然,如果Facebook真的能像它的白皮书中所说的,借用它的社交平台,打造一个有27亿用户的生态应用环境,这对于行业来说,将是历史性突破的一刻。

June 20, 2019 · 1 min · jiezi

前端培训中级阶段3-DOM-文档对象模型20190627期

前端最基础的就是 HTML+CSS+Javascript。掌握了这三门技术就算入门,但也仅仅是入门,现在前端开发的定义已经远远不止这些。前端小课堂(HTML/CSS/JS),本着提升技术水平,打牢基础知识的中心思想,我们开课啦(每周四)。 前面我们已经基本掌握常规的语法语义,以及基本的使用方法。接下来我们讲深入进去了解其中内在的原理。 今天讲什么?什么是 DOM ?DOM 文档对象模型HTML 元素接口DOM 元素继承什么是 DOM ?DOM 通常上来讲,我们可以理解为用 JS 操作 HTML 的 API或者说 JS 和 HTML 中间的处理器适配器。 文档对象模型 (DOM) 是 HTML 和 XML 文档的编程接口文档对象模型 (DOM) 将 web 页面与到脚本或编程语言连接起来。通常是指 JavaScript,但将 HTML、SVG 或 XML 文档建模为对象并不是 JavaScript 语言的一部分。DOM模型用一个逻辑树来表示一个文档,树的每个分支的终点都是一个节点(node),每个节点都包含着对象(objects)。DOM的方法(methods)让你可以用特定方式操作这个树,用这些方法你可以改变文档的结构、样式或者内容。节点可以关联上事件处理器,一旦某一事件被触发了,那些事件处理器就会被执行。文档对象模型 (DOM) - mdnDOM 文档对象模型圈起来的是比较常用的接口。 DOM 接口测试地址 DOM 接口 Attr用来表示一个 DOM元素的属性。大多数场景你可能会直接通过字符串的方式获取属性值(Element.getAttribute('name'))。其实还有(Element.getAttributeNode())返回Attr类型。目前 Attr接口 继承于 Node接口。DOM4 级别上会移出,所以尽量不要使用 Node接口上的属性 DOM 接口 Element非常通用的基类,所有 Document对象下的对象都继承它。Element接口继承 Node接口 DOM 接口 CommentComment 接口代表标签(markup)之间的文本符号(textual notations)。尽管它通常不会显示出来,但是在查看源码时可以看到它们。在 HTML 和 XML 里,注释(Comments)为 '<!--' 和 '-->' 之间的内容。在 XML 里,注释中不能出现字符序列 '--'。 ...

June 20, 2019 · 1 min · jiezi

带着canvas去流浪7绘制水球图

示例代码托管在:http://www.github.com/dashnowords/blogs博客园地址:《大史住在大前端》原创博文目录 华为云社区地址:【你要的前端打怪升级指南】 [TOC] 一. 任务说明使用原生canvasAPI绘制水球图,这将是一个非常有意思的挑战任务。水球图是一种常见的加载动画,属于扩展图形,在echarts中使用时需要下载扩展库(同为扩展库的还包括文字云插件和地图插件,项目地址为https://github.com/ecomfe/echarts-liquidfill)。 二. 重点提示水球图的绘制有以下几个难点: 水波的绘制水波的绘制实际上是运用简谐振动公式来模拟的,也就是x = A*(wt +),其中振幅A决定了水波的波纹高低,角频率w决定了水波的快慢,相位决定了初始位移差,再加上一些y轴方向的位移偏差和颜色的差异,就可以模拟出不同的水波,接着只需要在帧动画中不断改变并重绘曲线,就可以模拟出水波效果了。 球形剪裁区域水波的范围是不能流出球形的外轮廓的,此处的做法是在绘制水波之前,先使用context.clip( )方法将水波的可见绘图区域控制在水球之内即可,如果还有水球外的图形需要绘制,记得在每一帧绘制完水波后调用context.restore( )取消掉之前的剪裁。 文字的绘制如果只是绘制漂浮于水球图之上的文字,是比较容易实现的,但是如果想要实现一些细节更丰富的效果,并不那么容易。我们期望实现的效果是,当文字未被水波浸入时,显示水纹的蓝色,而被水浸润的部分显示为白色,这样看起来更加生动。但是绘制起来却并不容易,如果将文字绘制成蓝色,那么被水淹没的部分就会消失在水纹中,如果绘制成白色,那么水纹高度较小时,会完全看不到文字。那么这样的渲染文字要如何实现呢? 三. 示例代码let options = { value:0, a:20,//振幅 pos:[300,300],//水球图位置 r:160,//水球图半径 color:['#2E5199','#1567c8','#1593E7','#42B8F9']//水纹颜色};start(options);/** * 绘制水球图 */function start(options) { //移动绘图坐标至水球图左边界点 context.translate(options.pos[0],options.pos[1]); context.font = 'bold 60px Arial'; context.textAlign='center'; context.textBaseLine = 'baseline'; //计算水球图绘图数据 createParams(options); //开启帧动画 requestAnimationFrame(startAnim);}//生成水波动画参数,位置坐标公式为 y = A * (wt + )function createParams(options) { options.w = [];//存储水波的角速度 options.theta = [];//存储每条水波的位移 for(let i = 0; i < 4; i++){ options.w.push(Math.PI /(100 + 20*Math.random())); options.theta.push(20*Math.random()); }}//绘制水波线function drawWaterLines(options) { let offset; let A = options.a;//正弦曲线振幅 let y,x,w,theta; let r = options.r; //遍历每一条水纹理 for(let line = 0; line < 4; line++){ context.save(); //每次绘制时水波的偏移距离 theta = Math.random(); offset = r + A / 2 - (r*19/8 + A) * (options.value / 100 ) + line * r/12; //获取正弦曲线计算参数 w = options.w[line]; theta = options.theta[line]; context.fillStyle = options.color[line]; context.moveTo(0,0); context.beginPath(); //以0.1为步长绘制正弦曲线 for(x = 0; x <= 2*r; x+=0.1){ y = A * Math.sin(w * x + theta) + offset; //绘制点 context.lineTo(x,y); } //绘制为超出水球范围的封闭图形 context.lineTo(x,r); context.lineTo(x - 2 * r,r); context.lineTo(0, A * Math.sin(theta) - options.height); context.closePath(); //填充封闭图形得到一条水波 context.fill(); //截取水波范围,绘制文字(此处将在后文解释) context.clip(); context.fillStyle = 'white'; context.fillText(parseInt(options.value,10) + '%',options.r + 10,10); context.restore(); }}//绘制最底层文字function drawText1(options) { context.fillStyle = options.color[0]; context.fillText(parseInt(options.value,10) + '%',options.r + 10,10);}//帧动画循环function startAnim() { //用位移变化模拟水波 options.theta = options.theta.map(item=>item-0.03); //用百分比进度计算水波的高度 options.value += options.value > 100 ? 0:0.1; context.save(); resetClip(options);//剪切绘图区 drawText1(options);//绘制蓝色文字 drawWaterLines(options);//绘制水波线 context.restore(); requestAnimationFrame(startAnim);}/**设置水球范围为剪裁区域*(本例中并没有水球以外的部分需要绘制,实际上这里不需要加入帧动画循环中,只需要在开头设置一次即可。)*/function resetClip(options) { let r = options.r; context.strokeStyle = '#2E5199'; context.fillStyle = 'white'; context.lineWidth = 10; context.beginPath(); context.arc(r, 0, r + 10, 0, 2*Math.PI, false); context.closePath(); context.fill(); context.stroke(); context.beginPath(); context.arc(r, 0, r, 0, 2*Math.PI, true); context.clip();}浏览器中可查看效果: ...

June 19, 2019 · 2 min · jiezi

如何通过视频转换器将qsv格式转换成mp4格式

最近爱奇艺播出了一部《破冰行动》较为火爆,据很多网友判断这可能是继《士兵突击》后又一部里程碑式的电视剧。但是这部电视剧目前只能用爱奇艺进行观看。想要下载也只能下载爱奇艺的qsv文件。因此要用迅捷视频转换器把爱奇艺的qsv格式转换成mp4格式才能用别的播放器进行播放。 估计有好多小伙伴要说直接换个mp4后缀名不就好了,但是由于现在各大播放器都有自己的加密格式所以现在这个方法并不适用了。例如爱奇艺的“qsv”、腾讯视频和“qlv”酷狗的“kux”等都是无法通过直接更改后缀名来实现用别的播放器播放的。但是我们可以通过迅捷视频转换器把qsv格式转换成mp4格式。 1、首先我们在爱奇艺官网或者客户端中下载《破冰行动》到自己的电脑上。 2、然后到迅捷官网中下载迅捷视频转换器,并且安装到自己的电脑中,安装好后在软件中注册账号并且登录软件。 3、把刚才从爱奇艺下载的qsv格式的视频添加到迅捷视频转换器中。添加文件时可以点击添加文件夹或者直接将文件拖拽到软件中也可以。 4、qsv视频文件成功添加到软件中后,在软件中选择需要输出的文件格式,并且选择自己想要保存的路径就可以点击“转换”或者“全部转换”按钮进行格式转换了。 以上就是迅捷视频转换器的详细步骤了,当然了,迅捷视频转换器能转换的文件格式远远不只是爱奇艺的qsv格式,迅捷视频转换器输出的格式分为视频格式和音频格式,而主要视频输出格式有MP4、MOV、MKV、AVI、WMV、M4V、MPG、VOB、WEBM、OGV、3GP、FLV、F4V、SWF等格式。主要音频输出格式有MP3、WAV、M4A、WMA、AAC、FLAC、AC3、M4R、APE、OGG等格式。 在使用过迅捷视频转换器后我们发现这款软件相比别的软件更加的简单且拥有众多的主流功能使其变得更加的实用。在拥有迅捷视频转换器后我们就不用担心播放格式不同所带来的烦恼了。

June 19, 2019 · 1 min · jiezi

一行css代码搞定响应式布局

原文地址: https://medium.com/free-code-...原文作者: Per Harald Borgen 翻译作者: hanxiansen 在这篇文章中,我将教你如何使用 CSS Grid 来创建一个超酷的图像网格图,它将根据屏幕的宽度来改变列的数量。最精彩的地方在于:所有的响应特性被添加到了一行 css 代码中。这意味着我们不必将 HTML 与丑陋的类名(如col-sm-4, col-md-8)混杂在一起,也不必为每个屏幕创建媒体查询。ok,让我们发车吧。 设置在本文中,我将继续使用我在第一篇 CSS Grid 布局教程文章中的网格布局。然后,我们将在文章末尾添加图片。下面是我们初始化网格的外观: HTML 代码: <div class="container"> <div>1</div> <div>2</div> <div>3</div> <div>4</div> <div>5</div> <div>6</div></div>CSS 代码: .container { display: grid; grid-template-columns: 100px 100px 100px; grid-template-rows: 50px 50px;}注意: 示例中有一些基础的样式,但我在这里没有写出来,因为这对 CSS 网格布局没有任何影响如果这段代码让你感到困惑,我建议你去好好读下我的这篇文章Learn CSS Grid in 5 minutes ,其中就详细的解释了布局的基础知识。 让我们让列开始具有自适应特性吧。 基础响应单位: fractionCSS 栅格布局带来了一个全新的值:fraction单位,fraction单位通常简写为fr,它允许你根据需要将容器拆分为多个块。 让我们将每一列更改为一个 fraction 单位宽: .container { display: grid; grid-template-columns: 1fr 1fr 1fr; grid-template-rows: 50px 50px;}结果是栅格布局将会把整个宽度分成三个 fraction,每列占据一个 fraction 单位,效果如下: ...

June 19, 2019 · 1 min · jiezi

h5实现一键复制到粘贴板-兼容ios

实现原理采用document.execCommand('copy')来实现复制到粘贴板功能 复制必须是选中input框的文字内容,然后执行document.execCommand('copy')命令实现复制功能。初步实现方案 const input = document.querySelector('#copy-input'); if (input) { input.value = text; if (document.execCommand('copy')) { input.select(); document.execCommand('copy'); input.blur(); alert('已复制到粘贴板'); } }兼容性问题input 输入框不能hidden或者display: none;如果需要隐藏输入框可以使用定位脱离文档流,然后移除屏幕#copy-input{position: absolute;left: -1000px;z-index: -1000;}2.ios下不能执行document.execCommand('copy') 在ios设备下alert(document.execCommand('copy'))一直返回false查阅相关资料发现ios下input不支持input.select(); 因此拷贝的文字必须存在,不能为空字符串,不然也不会执行复制空字符串的功能参考这篇博客实现了ios下复制的功能 https://blog.csdn.net/VLilyV/... 主要是使用textbox.createTextRange方法选中输入框的文字 // input自带的select()方法在苹果端无法进行选择,所以需要自己去写一个类似的方法// 选择文本。createTextRange(setSelectionRange)是input方法function selectText(textbox, startIndex, stopIndex) { if (textbox.createTextRange) {//ie const range = textbox.createTextRange(); range.collapse(true); range.moveStart('character', startIndex);//起始光标 range.moveEnd('character', stopIndex - startIndex);//结束光标 range.select();//不兼容苹果 } else {//firefox/chrome textbox.setSelectionRange(startIndex, stopIndex); textbox.focus(); }}3.ios设备上复制会触发键盘弹出事件 给input加上readOnly只读属性 代码踩完以上的坑,总结的代码如下git地址 https://github.com/zhaosheng8... copyText = (text) => { // 数字没有 .length 不能执行selectText 需要转化成字符串 const textString = text.toString(); let input = document.querySelector('#copy-input'); if (!input) { input = document.createElement('input'); input.id = "copy-input"; input.readOnly = "readOnly"; // 防止ios聚焦触发键盘事件 input.style.position = "absolute"; input.style.left = "-1000px"; input.style.zIndex = "-1000"; document.body.appendChild(input) } input.value = textString; // ios必须先选中文字且不支持 input.select(); selectText(input, 0, textString.length); console.log(document.execCommand('copy'), 'execCommand'); if (document.execCommand('copy')) { document.execCommand('copy'); alert('已复制到粘贴板'); } input.blur(); // input自带的select()方法在苹果端无法进行选择,所以需要自己去写一个类似的方法 // 选择文本。createTextRange(setSelectionRange)是input方法 function selectText(textbox, startIndex, stopIndex) { if (textbox.createTextRange) {//ie const range = textbox.createTextRange(); range.collapse(true); range.moveStart('character', startIndex);//起始光标 range.moveEnd('character', stopIndex - startIndex);//结束光标 range.select();//不兼容苹果 } else {//firefox/chrome textbox.setSelectionRange(startIndex, stopIndex); textbox.focus(); } } };// 复制文字// 必须手动触发 点击事件或者其他事件,不能直接使用js调用!!!copyText('h5实现一键复制到粘贴板 兼容ios')/*兼容性补充: 移动端: 安卓手机:微信(chrome)和几个手机浏览器都可以用。 苹果手机:微信里面和sarafi浏览器里也都可以, PC:sarafi版本必须在10.2以上,其他浏览器可以. 兼容性测试网站:https://www.caniuse.com/*/ .

June 19, 2019 · 1 min · jiezi

怎么在阿里云搭建一个WordPress博客超详细建站教程

想以正确的方式启动一个 WordPress 博客吗?我知道,这可能是一个令人恐惧的想法 —— 其实你并不孤单。但是,在帮助很多用户创建博客之后,我决定编写一份详细的指南,让任何没有技术知识的人都能拥有一个自己的博客。 在这篇文章中,我将向你展示如何在 阿里云 上搭建一个 WordPress 博客,不需要任何技术经验。 启动 WordPress 网站的 6 个步骤创建阿里云账号选择一个虚拟主机启动 WordPress 网站选择一个域名将域名解析到虚拟主机上1、创建阿里云账号阿里云是目前国内最受欢迎的云平台,拥有各种弹性计算、网络、数据库、大数据等云服务,足以满足个人和企业的各种个性化需求。当然,在使用这些功能之前,你需要一个阿里云账号。 对于之前从没有使用过阿里云的用户,可以 点击这里 注册,然后你将会看到这个页面: 点击页面中的 免费注册 按钮,就会打开下图左边的页面: 注册账号非常简单,如果你不想注册,也没有什么问题,因为可以直接使用淘宝、支付宝、1688等账号登录。注册/登录成功之后,需要进行实名认证,点击控制台右上角的图像,选择实名认证,成功之后如下所示: 2、选择一个虚拟主机现在你已经有一个阿里云账号,接下来申请一台虚拟主机。 打开控制台,点击左上角的 产品与服务 菜单,选择 云服务器 ECS: 在新打开的页面中,点击 立即购买 按钮: 进入服务器设定页面,如下图所示: 系统默认给出的配置较高,目前我们用不上,需要修改一下: 地域:这个可以自行选择,但最好选择离自己最近的地方,我选择的是华东2(上海)。CPU:选择 1 核就行。内存:选择 1GB 就行,然后实例选择 突发性能实例 t5。配置为 1 核 CPU、1GB 内存的服务器足以支撑每天 1000 个访客。当你的网站流量在将来逐步上升时,你可以轻松扩展 CPU、内存、存储、带宽等各项参数。 镜像:系统镜像只有一个原生的操作系统,里面没有任何软件;自定义镜像相当于你的其他服务器副本;共享镜像相当于朋友的服务器副本;镜像市场里面拥有很多其他人制作的镜像。由于我们打算建设一个 WordPress 网站,所以在这里选择镜像市场,在弹出窗口中输入" WordPress博客系统 ",点击 搜索 按钮,然后选择免费的 wordpress 博客系统,点击 使用 按钮: ...

June 19, 2019 · 2 min · jiezi

模拟实现jQuery的on和trigger

前言:仅仅是简单模拟了$().on()和$().trigger(),仅支持id选择器,事件冒泡与事件委托。 代码: <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>模拟jQuery的事件绑定到触发过程</title></head><body><div id="A" style="background-color: deeppink"> 这是A <div id="B" style="background-color: aqua"> 这是B </div></div><script> //数据缓存 let events={} function $(elemId){ //只考虑理想情况 const element=document.querySelector(elemId) // console.log(element,'element27') function returnTrue(){ return true } function returnFalse(){ return false } $.event={ //不考虑用户的自定义事件 add:function (elemId,type,selectorReal,callbackReal) { let elemData=events[elemId] if(!elemData){ events[elemId]=elemData={} } elemData.handle=function(nativeEvent){ //锁定this return $.event.dispatch.call(this,nativeEvent) } if(!elemData[type]){ elemData[type]=[] elemData[type].delegateCount=0 //addEventListener只绑定一次 document.querySelector(elemId).addEventListener(type,elemData.handle) } let handlersCount=elemData[type].length let handlerObj={ type:type, handler:callbackReal, guid:++handlersCount, selector:selectorReal, } if ( selectorReal ) { //在下标为handlers.delegateCount++的位置插入委托事件 elemData[type].splice( elemData[type].delegateCount++, 0, handlerObj); } else { elemData[type].push(handlerObj) } }, dispatch:function (nativeEvent,) { let event=$.event.fix(nativeEvent) let handlers=events['#'+this.id][event.type] //继续锁定this let handlerQueue=$.event.handlers.call(this, event, handlers ) //为什么要用变量代替,因为循环的时候,需要保留该值 let matched,handleObj let i=0 while((matched=handlerQueue[i++])&&!event.isPropagationStopped()){ let j=0 while((handleObj=matched.handlers[j++])){ event.handleObj=handleObj handleObj.handler(event) } } // return event }, fix:function (nativeEvent,) { let $event={} //就是MouseEvent $event.originalEvent=nativeEvent $event.target=nativeEvent.target $event.type=nativeEvent.type // delegateTarget: div#A, // currentTarget: div#A, $event.timeStamp=Date.now() $event.stopPropagation=function() { this.isPropagationStopped = returnTrue; nativeEvent.stopPropagation() } $event.isPropagationStopped=returnFalse //fix 的标志 $event['chen'+(new Date()).valueOf()]=true return $event }, handlers:function (event,handlers) { let delegateCount = handlers.delegateCount let cur=event.target let handlerQueue=[] for(;cur!==this;cur=cur.parentNode||this){ let matchedHandlers = [] for(let i=0;i<delegateCount;i++){ let handleObj=handlers[i] matchedHandlers.push( handleObj ) handlerQueue.push( { elem: cur, handlers: matchedHandlers } ) } } cur=this if ( delegateCount < handlers.length ) { handlerQueue.push( { elem: cur, handlers: handlers.slice( delegateCount ) } ) } return handlerQueue }, trigger:function (elemId,type) { let element=document.querySelector(elemId) let eventPath=[] let cur=element let event={} event.target=cur event.type=type for(;cur;cur=cur.parentNode){ eventPath.push( cur ); } let i=0 //不考虑阻止冒泡的情况 while((cur=eventPath[i++])){ let handle=events['#'+cur.id]&&events['#'+cur.id].handle if(handle){ handle.call(cur,event) } } }, } return { on:function (type,selector,callback) { let callbackReal,selectorReal if(!type){ return } //如果selector是funcion的话,就没有委托元素了 if(typeof selector==='function'&&!callback){ selectorReal=undefined callbackReal=selector }else if(typeof selector==='string'&&callback){ selectorReal=selector callbackReal=callback } return $.event.add(elemId,type,selectorReal,callbackReal) }, trigger:function (type) { return $.event.trigger(elemId,type) }, } } //仅支持id选择器,事件冒泡与事件委托 //=========test1=============== $("#A").on("click" ,function (event) { console.log(event,"A被点击了") }) $("#A").on("click" ,function (event) { console.log(event,"A又被点击了") }) //=========test2=============== // $("#A").on("click" ,function (event) { // console.log(event,"A被点击了") // }) // $("#A").on("click" ,"#B",function (event) { // event.stopPropagation() // console.log(event,"B委托A被点击了") // }) //=========test3=============== // $("#A").on("click" ,function (event) { // console.log(event,"A被点击了") // }) // $("#B").on("click",function (event) { // // event.stopPropagation() // console.log(event,"B被点击了") // }) //==========test4============== // $("#A").on("click" ,function (event) { // console.log(event,"A被点击了") // }) // $("#A").on("click" ,function (event) { // console.log(event,"A又被点击了") // }) // $("#A").trigger("click")</script></body></html>根据上篇的流程图写出即可。 ...

June 19, 2019 · 2 min · jiezi

SEER主网网页钱包API节点列表更新-加入以获得更快的连接速度

SEER主网网页钱包API节点列表更新 加入以获得更快的连接速度 前段时间,因为网络原因,导致SEER主网网页钱包部分区域的API节点无法正常连接,当时就有小伙伴问了,为什么去中心化的区块链网络,还会被中心化的问题搞的无法访问呢? 在回答这个问题之前需要先向大家说明,API的问题目前已经解决了,爱好者们提供了大陆节点、新加坡节点、台湾节点和英国节点,可以满足各个区域SEER用户的访问需求,这些节点已加入列表中,连接时会自动选择。但由于浏览器缓存之类的原因,获取列表可能失败,大家可以手动添加节点: 大陆节点 wss://seernode.gedoumi.com 新加坡节点 wss://sg1.seerchain.org 台湾节点 wss://tw1.seerchain.org 英国节点 wss://uk2.seerchain.org 添加方式:菜单-设置-接入点-添加 API 服务器节点:ADDRESS中填入wss://sg1.seerchain.org 等API地址,然后确认。若处于连接错误页,则直接“添加 API 服务器节点”后点击RETRY重试。 回答之前那个问题,“为什么去中心化的区块链网络,还会被中心化的问题搞的无法访问呢? ”,作为一个多中心化架构的公有区块链平台,SEER由无数个全节点组成。其中根据分工,就有见证人节点、网关附属节点和API节点等,例如DAPP、网页钱包等应用,都是通过连接到API节点,向区块链广播交易,再由见证人签名,被全网确认,产生不可逆块。 虽然区块链网络是多中心化的,但节点的API服务本身却只是多中心化网络上的一个中心,如果出现问题,用户便不能通过这个API来使用区块链网络。 当然,用户还可以通过其它中心来和区块链进行交互,所以,前几天部分API节点出问题的时候,用户还可以通过英国节点使用网页钱包。 那么小伙伴们可能还是不放心,如果所有的API节点全挂了,那么用户怎么使用区块链网络呢。 如果有这样的极端情况,用户可以在自己的PC电脑上跑一个节点,用桌面钱包进行连接就可以了。 方法可以参考这篇文章:不依赖远程API启动命令行钱包和网页/桌面钱包的方法 https://docs.seerchain.org/#/...

June 18, 2019 · 1 min · jiezi

canvas实例-制作简易迷宫

这个系列分为两部分,第一部分为迷宫的生成及操作,第二部分为自动寻路算法。 我们先看效果:点击查看 我们直入正题,先说一说生成迷宫的思路。 整个思路十分简单: 首先我们将迷宫视为一个m行n列的单元格组合,每一个单元格便可以表示为 maze[i][j] 。接下来迷宫与m*n单元格的区别是什么呢?对,迷宫就是相当于不同单元格以某种规律相互连通,也就相当于我们把相邻的两个单元格之间的重合线给去掉,然后按照某种规律循环,便可生成一个迷宫。 我们假定从左上角开始出发,遍历每一个单元格,如果该单元格未被访问过,则查看其相邻元素(上,下,左,右)是否有未访问的单元格,如果有则随机取出一个相邻元素并打通他们之间的重合线,如果没有则回退到上一个单元格。 上代码:首先我们创建一个构造函数: function Maze(obj,col,row){ this.col = col || 10; this.row = row || 10; this.canvas = obj.getContext('2d'); this.init();}在这个构造函数中,我们接收三个参数,分别为canvas元素,迷宫的行数与列数,并直接调用Maze的init方法。 init : function(){ this.cell = (width - 2) / this.col; for(var i = 0 ; i < this.row ; i++){ maze_cells[i] = []; for(var j = 0; j < this.col ; j++){ maze_cells[i].push({ 'x' : j, 'y' : i, 'top' : false, 'bottom' : false, 'left' : false, 'right' : false, 'isVisited' : false, 'g' : 0, 'h' : 0, 'f' : 0 }) } } start_cell = {'x' : 0, 'y' : 0 }; start_row = start_cell.x; start_col = start_cell.y; visitRooms.push(start_cell) roomsLine.push(start_cell) maze_cells[0][0].isVisited = true; maze_cells[0][0].top = true; maze_cells[this.row-1][this.col-1].bottom = true; this.calcCells(0,0,maze_cells); this.drawCells(); maze_cells[0][0].top = false; maze_cells[this.row-1][this.col-1].bottom = false; this.drawRect(start_col,start_row); this.bindEvent(); },在init方法中,我们首先根据传入的列数col来计算单元格的宽度,然后构建一个maze_cells对象,其中每一行为一个数组,每个单元格包含的值分别代表x,y坐标,上下左右4个方向是否可以通行,是否访问过,还有该单元格的g,h,f值。我们假定迷宫的开口位于整个迷宫的左上角,出口位于右下角。visitRooms用来储存我们已访问过的单元格,roomLine则记录我们的访问路径。我们将迷宫的入口处和出口处的top,bottom分别设为true后再设置为false是为了在绘制的过程中不出现边框,绘制完成后保证不能向上(下)移动。 ...

June 18, 2019 · 3 min · jiezi

React复习进阶-高阶组件的使用配置装饰品模式新版context的使用

所谓高阶组件即使是接受一个组件作为参数, 返回一个新组件的函数, 用于提高组件的"自身能力", 提高组件复用性1.普通高阶组件HOC函数将父级属性乡下传递,并追加新属性,为Dumb添加样式和newName // App.jsimport React from 'react';import Dumb from './HocDemo';function App() { return ( <div className="App"> <Dumb name="木偶组件" color="#afa"/> </div> );}export default App;// HocDemo.jsimport React from 'react'//传入一个组件返回一个函数式组件const HOC = (Comp) => (props) => { const style = { display: 'flex', justifyContent: 'center', alignItems: 'center', width: '500px', height: '300px', border: `2px solid ${props.color}`, } return <Comp style={style} {...props} newName="高阶组件" />}// 木偶组件function Dumb(props) { return ( <div style={props.style}> 我是{props.newName || props.name} || 本体是{props.name} </div> )}export default HOC(Dumb);同样还可以为Dumb增加生命周期等,以便处理逻辑 ...

June 18, 2019 · 2 min · jiezi

通过json用canvas生成分享海报支持微信小程序和web

需求在项目里写过几个canvas生成分享海报页面后,觉得这是个重复且冗余的工作.于是就想有没有能通过类似json直接生成海报的库. 然后就在github找到到两个项目: wxa-plugin-canvas,不太喜欢配置文件的写法.就没多去了解mp_canvas_drawer,使用方式就比较符合直觉,不过可惜功能有点少.然后就想着能不能自己再造个轮子.于是就有了这个项目 json2canvas,你可以简单的理解为是mp_canvas_drawer的增强版吧. json2canvas canvas绘制海报,写个json就够了.项目的canvas绘制是基于cax实现的.所以天然的带来一个好处,json2canvas同时支持小程序和web功能支持缩放. 如果设计稿是750,而画布只有375时.你不需要任何换算,只需要将scale设置为0.5即可.支持图片圆角支持圆型,矩形,矩形圆角(背景色支持线性渐变)长文本自动换行(感谢 coolzjy@v2ex 提供的正则 https://regexr.com/4f12l ,优化了换行的计算方式(不会粗暴的折断单词))支持分组(cax里很好用的一个功能)同时支持小程序和web示例demo-web 界面左边的json,可以进行编辑,直接看效果哟~小程序demogit clone https://github.com/willnewii/json2canvas.git微信开发者工具导入项目 example/weapp/小程序安装npm i json2canvas微信开发者工具->工具->构建npm在需要使用的界面引入Component { "usingComponents": { "json2canvas":"/miniprogram_npm/json2canvas/index" }}举个例子想要生成一个这样的海报,需要怎么做?(红框是图片元素,蓝框是文字元素,其余的是一张背景图。) 简单,一个json搞定.具体支持的元素和参数,请查看项目readme { "width": 750, "height": 1334, "scale": 0.5, "children": [ { "type": "image", "url": "http://res.mayday5.me/wxapp/wxavatar/tmp/bg_concerts_1.jpg", "width": 750, "height": 1334 }, { "type": "image", "url": "http://res.mayday5.me/wxapp/wxavatar/tmp/wxapp_code.jpg", "width": 100, "x": 48, "y": 44, "isCircular": true, }, { "type": "circle", "r": 50, "lineWidth": 5, "strokeStyle": "#CCCCCC", "x": 48, "y": 44, }, { "type": "text", "text": "歌词本", "font": "30px Arial", "color": "#FFFFFF", "x": 168, "y": 75, "shadow": { "color": "#000", "offsetX": 2, "offsetY": 2, "blur": 2 } }, { "type": "image", "url": "http://res.mayday5.me/wxapp/wxavatar/tmp/medal_concerts_1.png", "width": 300, "x": "center", "y": 361 }, { "type": "text", "text": "一生活一场 五月天", "font": "38px Arial", "color": "#FFFFFF", "x": "center", "y": 838, "shadow": { "color": "#000", "offsetX": 2, "offsetY": 2, "blur": 2 } }, { "type": "text", "text": "北京6场,郑州2场,登船,上班,听到你想听的歌了吗?", "font": "24px Arial", "color": "#FFFFFF", "x": "center", "y": 888, "shadow": { "color": "#000", "offsetX": 2, "offsetY": 2, "blur": 2 } }, { "type": "rect", "width": 750, "height": 193, "fillStyle": "#FFFFFF", "x": 0, "y": "bottom" }, { "type": "image", "url": "http://res.mayday5.me/wxapp/wxavatar/tmp/wxapp_code.jpg", "width": 117, "height": 117, "x": 47, "y": 1180 }, { "type": "text", "text": "长按识别小程序二维码", "font": "26px Arial", "color": "#858687", "x": 192, "y": 1202 }, { "type": "text", "text": "加入五月天 永远不会太迟", "font": "18px Arial", "color": "#A4A5A6", "x": 192, "y": 1249 }] }问题反馈有什么问题可以直接提issue ...

June 18, 2019 · 2 min · jiezi

前端培训中级阶段2-事件event-事件冒泡捕获-20190620期

前端最基础的就是 HTML+CSS+Javascript。掌握了这三门技术就算入门,但也仅仅是入门,现在前端开发的定义已经远远不止这些。前端小课堂(HTML/CSS/JS),本着提升技术水平,打牢基础知识的中心思想,我们开课啦(每周四)。 前面我们已经基本掌握常规的语法语义,以及基本的使用方法。接下来我们讲深入进去了解其中内在的原理。 今天我们要讲什么?事件机制事件对象(Event)event loopDOM (与事件的关系,看不看无所谓)DOM(Document Object Model——文档对象模型)是用来呈现以及与任意 HTML 或 XML文档交互的 API。DOM 是载入到浏览器中的文档模型,以节点树的形式来表现文档,每个节点代表文档的构成部分(例如:页面元素、字符串或注释等等)。DOM 是万维网上使用最为广泛的 API 之一,因为它允许运行在浏览器中的代码访问文件中的节点并与之交互。节点可以被创建,移动或修改。事件监听器可以被添加到节点上并在给定事件发生时触发。DOM 并不是天生就被规范好了的,它是浏览器开始实现JavaScript时才出现的。这个传统的 DOM 有时会被称为 DOM 0。现在, WHATWG 维护DOM现存标准。-- MDN既然 DOM 有版本,那么在他的环境上事件的支持也是有版本的。文档 DOM 事件(0 级)body.onclick 这种定义方式的。 不可以多次监听事件,因为是赋值的方式,下次赋值会覆盖。只可以在冒泡阶段触发DOM 事件(2 级)addEventListener 方式定义的。 可以多次监听,切按监听顺序执行回调(有序)取消监听需要同一引用的函数。举个栗子 // 错误案例,两个方法不是同一引用,导致清除不掉 document.addEventListener('click', function(){}) document.removeEventListener('click', function(){}) // 正确案例,同一引用,可以清除。 function documentClick(){} document.addEventListener('click', documentClick) document.removeEventListener('click', documentClick) 可以选择触发阶段(冒泡&捕获) capture事件机制标准事件:EMCAScript 标准规定事件流包含三个阶段,分别为事件捕获阶段,目标阶段,事件冒泡阶段。先存个代码,之后的例子我们用这个例子。测试看我这里的 DEMO <html onclick="alert('html')"> <body onclick="alert('body')"> <a onclick="alert('a')">click</a> </body></html>事件捕获阶段捕获阶段:由外到内,触发规律为 html > body > a。如果想在捕获阶段就触发,需要传入参数 {capture: true} 事件冒泡阶段冒泡阶段:由内到外,触发规律为 a > body > html这个阶段执行是 W3C 默认的,等价于 {capture: false} ...

June 18, 2019 · 2 min · jiezi

带着canvas去流浪6绘制雷达图

示例代码托管在:http://www.github.com/dashnowords/blogs博客园地址:《大史住在大前端》原创博文目录 华为云社区地址:【你要的前端打怪升级指南】 [TOC] 一. 任务说明使用原生canvasAPI绘制雷达图。(截图以及数据来自于百度Echarts官方示例库【查看示例链接】)。 二. 重点提示雷达图绘制的看起来并不复杂,无非就是一些路径点的连线,其中的难点都在于一些细节。 坐标转换为了避免在绘制过程中不断根据夹角来计算某个数据点的坐标,我们可以让坐标系先移动到绘图中心,然后在绘制过程中逐步旋转并使用context.lineTo(x,y)来连线即可,这样做的好处是很明显的。比如在绘制背景六边形的时候,每次旋转后,路径点压根就不需要移动,直接在循环中每次都调用context.lineTo( )方法连线至同一个数据点即可,看起来位移没有变,实际上随着坐标系的旋转,连线绕过的是多边形的轨迹。 文字的对齐为了让文字保持正常的方向,我们需要将坐标系的旋转恢复到初始状态再进行绘制。绘制的过程中可以根据绘制点和中心连线相对于x轴的角度来动态修改其绘制时的相对点(left,right,center),否则就会出现下图的结果,也就是文字区域的中心到图形中心的距离的确是一致的,但这并不是我们想要的效果。 canvas坐标系请时刻记得canvas坐标系的初始方向是x轴向右,y轴向下,和普通笛卡尔坐标系是不一样的,尤其是在旋转角度和坐标计算的时候,很容易出现和预期角度不相符的结果。 三. 示例代码//options数据来自于百度Echarts官方示例库start(options);/** * 绘制图表 */function start(options) { drawBg(options); drawData(options);//绘制雷达图 drawText(options);//绘制文字}function drawBg(options) { let length = options.radar.indicator.length; let angleStep = -2 * Math.PI / length; context.strokeStyle="#b2b2b2"; context.lineWidth = 1; //调整坐标系 //移动中心点 context.translate(500,300); //将x轴旋转至竖直向上 context.rotate(-90 * 2 * Math.PI / 360); //每次以不同旋转半径绘制多个由大到小的图形 for(let r = 200; r > 0 ; r -=40){ //移动至第一个绘图点 context.save(); context.beginPath(); context.moveTo(r,0); //转动坐标系绘制所有点 for(let i = 0; i < length; i++){ context.rotate(angleStep); context.lineTo(r,0); } context.closePath(); context.stroke(); //明暗色替换填充,此处从大到小切换颜色覆盖式绘制即可 context.fillStyle = Math.round(r / 40) % 2 ? 'white':'#eaeaea'; context.fill(); context.restore(); }}/** * 绘制数据 */function drawData(options) { //解构赋值拿到数据关键点 let {radar:{indicator:indicators},series:[{data:data}]} = options; let colors = ['#c43e3a','#364c5a']; let length = indicators.length; let angleStep = -2 * Math.PI / length; for(let i = 0; i < data.length; i++){ context.save(); context.beginPath(); context.moveTo(200 * data[i].value[0] / indicators[0].max,0); //遍历每组数据 for(let j = 1; j < data[i].value.length; j++){ context.rotate(angleStep); context.lineTo(200 * data[i].value[j] / indicators[j].max,0); } context.restore(); context.lineTo(200 * data[i].value[0] / indicators[0].max,0); context.strokeStyle = colors[i]; context.lineWidth = 2; context.stroke(); } context.restore();}//绘制文字function drawText(options) { let {radar:{indicator:indicators}} = options; let length = indicators.length; let angleStep = 2 * Math.PI / length; let r = 220; context.fillStyle = 'black'; context.font = "14px bold 黑体"; context.textAlign = 'center'; context.rotate(90 * Math.PI * 2 / 360); for(let i = 0; i < indicators.length; i++){ let curAngle = -90*2*Math.PI/360 - angleStep*i; //根据方向调整文字的对齐点 let cos = Math.cos(curAngle); if (Math.abs(cos) < 10e-4) { context.textAlign = 'center'; }else if(cos > 0){ context.textAlign = 'left'; }else{ context.textAlign = 'right'; } console.log(indicators[i].name, Math.cos(curAngle)) context.fillText(indicators[i].name, r * Math.cos(curAngle), r * Math.sin(curAngle)); }}浏览器中可查看效果: ...

June 17, 2019 · 2 min · jiezi

jQuery之事件绑定到触发全过程及知识点补充

前言:最重要的还是最后的流程图,可以试着根据流程图手写实现$().on(),下篇文章会放出模拟实现的代码。 一、举例 <div id="A" style="background-color: deeppink"> 这是A <div id="C" style="background-color: aqua"> 这是C </div></div> $("#A").on("click" ,function (event) { console.log(event,"A被点击了") }) $("#A").on("click" ,"#C",function (event) { console.log(event,"点击了C,即C委托A的click事件被点击了") })二、$().on()(1)进行参数的调整(2)调用jQuery.event.add()方法 三、jQuery.event.add()最终调用elem.addEventListener()来绑定事件注意:(1)绑定常用的事件(如:click、focus),使用handleObj保存 handleObj = jQuery.extend( { //click,mouseout... type: type, //click,mouseout... origType: origType, data: data, //事件处理函数,如 function(){console.log('aaaa')} handler: handler, //索引,用于关联元素和事件 guid: handler.guid, //事件委托的标志,也是委托的对象选择器 selector: selector, needsContext: selector && jQuery.expr.match.needsContext.test( selector ), //命名空间,同一click事件有两个事件处理程序handler的话, //用这个标识,方便删除或添加handler namespace: namespaces.join( "." ) }, handleObjIn );(2)如果绑定的是自定义事件(如:windowResize),则使用handleObjIn保存 if ( handler.handler ) { handleObjIn = handler; handler = handleObjIn.handler; selector = handleObjIn.selector;}(1)、(2)都会初始化事件处理器(addEventListener): ...

June 17, 2019 · 2 min · jiezi

Vue项目部署在非网站根目录的解决方案

这篇文章主要介绍了在实际开发中遇到Vue项目编译后部署在非网站根目录的问题,通过搜索学习得到的解决方案。本次域名环境:www.admin.com/version1/修改配置文件修改打包后的资源引用路径找到config/index.js中build属性下的assetsPublicPath把/修改为/version1/build: { // Paths assetsRoot: path.resolve(__dirname, '../dist'), assetsSubDirectory: 'static', assetsPublicPath: '/version1/', ...}修改打包后的样式(图片、视频、字体文件等)引用路径找到build/utils.js中添加或修改publicPath: '../../'// Extract CSS when that option is specified// (which is the case during production build)if (options.extract) { return ExtractTextPlugin.extract({ use: loaders, fallback: 'vue-style-loader', publicPath: '../../' })} else { return ['vue-style-loader'].concat(loaders)}修改项目的路由在路由的history模式下,所有的路由都是基于根路径的,如/xxxx,由于项目部署在/version下,我们可以修改路由来保证页面正常访问我们可以来定义一个变量区分开发环境或生产环境 找到config/dev.env.js,定义一个ROUTER_BASE的变量,值为/,{代表开发环境是基于根目录}module.exports = merge(prodEnv, { NODE_ENV: '"development"', ROUTER_BASE: '"/"'})找到config/prod.env.js,定义一个ROUTER_BASE的变量,值为/version1/,{代表生产环境是基于version1目录}module.exports = merge(prodEnv, { NODE_ENV: '"development"', ROUTER_BASE: '"/version1/"'})vue-router里提供了一个base的属性,代表应用的基目录const routers = new Router({ mode: 'history', base: process.env.ROUTER_BASE, ...})此时base可以根据我们定义的变量ROUTER_BASE来区分环境 ...

June 17, 2019 · 1 min · jiezi

VueFlask实现一个图片分享网站及多平台部署

PicShare 网站简介源码地址 这是一个图片分享平台,借鉴Instagram的基础功能和页面布局并进行一点减法的移动端网页,也是我在移动端乃至Web项目的处女作,文章或者项目有问题的地方欢迎大家多多指正(o^^o) 先来点图登录&注册首页&内容发布评论&转发消息个人中心 项目技术栈前端:Vue.js + Vue Router + Vuex + ElementUI后端: Python Flask数据: MariaDB,对象云存储,图床功能模块登录&注册网站的内容需要登录使用,其中注册的第一项为设置头像,不少小伙伴及面试官没有看见而导致提交时候失败,这个地方是我的疏忽,后期有时间了进行优化其显示与验证功能 首页&关注用户登录成功后进入首页,首页可以获取到所有用户最近发表的图文动态,关注页面可以获取到所有关注用户的最近动态,用户可以通过点击点赞按钮对动态进行点赞操作,点击转发按钮进入内容转发页面,点击评论按钮进入评论页面 发表&转发提供给用户一个可以自由发表与转发的面板 消息用户可以收到与自己发表或者转发内容相关的消息,包括点赞,转发,评论,同时用户还可以收到与账户关系相关的消息,如关注,私信(有待实现) 个人中心页面的布局及内容完全模仿Instagram的移动端网页,用户可以通过个人中心展示自己或者他人的信息,他人信息的入口为显示用户头像及用户名的地方(首页&关注的内容去,评论内容区,消息详情区域) 粉丝&关注通过一个列表展示用户之间的关系,同时提供给用户关注与取消关注的按钮 项目部署前端默认当前目录为前端目录(frontend/) 安装所有的npm依赖 npm installbuild npm run build此时前端目录上一级得到的dist文件夹就是我们服务器部署需要的文件夹 后端默认当前的目录为后端目录(backend/) 确保你的服务器已安装Python 3 (推荐Python 3.6及以上)及虚拟环境 venv创建虚拟环境 python3 -m venv ./venv激活虚拟环境 source ./venv/bin/activate安装后端需要的依赖 pip install -r requirements.txt编辑自己的private_config.py SECRET_KEY 可以是字符串,通过这个字符串进行密码加密存储时的加盐HOST 数据库的地址,默认为本地USERNAME 数据库的连接用户名,我使用的是rootPASSWORD 数据库的连接密码PORT 数据库的监听端口,默认为3306DATABASE 数据库的名称,需要先建立数据库,不用建立表结构如果需要使用对象云存储服务,则需要对Bucket进行相应的配置服务器使用Nginx进行反向代理,配置文件参考backend目录下的default文件使用Heroku进行持续部署,配置文件参考backend目录下的Procfile文件部署结果个人主机:Picshare_running on_hostHeroku:Picshare runing on HerokuAzure: Picshare running on Azure总结这是我的第一个web应用,通过77次代码的提交,不断爬坑不断学习,从中学习到了如何使用H5,CSS3,JS,Python以及服务器部署 Github源码

June 17, 2019 · 1 min · jiezi

5大好用又免费BI软件系统

在BI诞生之前,业务数据的角色被忽略了。领导者通常依靠长期经验来做出重大决定。在某些重要时刻,经历可能会由于时间、地点和环境而导致不可预测的波动。这样的决定往往伴随着巨大的风险。现在可视化BI 可以帮助充分利用企业在日常运营中积累的大量数据,帮助企业做出理性的决策,降低风险,减少损失。然后,本文将分析五种主流的易于使用和免费的BI软件系统。 1 1、FineBI国产BI 排名前列。使用的过程是创建一个新的数据源,创建一个业务包,然后清理数据、关联,最后进行一系列操作,如制作工作表或仪表板。易于使用的特性非常便于在企业内部推广。官方网站有学习帮助文档,还有一个交流论坛。这种生态系统对用户来说非常好。可视化功能类似于Tableau,也不错。另外,权限管理等其他功能非常适合企业的实际应用。还支持数据分析和数据挖掘。个人使用是免费的,企业部署是基于功能和项目出价。 2、Tableau当数据量小时,Tableau速度很快,但当数据量大时,性能会下降。Tableau的可视化是其亮点之一,拖放操作基本上没有代码,并自动推荐合适的图表,非常方便。数据分析也是一个强大的特性,但是分组、过滤等都需要编写公式,这仍然有点困难。官方网站上有教学视频,但没有全部翻译,学习成本仍然相对较高。Tableau的试用版有15天的试用期,所以它很容易使用,但不是完全免费的。 3、PowerBIPowerBI的报表服务器有180天的免费试用期。这个产品是微软的,它的界面很像office,所以操作起来很熟悉。与Tableau相比,可视化功能较弱,图表中规中矩,但仍具有一定的实用性。它按用户和节点出价,每年的成本约为几十万元,比较昂贵。 4、Quick BIQuick BI是阿里巴巴云的产品,是基于云计算的自助BI工具服务平台。由于云计算的固有优势,Quick BI使组织能够以更低的拥有成本拥有业务智能平台。支持多种数据源,可以连接到云数据源如MaxCompute (ODPS),还支持连接自己的MySQL数据库。内置智能查询加速引擎,可以实时在线分析海量数据。 5、QlikQlik提供了三个程序的免费版本——QlikView Personal, Qlik Sense Desktop和Qlik Sense Cloud。QlikView旨在帮助企业整合来自多个数据源的数据,并探索数据中的相关性和可视化。Qlik Sense平台还具有数据压缩功能,可以将内存中的数据压缩到原始数据的十分之一,从而加快操作速度。个人版或免费版最适合个人使用,因为协作和共享是有限的,但它们有许多与完整版相同的核心功能。

June 17, 2019 · 1 min · jiezi

一文说清商业智能的好处概念架构

在大数据时代,大多数行业都开始发现数据的潜在价值,对数据分析的需求越来越大。因此,商业智能给企业带来了越来越多的好处。本文就来分析BI在挖掘数据价值方面具有固有的好处。 4 一、商业智能的概念商务智能,英语是Business Intelligence,简称BI,又称商务智能。很难对商业智能做出一个完整的定义。它是一个通称,指的是分析和处理企业中各种数据信息的软件系统。它将数据转换为知识、分析和结论,并帮助业务或决策人员做出正确而明智的决定。 Gartner Group将商业智能定义为:商业智能描述了一组概念和方法,这些概念和方法通过应用基于事实的支持系统来帮助制定业务决策。 二、商业智能的架构商业智能的体系结构主要包括数据挖掘(DM)、数据仓库(DW)和在线分析处理(OLAP)。如今,BI越来越受到企业的重视。许多商业智能软件还包括查询、报告和备份等功能系统。接下来,介绍其体系结构体系的主要三部分。 1、OLAP。OLAP,也称为多维分析,旨在满足决策支持或满足多维环境中的特定查询和报告需求。其技术的核心是维度的概念,使用户能够从多个角度和侧面观察数据库中的数据,从而深入了解数据中所包含的信息。例如,在按地区分析用户、比较不同产品之间的异同、观察销售变化等方面。 2、数据挖掘。利用神经网络、规则归纳等技术发现数据之间的关系,并进行基于数据的推理。 3、数据仓库(Data Warehouse)。包括数据转换、管理和存取等方面的预配置软件,通常还包括一些业务模型,如财务分析模型。 三、商业智能的好处1.商业智能最基本的好处是:将数据转化为价值。随着企业的发展,数据呈几何级数增长。通过商业智能,对企业的历史数据和不断增加的增量数据进行实时数据分析、数据挖掘和市场预测,从而做出领先的竞争对手的正确决策。这足以给企业带来巨大的利益。 2.提高效率:有了这个工具,业务人员可以随时分析数据,并使用数据支持决策。商业智能的过程可以大大减少企业在生产过程中对资源的浪费,降低企业的成本,增加人员的价值。 3.容易推广:BI主要是操作简单,不需要等待工作人员或其他专业技术人员来运行一个复杂的程序,以便数据支持决策的力量不局限于企业的最高领导层,也惠及广大的业务人员。 4.功能强大。一些例子会更直观。例如,BI可以对原始杂乱的数据进行分类、比较、分析和显示,从而提高数据的利用率。BI可以根据数据估计风险,并帮助决策者做出决策。合理的风险规避;BI可以更直观地显示数据,通过地图、图表和表格,让用户更直观地理解数据的价值。 BI能够给企业带来的好处实际上取决于公司所在的行业。具体来说,你还可以试用一些BI产品,比如FineBI,以了解BI产品的功能,这可以帮助更好地了解商业智能的好处。

June 17, 2019 · 1 min · jiezi

可视化BI是如何大大提高数据分析效率的

经过几十年的不断发展,可视化BI产品已经成为大型企业商业决策中不可或缺的工具。BI工具诞生之前,企业经营数据一直处于被忽视的状态,因为制作报表的时间、人力成本较高。可视化商业智能的出现大大提高了效率。 6 过去做报表的方法,是先找信息部门领导的excel数据,然后再考虑如何构建表格,如同比、利润率等,用excel制作表格,最后打印出来。然而,也有很多问题。 由于公司有多年的历史数据需要分析,而用excel打开几百兆字节的数据文件,一旦打开,它就会无限响应。领导者不喜欢看一堆数据,而是要用各种形象化的图表表示出来。3、使用Python等语言进行数据分析,这种方法对于非IT科班出身的人来说,存在学习成本高的问题。此外,这些高端方法可以解决数据量大的问题,但也有很多不足:可视化结果是一个静态页面,没有动态数据交互;而且界面没有过滤器,不能筛选过滤;不能立即进行深入分析;最重要的是在开发调试时,效率很低。 这些问题,在采取了可视化BI软件后,可以通通被解决。以FineBI为例,它的厂商——帆软公司,目前是IDC认证国内BI市场占有率第一的,它的可视化BI做的比较好了。使用它,可以发现可视化BI的优势很多: 1、FineBI是一款能免费试用的可视化BI。从帆软的官网下载安装即可用,它是B/S架构在线数据即席分析平台。 2、它上手容易,学习成本低。可以让不懂SQL/代码技术的小白快速上手,拖拽式自助数据可视化分析。拖拖拽拽,轻松统计出了公司多年来的销售金额和回款金额。跟以前一行行调试Python程序的代码相比,效果是一样的,但效率快了十倍不止!之后也可以在全公司的业务数据员中推广学习。 3、在可视化方面,FineBI提供默认的好看的图表选择,懒人必备!同时支持个性化选择,进一步为用户提供组件背景、仪表盘背景等设置功能,并可根据公司发布专属的美化升级模板。 4、做出来的仪表板,还自动带有交互性设置。可以联动、动态显示、钻取、筛选等等,无须返工做出一张一张的报表。 5、公司的数据量大,或者业务部门的数据报表需求非常多,甚至一些深度的复杂的数据分析的需求,FineBI都考虑到了。它能做到十亿数据秒级呈现,支持实时更新数据的需求,还有多种模式、几十种图表类型满足各类报表、仪表板的制作。若是你不用可视化BI软件工具的话,怕是远远不能想到如此丰富的可视化制作了。 一款能够真正多维深入地企业级可视化BI工具,就能够解决企业数据分析中存在的这些问题。赶快试用起来吧!

June 17, 2019 · 1 min · jiezi

数据分析师解读商业智能BI与数据挖掘DM的关系

数据挖掘是一个技术概念,而商业智能是一个非常广泛的应用概念,用于商业领域中数据的综合利用。本文就让数据分析师来解读,商业智能与数据挖掘的关系到底是怎样的。 6 一、商业智能与数据挖掘是什么数据挖掘的英文是data mining,简称DM,它的作用是描述过去,预测未来,评估未来。它是商业智能(BI)的一个重要应用方向。数据挖掘是从未处理的数据中提取信息的过程,其重点是发现相关性和模式分析。它可以帮助公司预测未来发生的事情,预测和评估风险。还需要统计分析功能来帮助分析客户细分、预测客户行为、预测客户业务趋势、识别欺诈等等。数据挖掘的一般功能包括分类、估计、预测、关联分类和聚类。 商业智能是利用现代信息技术收集、管理和分析结构化和非结构化的业务数据和信息,创造和积累业务知识,并改进业务决策。它是将数据中正确和有用的信息传递给适当的决策者,以便为决策提供有效的信息支持。 二、商业智能与数据挖掘的联系BI基于企业中的数据仓库,通过各种查询分析工具、在线分析处理(OLAP)工具或数据挖掘工具以及决策规划者的行业知识,从数据仓储中获得有利的信息,帮助公司提高盈利能力,提高生产力和竞争力。也就是说,商业智能(BI) =数据+人+工具+算法+知识+预测。 由此可见,数据挖掘只是商业智能的一部分。商业智能依赖于对不断生成和积累的数据的挖掘,从而得出一个论点。数据挖掘是实现商业智能的一种方式。事实上,数据挖掘的目的之一就是企业决策,这就是商业智能。 数据挖掘是一个技术概念,而商业智能是一个非常广泛的应用概念,用于商业领域中数据的综合利用。也可以说商业智能是数据挖掘技术在商业领域的应用。数据挖掘的步骤大致分为:业务理解、评价指标设计、数据提取、清理、数据转换、算法选择(聚类、预测算法、线性回归、时间序列、神经网络、决策树、贝叶斯分析、逻辑回归……)。 举个例子,像帆软的FineBI产品,数据挖掘、数据分析和报告表示是最关键的商业智能的主要组件。剩下的是一些参数,如处理数据的大小、挖掘深度、处理速度。FineBI的数据挖掘,是将以字段和记录的形式添加到多维数据库中,可以在创建新分析时从专用的数据挖掘服务包中使用,使用的方法与拖动任何正常字段没什么不同。

June 17, 2019 · 1 min · jiezi

StepByStep高频面试题深入解析-周刊04

关于【Step-By-Step】Step-By-Step (点击进入项目) 是我于 2019-05-20 开始的一个项目,每个工作日发布一道面试题。每个周末我会仔细阅读大家的答案,整理最一份较优答案出来,因本人水平有限,有误的地方,大家及时指正。 如果想 加群 学习,可以通过文末的公众号,添加我为好友。 __ 本周面试题一览:什么是闭包?闭包的作用是什么?实现 Promise.all 方法异步加载 js 脚本的方法有哪些?请实现一个 flattenDeep 函数,把嵌套的数组扁平化可迭代对象有什么特点?15. 什么是闭包?闭包的作用是什么?什么是闭包?闭包是指有权访问另一个函数作用域中的变量的函数,创建闭包最常用的方式就是在一个函数内部创建另一个函数。 创建一个闭包function foo() { var a = 2; return function fn() { console.log(a); }}let func = foo();func(); //输出2闭包使得函数可以继续访问定义时的词法作用域。拜 fn 所赐,在 foo() 执行后,foo 内部作用域不会被销毁。 无论通过何种手段将内部函数传递到所在的词法作用域之外,它都会持有对原始定义作用域的引用,无论在何处执行这个函数都会使用闭包。如: function foo() { var a = 2; function inner() { console.log(a); } outer(inner);}function outer(fn){ fn(); //闭包}foo();闭包的作用能够访问函数定义时所在的词法作用域(阻止其被回收)。私有化变量function base() { let x = 10; //私有变量 return { getX: function() { return x; } }}let obj = base();console.log(obj.getX()); //10模拟块级作用域var a = [];for (var i = 0; i < 10; i++) { a[i] = (function(j){ return function () { console.log(j); } })(i);}a[6](); // 6创建模块function coolModule() { let name = 'Yvette'; let age = 20; function sayName() { console.log(name); } function sayAge() { console.log(age); } return { sayName, sayAge }}let info = coolModule();info.sayName(); //'Yvette'模块模式具有两个必备的条件(来自《你不知道的JavaScript》) ...

June 17, 2019 · 4 min · jiezi

如何进行企业BI分析该如何选企业BI系统

新时代的BI也以各种形式出现:敏捷BI、移动BI、云BI……那么,这些先进的信息化系统是如何进行企业BI分析的,又该如何选择公司真正需要的企业BI系统呢?本文就来为你答疑解惑。 3-1F203153641418 一、企业BI系统的概念BI系统是一个可视化,智能化和自动化的数据管理系统,使决策者能够随时随地通过数据查看公司的运营情况并分析各种问题和机会。 为了满足客户大数据量、多样化数据的需求,新时代的BI也以各种形式出现:敏捷BI、移动BI、云BI。在BI竞争的新时代,传统的巨人还在,新的厂商也在进来。 二、该如何选企业BI系统企业真正需要的企业BI系统应该具备以下要求: 具有当前BI自我分析功能的BI。这是必须的,否则不能称为BI系统。具有传统的复杂报表生成功能。毕竟,在一个系统中,固定报表的比例仍然是最大的,特别是一些报告是中国式的复杂报表。能够进行数据收集和报告。很多场景都需要填报功能来收集数据,一半以上的系统需要能在展现的同时做采集。需要一个管理平台。系统应包括人员、权限、资源管理、资源推送和调度。要做仪表盘,能做大屏,管理看板,也被称为领导驾驶舱,一个屏幕掌握公司的重要数据,深入挖掘更深、更细粒度的一线生产数据,促进商业智能的过程中, 在辅助决策者决策的角色中,仪表盘非常有帮助和高效。三、如何进行企业BI分析以企业数据分析软件FineBI为例,介绍如何进行企业BI分析过程。 管理员创建业务包:创建业务包只是为后续分析准备数据,读取数据关联,并将数据转换为业务人员能够理解的数据,简而言之,就是数据准备过程。业务人员新建分析:业务人员根据实际业务情况在管理员创建的业务包中获取数据,然后对数据进行分析。简而言之,新建的实时分析是指创建一个模板来分析相应的数据。换句话说,这就是数据分析过程。3.领导查看分析:领导者查看业务人员创建的分析,根据分析结果发现问题,并协助决策,简而言之,就是数据结果查看过程。

June 17, 2019 · 1 min · jiezi

数据分析与BI的联系BI是如何做数据分析的

BI就是数据分析吗?两者的关系是怎样的?BI是如何进行数据分析的?要知道,数据分析与BI并不是完全等同的关系。本文就来解读数据分析与BI。 675bbec1dd125d2 一、名词解释BI是Business Intelligence的英文缩写,即商务智能。广义上,BI是指商务智能的一套整体解决方案;狭义上,BI是指可视化BI 产品,例如FineBI。 数据分析(DA)是用适当的统计分析原理,在专业系统和软件的帮助下,检查数据集,以计算出它们包含的有用信息。大数据分析技术广泛应用于商业领域,支持组织做出更明智的业务决策。 二、联系与区别从术语上讲,数据分析主要是指各种应用,包括商业智能(BI)、报表和联机分析处理(OLAP)到各种形式的高级分析。BI包括数据仓库、报表查询、数据分析、数据挖掘、数据可视化等。 所以,数据分析与BI并不是完全等同的关系,而是有交叉关系的两个领域。数据分析是BI的一个重要组成部分,BI是数据分析的一个典型应用。 三、BI是如何进行数据分析的?很多人觉得,Excel表格和BI技术差不多,都是用来做数据分析的。其实不然。 BI进行数据分析过程的第一步,是数据收集。现在的BI系统可以对接很多类型的数据仓库,大大提高了效率。下一步就是找到可能影响数据质量的问题,消除错误和重复数据,这在FineBI中可以很容易实现,建立自助数据集即可。然后构建数据分析模型,FineBI对这一复杂过程做了极大地简化,业务人员可以通过内置的数据挖掘功能,简单拖拽式操作之后就可以完成。 然后,就是数据分析的结果了,用户可以自主选择。举个例子,比如当公司管理者发现2008年的收入与2007年相比,下降了5.3%时,接下来怎么办?在BI系统中,可以首先从每个分店的角度进行分析,发现排名前两位的大店收入只有2007年的80%左右。然后,从产品的角度来看,这两个商店哪些品类的销售同比下降。再就时间而言,下降较快的品类是否有季节性?再回到分店的角度来分析,其他分店情况类似吗?然后从客户的角度来看,这些类别主要是哪些消费者消费……在BI中,这一连串的只需要通过点击,每个环节的几秒钟即可完成,总共一套分析下来,只需要几分钟的时间。 BI系统,真正做到了自助、敏捷的数据分析。

June 17, 2019 · 1 min · jiezi

5大知名的BI工具对比介绍

工欲善其事,必先利其器。企业对于BI工具的需求,已经刻不容缓。国内国外的BI工具不少,如Tableau、FineBI、Power BI等等。本文就对当下市面上最热门的5款知名的BI工具进行对比介绍。 4d388da7ecf445e8ba1d67042b9a99f4 1、FineBI FineBI是纯国内商业自助BI工具之一,属于fanruan的产品。它的数据处理很快,可以实时更新,并在数十亿秒内显示数据。在前端分析时,它呈现数据分析的结果也是很快的。其次,FineBI上手快,因为它基本上没有代码操作,几乎看一个10分钟的教学视频就可以掌握数据分析的操作方法。它的帮助文档资源也比较充足。最后,它还有全套的售后服务,完全不用担心不能落地的问题 2、Tableau Tableau是国际知名的BI工具。可视化功能是Tableau的王牌功能,可以通过单击或拖动感兴趣的维度(通常是离散的类别或特征)和度量值(值)来构建Tableau可视化效果。缺点就是价格太贵,而且国外的产品在国内往往有外包商承包实施。 3、Power BI Power BI包括用于Azure托管服务的Web界面和用于Windows桌面的power bi桌面应用程序。它的价格比竞争对手便宜得多,对于注重性价比的公司来说,它是一个不错的选择。它的缺点是数据分析能力或图表控制力不如FineBI或tableau。 4、Qlik Sense QlikView于2014年通过Qlik Sense扩展到自助BI的领域。Qlik Sense是一款基于与QlikView相同的内存关联数据索引引擎的自助式BI和可视化产品。Qlik Sense 2.0几乎可以连接到任何SQL数据库,并且可以对可视化进行大量控制。但是,它并不像Tableau那样易于学习,在可视化的呈现方面比Power BI更好,但不如Tableau好。 5、亿信WonderBI 也称为豌豆BI,也是国内一款知名的BI工具。在数据处理级别,通过点击操作,可以方便地删除重复的行、空替换、数据裁剪、数据脱敏、类型转换等操作。WonderBI允许用户一键浏览数据,系统自动匹配最合适的图形显示数据库数据,帮助用户初步了解数据规律,也可以在数字肖像的基础上进行二次分析。WonderBI学习成本低,整个过程无需编写表达式;还支持一键选择统计方法。图表类型算丰富,所有图表无需任何设置即可联动,也可以选择部分图表参与联动钻取。

June 17, 2019 · 1 min · jiezi

OLAP联机分析处理工具就是商业智能BI吗一文理清关系

OLAP(联机分析处理)和商业智能(BI)常常在一起出现,但事实上OLAP工具仅仅是BI的一部分,是一项十分关键的分析技术。本文就来仔细解释这一个问题,帮大家理清关系。 1、什么是OLAP OLAP也被称为多维分析,它的目标是满足决策支持或者满足在多维环境下特定的查询和报表需求,它的技术核心是维这个概念,“维”一般包含着层次关系。因此OLAP也可以说是多维数据分析工具的集合。 2、发展历程 当今的数据处理大致可以分成两大类:联机事务处理OLTP(On-Line Transaction Processing)、联机分析处理OLAP(On-Line Analytical Processing)。 起初是OLTP,它是传统的关系型数据库的主要应用,主要是基本的、日常的事务处理,例如银行交易。 1993年,关系数据库之父E.F.Codd提出了OLAP概念,认为OLTP已不能满足终端用户对数据库查询分析的需要,因为用户的决策分析需要对数据进行大量计算才行,仅仅是查询的结果并不能满足用户需求。因此,多维数据库和多维分析的概念被提出,即OLAP。 OLAP提供多维数据管理环境,其典型的应用是对商业问题的建模与商业数据分析。 3、应用场景 它的应用场景有很多:市场和销售分析、电子商务分析、基于历史数据的营销 、预算、财务报告等等。 举个例子,更便于理解。一个企业在考虑产品的销售情况时,通常从时间、地区和产品的不同角度来深入观察产品的销售情况。这里的时间、地区和产品就是维。而这些维的不同组合和所考察的度量指标构成的多维数组则是OLAP分析的基础,可形式化表示为(维1,维2,……,维n,度量指标)。比如按地区分类,按时间排序,比较不同产品间的异同,观察销售额的变化等等。 4、OLAP的结构与功能 OLAP的多数据结构一般有:超立方结构(Hypercube) ,多立方结构(Multicube)。 OLAP多维分析功能包括了对数据采取切片(Slice)、切块(Dice)、钻取(Drill-down和Roll-up)、旋转(Pivot)等各种分析动作,以求剖析数据,使用户能从多个角度、多侧面地观察数据库中的数据,从而深入理解包含在数据中的信息。 5、OLAP的优势 1、多维性:它面向分析,分析驱动,支持多维分析。“维”是人们观察数据的特定角度,是考虑问题时的一类属性,属性集合构成一个维(时间维、地理维等)。 2、信息性:它可以支持管理需要,面向决策人员;可以导出综合性和提炼性数据信息。 3、强处理性:OLAP一次处理的数据量比OLTP大得多。 4、快速性:用户对OLAP的快速反应能力有很高的要求。系统应能在5秒内对用户的大部分分析要求做出反应。 而商业智能不仅仅是OLAP工具,它还包含数据挖掘工具、统计分析工具等等,增强决策分析功能。

June 17, 2019 · 1 min · jiezi

关于移动BI你不可不知的东西

“只要有手机就能活”的现代社会,你还在电脑面前看报表?移动BI可将报告和数据转换为移动仪表板,并将它们即时传送到任何移动设备。越来越多的企业开始重视移动BI,并将其作为企业IT战略的一部分。移动BI是一个很大的话题,本文就来谈谈关于移动BI你不可不知的东西。 727049-20160428135900361-2133125783 一、什么是移动BI?移动BI(Mobile Business Intelligence),即移动商务智能,定义为一个包含技术和组织元素的系统。它让用户通过使用移动终端设备,可以随时随地获取所需的业务数据和分析显示,完成独立的分析决策应用,实现对决策分析的实时动态管理。 虽然移动计算的概念已经流行了十多年,但移动商业智能只是最近才开始发展。出现这样的变化,不得不说智能手机贡献很大。移动设备的出现彻底改变了人们在移动设备上使用数据的方式。这包括移动BI。 移动商业智能近来迅猛发展,它可以使企业数据变得活跃,随时随地查看企业数据,分析数据和呈现数据。移动BI结合了计算机技术、通信技术和互联网技术,消除了时间和空间的限制。企业高管和基层员工都可以使用移动BI辅助决策。 二、移动BI的优势1、无需代码,拖拉拽即可开发报表。 2、使用BI平台变更管理工具,可以轻松修改和维护应用程序。 3、可以使用大多数类型的数据可视化,而不仅限于少数。 4、平台提供专业的企业BI解决方案。 三、移动BI应用场景:以东方融资网为例,该企业为总部、分公司的中层以上管理者打造了移动业务数据分析平台——FineMobile。随着移动互联技术的成熟,管理决策者更愿意在移动设备上办公, 提供实时业务数据查询与分析,分支机构运营数据比较分析,融资平台运营趋势分析等报表。 而且上述所有的数据都是实时刷新的,不管高管在出差途中,在飞机上、高铁上,或者躺在沙发上,还是在会议中,都可以实时看到最新的数据。 四、移动BI产品有哪些?目前市面上的移动BI产品不少,有Finemobile、移动版QlikView、MicroStrategy 移动应用平台、RoamBI、Birst Mobile、RoamBI、Infor Motion Road Warrior、SAP BusinessObjects Explorer、IBM Cognos Mobile等等。 帆软FineReport带有移动BI功能——数据决策平台移动客户端,使用者可以在iphone、ipad及android智能手机上访问平台、浏览处理报表,查看分析企业的数据,帮助用户做好时间管理,充分利用时间碎片。 帆软旗下的FineBI也有移动BI解决方案,可直接手机浏览器访问,或集成到微信/钉钉/其他APP中,可以直接通过URL方式调用HTML5解析的报表。可以自适应显示、手势操作,也支持即使备注与分享数据。 在企业高速发展过程中数据可视化分析必不可少,移动BI能够让企业的数据活起来,随时随地查看、分析、展现企业数据。

June 17, 2019 · 1 min · jiezi

四大热门的自助BI工具深度测评

在了解过自助式BI的基本知识之后,我们知道传统BI工具已不能满足企业对于及时性数据分析的需求,以IT主导的商业智能BI和分析将逐步演变为以业务为主导的自助式分析。本文就来深度测评市场上几大热门的自助BI工具:FIneBI,Tableau,亿信WonderBI,PowerBI。 a1db1ab139b7496ea0482e345644b0fe 1、FineBIFineBI是一个很“快”的自助BI工具。它的“快”体现在: 第一,数据处理很快。在读取数据时,FineBi的FineIndex方法访问数据,并使用类似于传统多维数据集构造的缓存机制,减少了重复提取原始数据的工作,降低了硬件系统的压力。更新数据时,它可以实时更新,并在数十亿秒内显示数据。有些企业数据量不大,但业务复杂,分析需求多,灵活性要求高。通过这种方式,它可以直接连接到基于SQL数据库FineDirect的引擎。FineDirect可以直接访问10亿甚至100亿的数据量,这大大加深了分析的厚度和深度,提高了分析的准确性。在前端分析时,它呈现数据分析的结果也是很快的。 其次,FineBI的帮助文档中,每一种图表都给到了应用场景的提示,比如对地域分析要求较高的数据选用GIS地图。以此来避免因为选错图表,而导致数据分析错误的情况。 第三,它能改善企业部门间的沟通协作流程,让分工协作更加快速。IT人员或数据管理员可以以业务主题和业务包的形式准备数据,并对数据设置操作权限(不同职位的人员可以智能地在权限范围内操作数据。数据整理后,业务人员只需要从数据包中读取数据,然后在前端进行分析,无需重复沟通。而且它有实时更新的特点,做好的报表只要推送给领导即可及时查收。 2、TableauTableau将其产品描述为提供“按您的想法工作的分析”。在Tableau中调整和转换数据很容易,就像在Excel中一样。您可以添加计算字段或过滤数据,而不必返回到导入阶段。可视化功能是Tableau的王牌功能, Tableau为其易于使用的实现和对图表显示的细粒度控制设置了标准。您可以通过单击或拖动感兴趣的维度(通常是离散的类别或特征)和度量值(值)来构建Tableau可视化效果。还可以通过在线将仪表板和故事发布到Tableau服务器或Tableau与其他人共享。 3、亿信WonderBI也称为豌豆BI,为了使业务人员能够完成自助BI数据分析,它自动识别索引维度和相关关系,形成数据模型。在数据处理级别,通过点击操作,可以方便地数据裁剪、数据脱敏、类型转换等操作。WonderBI学习成本低,支持一键选择统计方法,如最大、最小、排名、比例、同比、月同比、上一期、去年同期等,以满足需求各种用户对业务数据的综合分析。WonderBI支持HTML5统计图表,图表类型丰富。并支持联动钻取,即同一看板可以改变角度查看数据,WonderBI所有图表无需任何设置即可联动,也可以选择部分图表参与联动钻取。 4、Power BIPower BI是微软进入自助BI工具策略的入口,包括用于Azure托管服务的Web界面和用于Windows桌面的power bi桌面应用程序。它的价格比竞争对手便宜得多,对于注重性价比的公司来说,它是一个不错的选择。对于某些数据源,Power BI具有预定义的图表、仪表盘和报表,这对用户来说比较方便。另一方面,它的缺点是数据分析能力或图表控制力不如FineBI或tableau。

June 17, 2019 · 1 min · jiezi

权威解读自助式BI为什么这么火

现代技术的不断进步,已将数据分析的任务从IT转移到业务人员、管理人员的自助服务。自助式BI应运而生。商业智能(BI)分析平台如今是大中型企业信息建设的主要内容,新趋势自助式BI自然也备受瞩目。本文就来解读自助式BI的相关概念。 3-1F203153641418 一、什么是BI?商业智能(BI)分析平台如今是大中型企业信息建设的主要内容。通常,商业智能包括应用程序、基础设施、工具等等,可以访问和分析信息,支持决策。不管是什么平台环境、应用程序或基础设施下,BI可以部署模块化、可扩展、基于标准的商业智能解决方案体系结构,以便在整个企业内提供服务。 二、自助BI是什么?自助式BI,就是自助式商业智能。 现代技术的不断进步,已将数据分析的任务从IT转移到业务人员、管理人员的自助服务。自助式BI应运而生,自助式BI的重点就是人人可用,而且时间更快,效率更高,让公司通常可以决定在几天内采取行动,而不是花费数月时间来做出决定。 三、自助式BI的好处及特点有哪些?数据可视化分析是自助式BI的关键组成部分。借助自助式BI,用户可以自由浏览他们的数据并自主选取观察数据的角度。自助式BI支持数据可视化或图形描述,以帮助人们查看交互式(可点击)数据可视化,支持向下钻取以探索细节,识别模式和异常值,并更改处理哪些数据,更容易识别新兴趋势。 举个例子,零售商希望探索不同的数据维度,包括批发成本,零售价格,库存老化,运输成本和产品推广数据。为此,用户可以构建自定义报告或使用数据探索工具来直观地查找数据他们需要并允许他们回答他们的即席查询问题。 自助式BI还可以供数千名用户设计和扩展丰富、交互式的仪表板,以及针对Web,打印或移动设备的临时报告。 除此以外,自助式BI还具备许多一般BI的好处。 四、如何选择自助式BI?一般选择自助式BI时,需要从用户的角度和IT基础架构的角度找到最适合企业的平台。 从用户的角度看,首先,自助式BI平台需要与使用它的人员的技能相匹配。这时候就要该BI产品具备易用、上手快、学习资料充足的特点,才能让员工可以轻松学习和使用它。第二,自助式BI应该具备良好的性能,功能强大,能确实起到简化工作、提高工作效率的积极影响。否则,一项拖后腿的工具只会给公司带来更大的损失。 从IT基础架构的角度看,自助式BI产品要能够读取本公司所有内部和外部数据源,支持在BI平台内轻松清理和转换数据,支持显示业务需要的所有图表。还有共享设置、权限设置等功能在企业中也是十分重要和实用的功能。 市场上,自助式BI十分多,可以了解更多自助式BI产品的相关信息。而且,BI产品最好经过试用,才知道是否真正适合企业。

June 17, 2019 · 1 min · jiezi

主流趋势之云商业智能BI的全面解读

什么是云商业智能(Cloud BI)?为什么最近成为一种新趋势?本文将从概念、面向群体、优势、劣势几个方面来深度分析。 一、概念 云商业智能(Cloud BI)即基于云的商业智能。 BI即商务智能,它是一套完整的解决方案,用来将企业中现有的数据进行有效的整合,快速准确地提供报表并提出决策依据,帮助企业做出明智的业务经营决策。商业智能BI在数据架构中处于前端分析的位置。 云计算的本质就是将计算能力作为一种较小颗粒度的服务提供给用户,按需使用和付费,体现了:经济性,不需要购买整个服务器。快捷性,即刻使用,不需要长时间的购买和安装部署弹性,随着业务增长可以购买更多的计算资源。 二、面向群体 云商业智能产品通常对一些小企业来说更具有吸引力,其中的一个原因是因为这些小企业内部一般都不设有IT运维和管理部门,以管理其内部部署的产品和服务。 现在一些大企业也开始部署云商业智能,而且一般都是从单一的工作小组或部门开始。 三、优势 通常,BI解决方案需要专家团队进行现场托管。但是,考虑到所涉及的维护成本,对您的公司而言,这可能是一项代价高昂的事情。 云解决方案具有成本效益,可以提供更好的数据存储和高级洞察力。企业部署云商业智能服务,主要是因为它有利于加快其产品投入市场的时间,企业也不需要去维护内部部署软件,而且非常简单易用,这一点很重要。 四、劣势 网络安全风险不容小觑,这一点是致命劣势,对企业可能带来巨大的风险。 对于这一点,也有相应的对策,就是企业将某些高度敏感的数据存储在混合云环境中——在公司的服务器中,私有云和第三方服务提供商很可能获得广泛的关注。 其实,云BI与敏捷商业智能有类似的优势,有时敏捷BI甚至优于云商业智能,建议阅读《敏捷商业智能(BI)的最新全面解读》了解更多相关知识和信息。

June 17, 2019 · 1 min · jiezi

2019商业智能报表工具的全方位剖析

“商业智能”、“报表”都是当下信息时代的热词,但是报表工具和BI的区别和联系究竟是什么呢?小编这就一文解决这普遍存在的困惑,从产品理念、典型应用场景、功能使用、面向群体、企业应用情况这5各方面解释,帮助企业理清关系,科学决策。 1 1、产品理念所谓报表,简单的说:报表就是用表格、图表等格式来动态显示数据,可以用公式表示为:“报表 = 多样的格式 + 动态的数据”。诸如经典的Excel、国内的FineReport、国外的水晶报表等等,这类产品的本质都一样,就是统计和展现数据,并提供基础的分析功能如排序、总计、方差等。 而BI软件从产品理念上就跟报表不一样。BI(Business Intelligence,简称:BI,中文翻译就是商业智能),又称商业智慧或商务智能,指用现代数据仓库技术、线上分析处理技术、数据挖掘和数据展现技术进行数据分析以实现商业价值。本质是数据+业务理解,数据部分和报表类似,就是统计和展示数据,业务理解部分是通过各种BI软件的功能实现深度的数据分析+智能的数据预测。比较有名的有国内的FineBI、国外的Tableau。 一言以蔽之,报表产品的目的是帮助用户掌握和了解数据,让报表使用者通过观察企业数据,知道当下的情况。商业智能的目的是通过应用基于事实的支持系统,来辅助商业决策的制定。 2、典型应用场景报表的应用场景主要就是业务报表制作,比如销售月报,季报和关键数据指标的统计、展示和分析。看这些报表就可以知道当月总销售额、各个销售员的业绩等等。主要是通过统计已知数据,了解总体和细节上的事实。 商业智能软件,还可以基于这个报表进行探索分析,比如分地区、分门店查看,比如使用不同的图表(折线图、饼图、柱状图等)来获取不同视角下的结论,甚至还能对未来做出预测。领导看这些时,就可以进行多方位的分析,辅助决策。这是和报表核心区别。 3、功能使用报表软件,还是那个公式“报表 = 多样的格式 + 动态的数据”。它们有专门的报表结构来动态的加载数据,同时也能够实现报表格式的多样化。这也是报表区别于数据库软件的一大特点:数据库软件没有实现报表软件的”格式多样化”的特性。 商业智能可以和大数据平台对接,处理更大的数据量。数据处理方面有钻取、联动、旋转、切片、预警。当然有些报表工具也可以完成这一部分工作。商业智能工具侧重于数据分析,所以在报表制作难度上大大降低但换来的代价是,不能制作复杂的报表。 4、面向群体报表主要面向IT开发者,或者某些企业专门设置的报表开发人员。 商业智能主要面向业务人员、数据分析人员,操作简单,侧重分析。 两者最后的报表和数据分析结果都是给领导、管理层看的,他们通过分析结果来制定决策。 5、企业应用情况国内大部分企业还是使用的报表软件,主要用以解决企业内数据统计和展示的需求。而BI的应用集中在信息化水平较高的行业中,比如银行、零售、电商、互联网公司。 而国外企业因为信息化更加早,已经普遍应用商业智能了。 在信息化的大趋势下,商业智能的应用会越来越广泛。任何学习,“知识+实践”才能真正掌握,读者试用一下才能真正了解它们的不同。例如FineReport报表软件、FineBI商业智能平台都是可以个人免费试用哦。也最好了解更多的新趋势,比如敏捷商业智能(BI)。

June 17, 2019 · 1 min · jiezi

敏捷商业智能BI的最新全面解读

什么是敏捷商业智能?该如何正确应用BI?当下主流的敏捷商业智能产品/解决方案提供商有哪些?本文就对这些问题进行全面深入的研究与解答。 一、什么是敏捷商业智能? BI(Business Intelligence),中文翻译是商业智能又称商务智能。 数据时代,人们接受了“数据化运营、决策“的理念,企业的经营面临越来越激烈的竞争,如果部署数据分析平台还像10年前经历漫长实施过程的话,那么数据化运营将成为空谈。于是数据时代催生了敏捷需求,满足市场期望的“敏捷商业智能“出现了。 敏捷这个词汇,最早用来描述一种能够增加客户满意度的软件开发过程–敏捷式开发过程。敏捷是要商业活动中做出迅速反应。传统的BI解决方案往往需要三个月甚至半年的实施周期。从数据建模到数据展现,整个研发周期冗长而低效。 敏捷BI并不是指某个前端工具软件,而是贯穿在数据分析平台构建和运行过程中的快速实现能力。 二、敏捷商业智能的特征 它主要有以下4个方面的特征:业务模型开发和设计,数据分析,实施团队和基础架构。 首先,传统商业智能软件很难应对业务模型的变化,敏捷式BI具有更好的适应业务数据模型的灵活性,更能适应当前经济全球化背景下的新经济模式。 其次,数据分析能力是商业智能过程的核心功能,敏捷BI允许终端业务人员自己通过交互性很强的界面完成即时信息的分析,比起传统的BI大大缩短了商业智能需求的实施过程。 第三,实施团队也是BI能否落地并发挥效用的关键因素。敏捷BI要求商业智能厂商意识到内部协作的重要性,能够首先建立一支这样的商业智能化实施团队,有业务人员和IT人员共同参与并且能够并肩战斗,保证BI项目的成功实施。 最后,云计算、虚拟化、软件在线服务等新兴技术的出现,挑战了传统BI的基础架构。于是涌现出一批新型中小企业能够以更低的费用和更快的周期更好地让BI项目敏捷化,完全具备与大公司竞争的实力,例如国内市场占有率的帆软公司的FineBI产品就是典例。无论是部署、交付、制作、变更,还是用户查询,都是快而有效的,加快了需求沟通流程,大大缩短了项目开发周期。。 三、如何应用敏捷BI 第一,“工欲善其事必先利其器”,选择合适的敏捷商业智能是重中之重。第二,高层领导对于敏捷商业智能项目的应用要多多支持,给予实施者应有的权利。第三,企业实施的项目团队应和产品所有者一起实施该项目。而且实施团队的组成人员要多样化,既要有业务人员,也要有IT技术人员。第四,敏捷性项目开发时要注意满足用户的需求。 四、主流的敏捷商业智能产品/解决方案提供商 Tableau,FineBI,QlikView……都是最近热门的。具体这些工具的测评,可以在本站的另一篇文章《主流的敏捷商业智能平台厂商排名》中看到。

June 17, 2019 · 1 min · jiezi

SVG的正确使用姿势

原文地址: https://css-tricks.com/using-...原文作者: Chris Coyier 翻译作者: https://github.com/chenmf6 翻译出处:https://github.com/lightningm... SVG是一种向量图的图片格式,即可伸缩向量图(Scalable Vector Graphics),可以在Adobe Illustrator里面生成。在Web中使用SVG很简单,但是也有一些需要知道的事情。 为什么用SVG压缩后文件体积小可以无损伸缩到任意尺寸(除非尺寸特别小)在retina屏幕上可以完美显示设计可控,比如交互和滤镜怎么生成SVG可以在Adobe Illustrator里设计并且得到SVG。下面是一个站在椭圆上的奇异鸟:留意到画板刚好贴着设计主体的边缘,画布的大小在SVG里面的重要性和在PNG和JPG里面是一样的。然后可以直接在Adobe Illustrator里面保存成SVG文件。 保存的时候,可以在duihua对话框里面选择SVG选项。完整的参考可以看SVG 介绍。这里选SVG 1.1就可以了。 当点击'OK'或者'SVG Code...'的时候,就会打开文本编辑器,显示SVG的编码。 在<img>标签里面使用SVG如果把SVG保存成文件之后,可以直接在<img>标签里面使用。 HTML<img src="kiwi.svg" alt="Kiwi standing on oval">在Illustrator里面,画板的大小是612px ✕ 502px:这正是图片在页面中的大小。可以选择<img>标签并且改变width和height来改变它的尺寸,就像PNG和JPG一样,比如: 前往codepen查看 浏览器支持在<img>标签里面使用需要有浏览器支持。基本上在IE8以上和Android 2.3以上都可以用。如果你想要在不支持的浏览器里面使用,可以这样: 使用Modernizr来替换<img>的src属性:jQueryif (!Modernizr.svg) { $(".logo img").attr("src", "images/logo.png");}David Bushell提供了一个更简单的操作:HTML<img src="image.svg" onerror="this.onerror=null; this.src='image.png'">使用SVGeezy在background-image里面使用SVG可以在CSS的background-image里面使用SVG。 HTML<a href="/" class="logo"> Kiwi Corp</a>CSS.logo { display: block; text-indent: -9999px; width: 100px; height: 82px; background: url(kiwi.svg); background-size: 100px 82px;}注意把background-size设置成我们想要的尺寸,否则只能看到很大的原始SVG图片的左上角。这个尺寸设置成了跟原始尺寸保持宽高比,如果在不知道原始尺寸的情况下想要保持宽高比,可以把background-size设置成contain。 浏览器支持在background-image里面使用SVG也需要看浏览器支持,基本上跟在<img>中使用是一样的。 如果要在不支持的浏览器里面使用: 用Modernizr把background-image替换成一个支持的格式。它会在不支持SVG的情况下加上一个no-svg的class,注意它也是只会发送一个图片的HTTP请求,不会发两个。CSS.main-header { background: url(logo.svg) no-repeat top left; background-size: contain;}.no-svg .main-header { background-image: url(logo.png);}另一个更方便的方法,就是利用多个背景(background),SVG的浏览器支持和多背景的很接近。CSSbody { background: url(fallback.png); background-image: url(image.svg), none;}使用<img>和background-image的问题在<img>和background-image里面使用SVG,没法利用CSS对SVG内部进行控制,所以接着看下面的两种其他方式。 ...

June 17, 2019 · 2 min · jiezi

关于谷歌Google-Maps-JavaScript-API-的学习与分享

最近参与页面插入谷歌地图API的项目,因此在此分享下我的学习经验,第一次写,请多担待! 首先,讲下公司的需求,在网页进行点击产品列表,渲染对应的地图信息以及对应的详情信息,并且修改谷歌固有标签以及点击标签出现model,展示详细信息以及对应的产品。 加载谷歌API并插入页面 <!DOCTYPE html><html> <head> <style> /* Set the size of the div element that contains the map */ #map { height: 400px; /* The height is 400 pixels */ width: 100%; /* The width is the width of the web page */ } </style> </head> <body> <h3>My Google Maps Demo</h3> <!--The div element for the map --> <div id="map"></div> <script>// Initialize and add the mapfunction initMap() { // The location of Uluru var uluru = {lat: -25.344, lng: 131.036}; // The map, centered at Uluru var map = new google.maps.Map( document.getElementById('map'), {zoom: 4, center: uluru}); // The marker, positioned at Uluru var marker = new google.maps.Marker({position: uluru, map: map});} </script> <script async defer src="https://maps.googleapis.com/maps/api/js?key=&callback=initMap"> </script> </body></html>并且公司需要我们在地图高度变高时,需要对标签进行统计,正好Google maps api中正好有对这一方面进行设计,就是‘Marker Clustering’ 【标记聚类】 ...

June 17, 2019 · 2 min · jiezi

限制-input-输入框只能输入xxx

限制 input 输入框只能输入xxx使用 onkeyup 事件,有 bug ,那就是在中文输入法状态下,输入汉字之后直接回车,会直接输入字母使用 onchange 事件,在输入内容后,只有 input 丧失焦点时才会得到结果,并不能在输入时就做出响应使用 oninput 事件,完美的解决了以上两种问题,测试暂时还没有出现其它问题。原理就是在输入时会触发事件,事件会通过字符替换和正则表达式将不符合规范的替换掉(删除掉) 输入大小写字母、数字、下划线:<input type="text" oninput="value=this.value.replace(/[^\w_]/g,'');"> 输入小写字母、数字、下划线:<input type="text" oninput="value=this.value.replace(/[^a-z0-9_]/g,'');"> 输入数字和点<input type="text" oninput="value=value.replace(/[^\d.]/g,'')">输入中文:<input type="text" oninput="value=this.value.replace(/[^\u4e00-\u9fa5]/g,'')"> 输入数字:<input type="text" oninput="value=this.value.replace(/\D/g,'')"> 输入英文:<input type="text" oninput="value=this.value.replace(/[^a-zA-Z]/g,'')"> 输入中文、数字、英文:<input oninput="value=value.replace(/[^\w\u4E00-\u9FA5]/g, '')"> 输入数字和字母:<input oninput="value=value.replace(/[\W]/g,'')"> 只能输入英文字母和数字,不能输入中文<input oninput="value=value.replace(/[^\w\.\/]/ig,'')">只能输入数字和英文<input oninput="value=value.replace(/[^\d|chun]/g,'')">

June 16, 2019 · 1 min · jiezi

关于Vue2一些值得推荐的文章-五六月份

五、六月份推荐集合查看github最新的Vue weekly;请::点击::集web前端最近很火的vue2框架资源;定时更新,欢迎 Star 一下。 苏幕遮·燎沈香 [宋] 周邦彦 燎沈香,消溽暑。鸟雀呼晴,侵晓窥檐语。 叶上初阳乾宿雨,水面清圆,一一风荷举。 故乡遥,何日去。家住吴门,久作长安旅。 五月渔郎相忆否。小楫轻舟,梦入芙蓉浦。 Vue 3Vue CLI 3 项目构建基础你了解vue3.0响应式数据怎么实现吗?模拟 vue3.0 rfcs createComponent api 中的props类型推导Vue-cli 3.5.1 + Webstorm 使用手机访问演示页面用vue3公开的思路从0实现最简化的vue在 WebStorm 中,配置能够识别 Vue CLI 3 创建的项目的别名 alias @配置一个vue3.0项目快速上手最新的 Vue CLI 3五月不打烊面试官:自己搭建过vue开发环境吗?Vue项目引入CreateJS的方法(亲测)【Vue项目总结】组件通信处理方案vue-cli3+ts+webpack实现多入口多出口前端小白写的Vue+Koa2+Mysql移动商城Vue核心50讲 | 第三回:速看Vue世界的生命轮回聊聊 vue-router【第二篇】创建 @vue/cli3 插件,并整合 ssr 功能Vue Router history模式的配置方法及其原理详解vue组件三大核心概念【前端性能优化】vue性能优化关于Vue.use()详解从零开始构建自己的vue组件库之——button篇用 Vue 写个移动 SPA 应用用vscode开发vue应用3分钟了解vue数据劫持的原理Vue源码: 关于vm.$delete()/Vue.use() 内部原理Vue CLI 3 项目构建基础vue2之简易的pc端短信验证码的问题Vue之项目整合与优化Vue多页路由与模板解析且用且珍惜Vue CLI3之pages 构建多页应用Vue API 盲点解析Vue之合理划分容器组件与展示组件Vue之学会编写可复用性模块Vue编码技巧与规范Vue组件之全局注册Vue源码: 构造函数入口【愣锤笔记】基于vue的进阶散点干货百行代码带你入门 vue-routerwebpack入门——构建简易版vue-cli手摸手教你封装跨项目复用的 Vue 组件库Vue 递归多级菜单Vue响应式原理-理解Observer、Dep、Watcher前端框架技术选型 React vs. Vue (vs. Angular)公司要求会使用框架vue,面试题会被问及哪些?Vue核心50讲 | 第四回:Vue 官方赠送的橙色装备,岂能不要基于vue-cli3多页面开发apicloud应用vue实现录音功能(pc端)在 Vue 应用中使用 Netlify 表单功能Vue+Express实现登录,注销尝试用 vue 实现灭霸打响指英雄消失的效果 demo初步学习VuexVue-Cli 3.0从0 开始搭建项目(篇1)5分钟了解vue-router的基本使用SpringBoot,Vue前后端分离开发首秀express 使用 vue-router 的 history 踩坑尤大大 6 月 4 日的 Vue 技术分享vue-router工作原理概述和问题分析vue面试必备知识点页面刷新后,vuex中数据丢失、清空的解决方案 vuex-persistedstateVue 框架原理相关知识点【前端词典】 Vue 响应式原理其实很好懂Vue核心50讲 | 第一回:Vue 与 MVVM 之间那些事儿尤雨溪大大在 6 月 4 日的 Vue3.0 的技术分享新手使用vue-router传参时注意事项如何写一个 vue 插件vue组件props传值,对象获取不到的问题用 Vue 开发自己的 Chrome 扩展每日前端夜话0x7F六月不出门巧用 ES6,轻松优化 Vue 代码vue2 配置scssVue SSR技术方案落地实现—构建同构应用vue,angular,react框架对比Vue数据绑定简析没有废话的vue进阶( 一 )【vue源码】深度理解v-forVue.js进阶-从源码角度剖析计算属性的原理用 Vue 编写抽象组件Vue-Cli 项目基础搭建vue中使用protobuf踩坑记你了解vue3.0响应式数据怎么实现吗?nextTick 在 vue 2.5 和 vue 2.6 之间有什么不同没有废话的vue高级进阶( 二 ) 8种组件通信详解前端Vue:函数式组件Vue奇淫技巧vue权限问题解决方案快速上手BootstrapVueVue-router基础篇vue-cli@3.0 使用及配置说明Vue 实现前进刷新,后退不刷新的效果Vue.js进阶-从源码角度剖析vue-router(三)为vue项目自动设置请求状态Vuex基础《现场实录》 VueConf 2019 尤雨溪演讲总结「试着读读 Vue 源代码」初始化前后做了哪些事情 ❓一张图弄明白 Vuex 里该存放什么样的数据VueCli+Node+mongodb打造个人博客(含前台展示及后台管理系统)(上)webpack手动搭建Vue项目「试着读读 Vue 源代码」new Vue()发生了什么 ❓译| 自定义一个Vue路由器没有废话的vue高级进阶( 三 ) 组件高级用法及最佳实践如何在Vue里实现一个Redux状态管理?vue-json-view 一款用于展示json的vue组件,支持大体积json文件快速解析渲染从源码分析vue-cli@3.0环境变量配置原创文章:使用Vuejs实现个人所得税功能兼容移动端Vue项目中配置pug解析支持手摸手,带你用vue撸后台 系列五(v4.0新版本)《PPT》 尤雨溪:State of Vuevue通信方法EventBus的实现谈一谈Vuexvue.js应用开发笔记Vue项目打包后动态获取自定义变量webpack4-05-配置vue相关为管理复杂组件状态困扰?试试 vue 简单状态管理 Store 模式前端答疑-对象引用-vue共享数据源的三种方式ES6 Proxy实现Vue的变化检测Laravel 5.8 集合 vue-element-admin 踩坑记Vue Function-based API RFC在Vue中用canvas实现二维码和图片合成海报在vue2中使用echarts (Vue-ECharts插件)个人对vue中生命周期的理解electron-vue利用webpack打包实现多页面的入口文件vuecli3 vant rem 移动端框架方案sortable.js——Vue 数据更新问题用 Vue 开发自己的 Chrome 扩展程序vue的事件冒泡Flutter部件内部状态管理小结(实现Vue的v-model)vue.js中如何导出Excel表格尤雨溪:Vue Function-based API RFC谈谈Vue/React中的虚拟DOM(vDOM)与Key值开发Vue插件四种方式Vue后台管理系统用户认证封装无限滚动插件vue-infinite-scroll源码解析新丝缠角粽,金盘送!从今天开始,拿起VuePress打造属于自己的专属博客一张思维导图辅助你深入了解 Vue | Vue-Router | Vuex 源码架构vue导出excel表格vue项目前端知识点整理vue实现歌手列表字母排序,下拉滚动条侧栏排序实时更新vue中的scoped坑点基于Vue的简易MVVM实现详解Vue生命周期【上】深入理解vue组件Vue项目使用pdf.jsVue原理之虚拟DOM和render函数第三届VueConf来啦,尤雨溪将出席如何写好一个vue组件,老夫的一年经验全在这了vue组件间通信六种方式(完整版)小实例: 用vue实现手风琴效果如何写出一个利于扩展的vue路由配置自己搭建Vue + Vuex + Typescript 项目的使用Vue开发总结 及 一些最佳实践 (已更新)webpack4手动搭建Vue开发环境实现todoList项目我在vue开发中的小技巧你真的知道如何使用Vue.set吗atom-design(Vue.js移动端组件库)手势组件使用教程9102年:从0开始手写一个Vue.js优化版脚手架VsCode从零开始配置一个属于自己的Vue开发环境vue+electron高仿网易云谈一谈我是怎么学习使用vuex的vue+高德地图开发采坑持续记录vue-cli3.0的简单配置Vue入门及上手教程Vue2.0解决watch对象属性变化监听不到问题vue路由里前进后退的那些事儿webpack4 + vue多页面项目精细构建思路Vue使用props父子组件传递数据Vue+Express全栈购物商城从源码看 Vue 中的 Mixin详解JS错误处理:前端JS/Vue/React/Iframe/跨域/Nodevue-生命周期songEagle开发系列:Vue.js + Koa.js项目中使用JWT认证Vue模板、JS、CSS分离实现vue 路由 按需 keep-alive【前端词典】Vuex 注入 Vue 生命周期的过程nuxt.js基于ssh的vue通用框架vue源码阅读之数据渲染过程单页面(如react,vue)网站的服务器渲染 SSR 之 SEO 大杀器 Rendertron7 个有用的 Vue 开发技巧Vue 组件间通信方式使用vue自定义指令开发一个表单验证插件validate.jsVue生命周期总结vxe-table vue table 一个非常强大表格组件vue中$refs, $emit, $on, $once, $off的使用vue项目打包后怎样优雅的解决跨域Vue + Echarts + 百度地图 实践Vue引入echarts使用教程Vue.js进阶-从源码角度剖析vue-router(二)vue cli3.0 引入eslint 结合vscode使用vue项目前端错误收集之sentryvue全家桶+Echarts+百度地图,搭建数据可视化系统(【续】接口篇)从vue2.6.10源码看vue是怎么跑起来的webpack4手动搭建Vue开发环境实现todoList项目(2)Vuex使用(实战记录)由Vue中三个常见问题引发的深度思考GraphQL + Apollo + Vue 牛刀小试vue-cli3开发Chrome插件实践vue读取本地的excel文件并显示在网页上vue-cli3中vue.config.js配置Vuex概念浓缩版记录【第一篇】基于 @vue/cli3 与 koa 创建 ssr 工程更多推荐查看github最新的Vue weekly;请::点击::集web前端最近很火的vue2框架资源;定时更新,欢迎 Star 一下。 ...

June 15, 2019 · 2 min · jiezi

建造者

建造者模式建造者模式(Builder Pattern)使用多个简单的对象一步一步构建成一个复杂的对象。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。一个 Builder 类会一步一步构造最终的对象。该 Builder 类是独立于其他对象的。建造者实用范围当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式时。当构造过程必须允许被构造的对象有不同表示时。建造者主要解决主要解决在软件系统中,有时候面临着"一个复杂对象"的创建工作,其通常由各个部分的子对象用一定的算法构成;由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合在一起的算法却相对稳定定义将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。 使用场景通过上面的定义我们大概已经知道创建模式它是要做什么了 相同的方法,不同的执行顺序,产生不同的事件结果时多个部件或零件,都可以装配到一个对象中,但是产生的运行结果又不相同时产品类非常复杂,或者产品类中的调用顺序不同产生了不同的效能,这个时候使用建造者模式非常合适当初始化一个对象特别复杂,如参数多,且很多参数都具有默认值时建造者实现客户客户提出的需求,比如我想要什么,我需要什么样的,这个我得告诉有这个东西的人对吧或是可以建造的人,那现在客户说了我需要建造一个房子,下面是我们的客户需求码 class Product { constructor () { this.bedroom = '' this.living = '' this.kitchen ='' } }上面的代码我创建了一个Product类,里面产生了一个卧室的空间变量bedroom,一个客厅living的空间,一个厨房kitchen的空间 抽象建造者类我们需要找到它们共同的本质,从而写一个属于卧室,客厅,厨房的抽象类函数,那么抽象是什么:从具体事物抽出、概括出它们共同的方面、本质属性与关系等,而将个别的、非本质的方面、属性与关系舍弃,这种思维过程,称为抽象。总的来说我绝绝的它们是虚无缥缈的东西,需要你自己的思维去想去思考,当然每个人的思考方式,思考的点不同抽象出的本质就不一样 class house { build () { console.log('建造') } }上面的代码是我们编写一个简单的房子类,我们在这里抽离的本质是它的建造,俗话说就是盖的那种,你懂得~ 简单举例: 本质:运动 事物具体的实现:跑步,游泳 本质:射击 事物具体的实现:手枪射击,步枪射击 本质:行驶 事物具体的实现:宝马行驶,奔驰行驶 具体的建造类就是我们要具体怎么建造卧室bedroom,客厅living,厨房kitchen我们要具体的去实现客户想要的东西 // 卧室的建造类型 class Bedroom extends house { build () { console.log('建造卧室') } } // 客厅的建造类 class Living extends house { build () { console.log('建造客厅') } } // 厨房的建造类 class Kitchen extends house { build () { console.log('建造厨房') } }上面的代码就是我们实现三个不同风格的房子代码实现 ...

June 15, 2019 · 2 min · jiezi

公司官网前端开发经验分享

公司官网的重要性和特殊性不言而喻。很多前端都会经历这个项目,笔者有幸在所就职的每家公司都负责过官网的前端开发工作。开发中遇到过很多问题,反思起来值得和大家一起分享,以减少或者减低大家可能遇到的问题。理想开发流程UI => 开发 =》 测试 =》 上线 现实开发流程需求方 =》 UI => 开发 =》需求方 =》 UI => 测试 =》需求方 =》 ...... UI => 上线 =》需求方 =》 UI => 开发 测试 =》上线 实际开发中需求及UI会一直调整,直到上线以后仍会不停调整。所以,前期的需求评审至关重要。一定要让需求方(一般是市场部负责人)评审通过以后再开发。吐槽:官网是我见到为数不多的产品总监PK不过市场总监的项目之一。一般项目,前端展示效果产品总监拍板即可。 0. 特性跨部门沟通跨项目耦合PWA测试的重要性工期的紧迫性项目重要性SEO的重要性1. 跨部门沟通由于官网的特殊性,官网通常会涉及多部门协作。 市场部:需求方,一般官网都必须满足市场部推广需求销售部:半需求方,一般官网都必须满足市场部推广需求人力部:半需求方,辅助招聘需求客服部:半需求方,辅助客服需求产品部:设计,对UI及UE负责开发部:开发,对技术及开发进度负责测试部:测试,对质量、效果负责,保证测试充分运维部:运维,对网络及服务器负责运营部:文案,对文案及SEO推广负责国际化:翻译,保证文案翻译的准确性及效率(一般小公司会外包,所以必须保证时效)2. 跨项目耦合用户系统:实现单点登录(SSO)功能公司产品:涉及到公司产品的子项目官方博客:如blog、wiki、zendesk等客服功能:WeChat、App、小程序、微博等功能的集成3. PWA1. 可靠性 跨终端可用性离线可以访问基本功能保证服务长期可访问2. 快速性 可交互等待时长加载速度3. 友好性 合理的布局友好的UI设计便捷的交互适合不同国家的用户使用习惯,如阿拉伯语国家 direction无障碍阅读4. 测试的重要性自测产品测试部门公司内测5. 工期的紧迫性由于官网是企业对外宣传的重要工具,所以一般会要求时效性,如新闻、咨询、招聘信息等及时更新。 以及活动页的开发,如周年庆、春节、促销、展会、推广等活动。 6. 项目重要性由于官网是企业的门面,一般公司(中小型企业)的老板都会对官网亲自把关,通过官网来展现公司的企业文化。所以,倘若你在中小型企业,接手官网的话,拿出看家本领把官网做好也是非常值得的。 7. SEO的重要性由于官网的特殊性,往往公司会付费做SEO推广,所以,官网的SEO友好性不言而喻。这就要求我们在项目技术选型期要慎重考虑,想办法将SEO做的更好,这样就可以大幅节省推广成本,达到事半功倍的效果。 现在适合SEO的方法比较多,如SSR、Prerender等其他方式。 检查清单参与需求评审,待定稿后开始开发工期预估,按正常工时的1.5-2倍时间进行预估,后期更改会比较频繁硬件条件提前准备,如服务器、SSL、HTTPS等需要提前准备,待项目上线前搞定。对老官网的兼容性,新官网发布前务必邮件告知公司全部高管,让大家自行修改,处理新老官网更换代理的问题。如,页面路径发生变化。统计工具兼容(友盟、GA等)埋点及上报代码不应遗漏公测(公司内部测试,尽量保证1周左右的时间,让大家体验并上报问题)

June 15, 2019 · 1 min · jiezi

H5-inputtypedate-优化-pc端和移动端的使用

<input>标签在HTML5中新增了color, date, datetime, datetime-local, month, week, time, email, number, range, search, tel 以及 url新属性。本篇记录在开发中使用date属性,遇到的一些问题,以及功能扩展: 获取当前日期,并显示在input[type='date']上html:<input type='date' id='dataInput'/>js:<script>$(function(){ var date_now = new Date(); var year = date_now.getFullYear(); var month = date_now.getMonth()+1 < 10 ? "0"+(date_now.getMonth()+1) : (date_now.getMonth()+1); var date = date_now.getDate() < 10 ? "0"+date_now.getDate() : date_now.getDate(); var nowDate=year+"-"+month+"-"+date; $("#dataInput").val(nowDate);})</script> 限制日期框选择范围利用标签属性实现<input type="date" min="2019-06-01" max="2019-06-20">max:可选最大日期min:可选最小日期 js设置最大只能选择到当前日期html<input type="date" id="maxDate"/>js<script>$(function(){ var date_now = new Date(); var year = date_now.getFullYear(); var month = date_now.getMonth()+1 < 10 ? "0"+(date_now.getMonth()+1) : (date_now.getMonth()+1); var date = date_now.getDate() < 10 ? "0"+date_now.getDate() : date_now.getDate(); var nowDate=year+"-"+month+"-"+date; $("#maxDate").attr("max",nowDate);//最大只能选择到当前日期})</script> 移动端显示问题当移动端使用nput[type='date']时 ios系统日历格式是这样 ===> 2019年06月06日样式上安卓和ios不统一 ...

June 15, 2019 · 1 min · jiezi

使用Nodejs爬取任意网页资源并输出高质量PDF文件到本地

本文适合无论是否有爬虫以及Node.js基础的朋友观看~需求:使用Node.js爬取网页资源,开箱即用的配置将爬取到的网页内容以PDF格式输出如果你是一名技术人员,那么可以看我接下来的文章,否则,请直接移步到我的github仓库,直接看文档使用即可仓库地址:附带文档和源码,别忘了给个star哦本需求使用到的技术:Node.js和puppeteerpuppeteer 官网地址: puppeteer地址Node.js官网地址:链接描述Puppeteer是谷歌官方出品的一个通过DevTools协议控制headless Chrome的Node库。可以通过Puppeteer的提供的api直接控制Chrome模拟大部分用户操作来进行UI Test或者作为爬虫访问页面来收集数据。环境和安装Puppeteer本身依赖6.4以上的Node,但是为了异步超级好用的async/await,推荐使用7.6版本以上的Node。另外headless Chrome本身对服务器依赖的库的版本要求比较高,centos服务器依赖偏稳定,v6很难使用headless Chrome,提升依赖版本可能出现各种服务器问题(包括且不限于无法使用ssh),最好使用高版本服务器。(建议使用最新版本的Node.js)小试牛刀,爬取京东资源const puppeteer = require('puppeteer'); // 引入依赖 (async () => { //使用async函数完美异步 const browser = await puppeteer.launch(); //打开新的浏览器 const page = await browser.newPage(); // 打开新的网页 await page.goto('https://www.jd.com/'); //前往里面 'url' 的网页 const result = await page.evaluate(() => { //这个result数组包含所有的图片src地址 let arr = []; //这个箭头函数内部写处理的逻辑 const imgs = document.querySelectorAll('img'); imgs.forEach(function (item) { arr.push(item.src) }) return arr }); // '此时的result就是得到的爬虫数据,可以通过'fs'模块保存'})() 复制过去 使用命令行命令 ` node 文件名 ` 就可以运行获取爬虫数据了 这个 puppeteer 的包 ,其实是替我们开启了另一个浏览器,重新去开启网页,获取它们的数据。上面只爬取了京东首页的图片内容,假设我的需求进一步扩大,需要爬取京东首页中的所有<a> 标签对应的跳转网页中的所有 title的文字内容,最后放到一个数组中。 ...

June 15, 2019 · 2 min · jiezi

Electron酷家乐客户端开发实践分享-下载管理器

作者:钟离,酷家乐PC客户端负责人原文地址:https://webfe.kujiale.com/electron-ku-jia-le-ke-hu-duan-kai-fa-shi-jian-fen-xiang-jin-cheng-tong-xin/酷家乐客户端:下载地址 https://www.kujiale.com/activity/136文章背景:在酷家乐客户端在V12改版成功后,我们积累了许多的宝贵的经验和最佳实践。前端社区里关于Electron知识相对较少,因此希望将这些内容以系列文章的形式分享出来。系列文章: 【Electron】酷家乐客户端开发实践分享 — 入坑篇【Electron】酷家乐客户端开发实践分享 — 软件自动更新【Electron】酷家乐客户端开发实践分享 — 浏览器启动客户端【Electron】酷家乐客户端开发实践分享 — 进程通信【Electron】酷家乐客户端开发实践分享 — 下载管理器不定期更新...背景打开酷家乐客户端,可以在左下角的更多菜单中找到下载管理这个功能,今天我们就来看看在Electron中如何实现一个下载管理器。 如何触发下载行为由于Electron渲染层是基于chromium的,触发下载的逻辑和chromium是一致的,页面中的a标签或者js跳转等等行为都可能触发下载,具体视访问的资源而定。什么样的资源会触发浏览器的下载行为呢? response header中的Content-Disposition为attachment。参考MDN Content-Dispositionresponse header中的Content-Type,是浏览器无法直接打开的文件类型,例如application/octet-stream,此时取决于浏览器的具体实现了。例子: IE无法打开pdf文件,chrome可以直接打开pdf文件,因此pdf类型的url在chrome上可以直接打开,而在IE下会触发下载行为。在Electron中还有一种方法可以触发下载: webContents.download。相当于直接调用chromium底层的下载逻辑,忽略headers中的那些判断,直接下载。 上述两种下载行为,都会触发session的will-download事件,在这里可以获取到关键的downloadItem对象 整体流程 设置文件路径如果不做任何处理的话,触发下载行为时Electron会弹出一个系统dialog,让用户来选择文件存放的目录。这个体验并不好,因此我们首先需要把这个系统dialog去掉。使用downloadItem.savePath即可。 // Set the save path, making Electron not to prompt a save dialog.downloadItem.setSavePath('/tmp/save.pdf');为文件设置默认下载路径,就需要考虑文件名重复的情况,一般来说会使用文件名自增的逻辑,例如:test.jpg、test.jpg(1)这种格式。文件默认存放目录,也是一个问题,我们统一使用app.getPath('downloads')作为文件下载目录。为了用户体验,后续提供修改文件下载目录功能即可。 // in main.js 主进程中const { session } = require('electron');session.defaultSession.on('will-download', async (event, item) => { const fileName = item.getFilename(); const url = item.getURL(); const startTime = item.getStartTime(); const initialState = item.getState(); const downloadPath = app.getPath('downloads'); let fileNum = 0; let savePath = path.join(downloadPath, fileName); // savePath基础信息 const ext = path.extname(savePath); const name = path.basename(savePath, ext); const dir = path.dirname(savePath); // 文件名自增逻辑 while (fs.pathExistsSync(savePath)) { fileNum += 1; savePath = path.format({ dir, ext, name: `${name}(${fileNum})`, }); } // 设置下载目录,阻止系统dialog的出现 item.setSavePath(savePath); // 通知渲染进程,有一个新的下载任务 win.webContents.send('new-download-item', { savePath, url, startTime, state: initialState, paused: item.isPaused(), totalBytes: item.getTotalBytes(), receivedBytes: item.getReceivedBytes(), }); // 下载任务更新 item.on('updated', (e, state) => { // eslint-disable-line win.webContents.send('download-item-updated', { startTime, state, totalBytes: item.getTotalBytes(), receivedBytes: item.getReceivedBytes(), paused: item.isPaused(), }); }); // 下载任务完成 item.on('done', (e, state) => { // eslint-disable-line win.webContents.send('download-item-done', { startTime, state, }); }); });现在触发下载行为,文件就已经会下载到Downloads目录了,文件名带有自增逻辑。同时,对下载窗口发送了关键事件,下载窗口可以根据这些事件和数据,创建、更新下载任务。 ...

June 14, 2019 · 2 min · jiezi

lua-web快速开发指南4-详细了解httpd库的作用

httpd库是基于HTTP 1.1协议实现而来, 内置了高性能的http协议解析器与urldecode解析库. httpd库默认情况下就能工作的很好, 但是在一些需求较为极端的场景还是需要微调一下参数. httpd常用的内置方法介绍1. httpd:timeout(number)设置每个连接到最大空闲(idle)连接等待时间, 超过这个数值httpd将主动断开连接. (默认值为:30秒) 2. httpd:max_path_size(number)设置Path的最大长度, 超过这个值httpd将会返回414. (默认值为: 1024) 3. httpd:max_header_size(number)设置Header最大长度, 超过这个值httpd将会返回431. (默认值为: 65535) 4. httpd:max_body_size(number)设置Body的最大长度, 超过这个值将会返回413. (默认为 1024 * 1024) 5. httpd:before(function)before方法决定API与USE路由回调在触发之前的行为, 默认情况下允许所有路由通过. before方法一般用来设置与修改用户验证路由行为(例如头部验证), 这提供了开发者基于before函数设计中间件的机会. 当开发者设置了function后(即是是一个空函数), 需要利用http库来决定行为. 6. httpd:group(type, prefix, handles)group方法提供了一种批量注册路由的方式, 为一组同一组路由提供简单便方便在注册方法. 第一个参数type为需要批量注册的路由类型; 初始化httpd对象后, 使用app.USE或app.API进行传值; 第二个参数prefix为string类型的头部; 例如:/api、/admin; 第三个参数为一组路由处理函数或处理类数组; 类型为: {route = '/login', class = class}; 注意: 此方法仅支持批量注册API与USE路由, 不可同时注册不同类型路由; 7. httpd:static(folder, ttl)listen方法用于告诉httpd对象监听指定端口. 第一个参数ip暂未被httpd使用(但是必须设置), 默认监听所有网卡的'0.0.0.0'地址与指定的端口号; backlog为用户最大连接等待队列, 合理的设置能减少连接被重置的情况(默认值为128). 8. httpd:run()在httpd库所有参数与路由设置完毕之后, 调用run方法开启监听模式. httpd的请求日志日志格式为: [年/月/日 时:分:秒] - [ip] - [x-real-ip] - [path] - [method] - [http code] - [request handle timeline] ...

June 14, 2019 · 1 min · jiezi

lua-web快速开发指南3-初识httpd库路由

本章假设您已经知道httpd server如何快速搭建, 并且知道cf的启动流程与运行流程, 知晓httpd如何创建与启动. 回顾上一章节-- script/main.lualocal httpd = require "httpd"local app = httpd:new("app")app:static("static", 30)app:listen("0.0.0.0", 8080)app:run()我们利用httpd内置库快速实现了一套httpd静态文件server, 其中包括静态文件目录指定与端口设置. 并且在启动server后可以在看到测试页面. 什么是"路由"与"路由表"?Web路由用于描述资源到处理函数之间的一个映射关系. Web路由表用于描述当前作用域下所有路由的一个集合. 如下所示: /userlogin -> function userlogin(content) ... end/userinfo -> function userinfo(content) ... end对于一个服务端开发者来说! 当接受到客户端的HTTP请求时, 服务端会将请求URL中的PATH进行分割, 然后开始寻找的PATH映射对应的回调处理函数. 当URL映射的回调处理函数被找到时, 将会为其注入整个http上下文并且根据处理函数的行为将返回值展现给资源访问者. 这就是基本的路由雏形. cf中的各种路由cf的httpd库利用这种机制, 为开发者提供了一整套完整的路由注册方法, 其中包括: 静态文件路由、API接口路由、USE页面路由、WebSocket路由. 静态文件路由我们在上一章节已经看到过, 其本质是根据需要读取指定文件而存在的. 这种路由一般有库编写者或者框架编写者实现. 而API接口路由、USE页面路由、Websocket路由则一般由开发自行指定, 这些路由一般都用来处理对应的业务逻辑. 下面我们就开始学习如何在cf中注册路由. 注册API与USE路由1. API路由API接口路由用于快速构建前、后端分离的web开发场景. 它提供了基于http协议提供了基础的前、后端通讯的解决方案, 是目前位置Web领域最为常见的开发模式. 而作为前、后端数据沟通的桥梁自然需要指定指定数据交互类型. 目前为止, API路由的content-type为"application/json", 数据交互格式仅支持: json. httpd库为开发者提供了app:api方法用来注册API路由, 第一个参数是一个字符串类型的资源路径, 第二个参数则是回调处理方法; 现在让我们在main.lua中, 添加我们刚刚学习到的api路由: -- main.lualocal json = require "json"app:api('/userinfo', function(content) return json.encode({ code = 200, user = { name = "CandyMi", age = 29, sex = "男", } })end)然后打开浏览器, 输入http://localhost:8080/userinfo. 我们就可以看到我们输出的接口数据了. ...

June 14, 2019 · 1 min · jiezi

华为鸿蒙基于旗鱼OS开发-我还认识一个旗鱼云梯

据了解近期关于华为鸿蒙操作系统的消息越来越多,而且细节也越来越丰富。不过外媒的一则消息却表示华为鸿蒙操作系统并不是从零开始的。俄罗斯一家媒体表示,华为鸿蒙操作系统是基于旗鱼 OS进行开发的,之所以能够兼容安卓,也正是这个原因。 旗鱼 OS是诺基亚放弃MeeGo的继承者,基于MeeGo开发出旗鱼 OS。在华为正式公布鸿蒙操作系统的细节之前,还无法确定鸿蒙操作系统是完全自研还是基于已有成果之上。不过从前段时间的信息来看,鸿蒙完全自研的可能性是比较大的。另一个我知道的旗鱼云梯是建站平台,可以再linux系统上一键建站,帮助企业和站长实现一键建站能力.旗鱼云梯是批量化linux服务器集群管理平台,可以快速搭建web环境,让用户最快的建立网站.都是旗鱼os系统,旗鱼云梯你咋这么优秀呢.作为linux面板建站来说.

June 14, 2019 · 1 min · jiezi

js内功修炼之九阳神功原型链

写在前面如果说JavaScript是一本武学典籍,那么原型链就是九阳神功。在金庸的武侠小说里面,对九阳神功是这样描述的:"练成「九阳神功」后,会易筋洗髓;生出氤氲紫气;内力自生速度奇快,无穷无尽,普通拳脚也能使出绝大攻击力;防御力无可匹敌,自动护体,反弹外力攻击,成就金刚不坏之躯;习者速度将受到极大加成;更是疗伤圣典,百病不生,诸毒不侵。至阳热气全力施展可将人焚为焦炭,专门克破所有寒性和阴毒内力。"可见其功法强大。那么,如何修炼好js中的九阳神功呢?真正的功法大成的技术是从底层上去理解,那种工程师和码农的区别就在于对底层的理解,当你写完一行代码,或者你遇见一个bug,解决的速度取决于你对底层的理解。什么是底层?我目前个人的理解是“在你写每一行代码的时候,它将如何在相应的虚拟机或者V8引擎中是如何运行的,更厉害的程序员甚至知道每条数据的操作是在堆里面还是在栈里面,都做到了然于胸,这是JavaScript的内功最高境界(反正我现在是做不到,我不知道你们能不能,哈哈哈)”。 一、Js原型链的简单理解**理解原型链之前首先要了解js的基本类型和引用类型:1、基本类型 基本类型有Undefined、Null、Boolean、Number 和String。这些类型在内存中分别占有固定大小的空间,他们的值保存在栈空间, 我们通过按值来访问的。 基本类型:简单的数据段,存放在栈内存中,占据固定大小的空间。2、引用类型引用类型,值大小不固定,栈内存中存放地址指向堆内存中的对象。是按引用访问的。存放在堆内存中的对象,变量实际保存的是一个指针,这个指针指向另一个位置。每个空间大小不一样,要根据情况开进行特定的分配。当我们需要访问引用类型(如对象,数组,函数等)的值时,首先从栈中获得该对象的地址指针,然后再从堆内存中取得所需的数据。** js的原型链说简单也简单,说难也难。 首先说明:函数(Function)才有prototype属性,对象(除了Object)拥有_proto_.原型链的顶层就是Object.prototype,而这个对象的是没有原型对象的。可以在Chrome输入: Object.__proto__输出的是: ƒ () { [native code] }可以看到这个没有.prototype属性。 二、prototype和_proto_的区别我们知道原型是一个对象,其他对象可以通过它实现属性继承。 var a = {};console.log(a.prototype); //undefinedconsole.log(a.__proto__); //Object {}var b = function(){}console.log(b.prototype); //b {}console.log(b.__proto__); //function() {} /*1、字面量方式*/var a = {};console.log(a.__proto__); //Object {}console.log(a.__proto__ === a.constructor.prototype); //true/*2、构造器方式*/var A = function(){};var a = new A();console.log(a.__proto__); //A {}console.log(a.__proto__ === a.constructor.prototype); //true/*3、Object.create()方式*/var a1 = {a:1}var a2 = Object.create(a1);console.log(a2.__proto__); //Object {a: 1}console.log(a.__proto__ === a.constructor.prototype); //false(此处即为图1中的例外情况) ...

June 14, 2019 · 2 min · jiezi

一个让我很艹蛋的手机报表

需求如图: 用echarts实现,代码如下,无注释。 var myChart = echarts.init(document.getElementById('main')); var x = new Array(); var optionx = new Array(); var y = new Array(); for(var i = 0; i < chartData.length; i++){ for (item in chartData[i]){ x.push(item); y.push(chartData[i][item]); } } for(var i = 0; i < x.length; i++){ var index1 = x[i].indexOf('-') + 1; optionx.push(x[i].substring(index1,x[i].length)); } // 指定图表的配置项和数据 var option = { backgroundColor: "#FCFCFC", tooltip : { backgroundColor: "#17191D", trigger: 'axis', axisPointer: { type: "none", label: { backgroundColor: '#6a7985' } }, formatter: function(params, ticket, callback) { return '<div style="padding: 5px;overflow: hidden;"><div style="display: block;font-size: 12px;line-height: 14px;margin-bottom: 6px;">'+x[params[0].dataIndex]+'</div><div style="display: block;width: 1px;height: 9px;border-radius: 3px;background-color: #1890FF;margin-top: 2.5px;float: left;"></div><div style="display: block;float: left;margin-left: 7px;font-size: 12px;line-height: 14px;">'+params[0].data+'</div></div>'; } }, grid: { top: 0, bottom: 36, left: -20, right: -20 }, xAxis :{ type : 'category', boundaryGap : false, axisLine : { show: false, lineStyle :{ color : "#C6D2DD" } }, axisLabel: { color : "#666" }, splitLine : { show: true, lineStyle :{ color : "#D7D8DA", type : "dashed" } }, axisTick : { show: false, lineStyle :{ color : "#EBEBEB" } }, data : optionx }, yAxis : { type : 'value', axisLine :{ show: false }, axisLabel : { show: false }, splitLine : { show: false }, axisTick : { show: false } }, series : [ { type:'line', stack: '总量', smooth : true, //是否平滑显示 symbolSize : 6, itemStyle : { color: "#FFD205", borderColor : "#FFD205", borderWidth : 2 }, lineStyle : { color : "#FFD205", width : 4 }, areaStyle : { color : "#FFF", origin : "end", opacity : 1 }, data:y } ] }; myChart.setOption(option);

June 14, 2019 · 2 min · jiezi

带着canvas去流浪5绘制K线图

示例代码托管在:http://www.github.com/dashnowords/blogs博客园地址:《大史住在大前端》原创博文目录 华为云社区地址:【你要的前端打怪升级指南】 [TOC] 一. 任务说明使用原生canvasAPI绘制K线图。(截图以及数据来自于百度Echarts官方示例库【查看示例链接】)。 二. 重点提示K线图最常见的是在金融市场,尤其是股市中,它的绘制算法和表达的意思是直接相关的: 一般一个数据点包含开盘价,收盘价,当日最高价,当日最低价4个数据点。当开盘价低于收盘价时,当天为涨价,则图形为红色,反之则为绿色。图形中间的细线是当日最高价和当日最低价之间的连线。图形中的矩形是在开盘价和收盘价之间的范围。了解了上述基本知识,K线图的绘制和折线图其实并没有太大区别,按部就班去绘制就好了。如果仔细观察Echarts官方提供的示例会发现图例中还有 MA5,MA10这样的图例标记,这里其实指的是N天的移动平均值Moving Average N,是减小数据波动性展示其宏观规律的常用方法之一,示例中的MA5就是指依次将源数据中每5个点的值求平均值作为当前点的数据(至于5个点是从当前点开始算,还是从当前点结束都是可以的)。 三. 示例代码实现难度较低,本文不再赘述。 /*数据点来自于百度Echarts官方示例库* 每个数据点意义:[日期,开盘(open),收盘(close),最低(lowest),最高(highest)]* 例如: ['2013/2/7', 2430.69,2418.53,2394.22,2433.89],*//** * 绘制数据 */function drawData(options) { let data = options.data; let xLength = options.chartZone[2] - options.chartZone[0]; let c;//记录当前绘制点的颜色 let gap = xLength / options.xAxisLabel.length; let activeX = 0;//记录绘制过程中当前点的坐标 let activeY = 0;//记录绘制过程中当前点的y坐标 context.strokeWidth = 2; context.beginPath(); context.moveTo(options.chartZone[0],options.chartZone[3]);//先将起点移动至0,0坐标 for(let i = 0; i < data.length; i++){ //获取绘图颜色 c = getColor(data[i]); context.strokeWidth = 1; context.strokeStyle = context.fillStyle = c; //计算绘制中心点x坐标 activeX = options.chartZone[0] + (i + 1) * gap; //绘制最高最低线; context.beginPath(); context.moveTo(activeX,transCoord(data[i][3])); context.lineTo(activeX,transCoord(data[i][4])); context.closePath(); context.stroke(); //绘制开盘收盘矩形 if (data[i][0] >= data[i][5]) { context.fillRect(activeX - 5 , transCoord(data[i][0]) , 10, transCoord(data[i][6]) - transCoord(data[i][0])); } else{ context.fillRect(activeX - 5 , transCoord(data[i][7]) , 10, transCoord(data[i][0]) - transCoord(data[i][8])); } } }//根据K线图的数据中开盘价和收盘价计算绘图颜色function getColor(data) { return data[0] >= data[1] ? '#1abc9c' : '#DA5961';}//从可视坐标系坐标转换为canvas坐标系坐标function transCoord(coord) { return options.chartZone[3] - (options.chartZone[3] - options.chartZone[1])*(coord - options.yMin) / (options.yMax - options.yMin);}浏览器中可查看效果: ...

June 13, 2019 · 1 min · jiezi

摆脱客户端网页发起直播势在必行

背景近几年直播行业飞速发展,但是由于Web端这方面功能的长时间缺失,使得直播端以客户端为主;WebRTC 的出现使得网页也可以成为直播端。那么究竟WebRTC是什么呢? WebRTC,即Web Real-Time Communication,web实时通信技术。简单地说就是在web浏览器里面引入实时通信,包括音视频通话等,它使得实时通信变成一种标准功能,任何Web应用都无需借助第三方插件和专有软件,而是通过JavaScript API即可完成;而且WebRTC提供了视频会议的核心技术,包括音视频的采集、编解码、网络传输、展示等功能,还支持跨平台,包括主流的PC和移动端设备。 下面介绍下需要用到的几个API: getUserMedia我们可以通过调用navigator.mediaDevices.getUserMedia(constraints)去初始化一个本地的音视频流,然后把直播流通过video标签播放。代码如下: html: <div id="container"> <video id="gum-local" autoplay playsinline></video> <button id="showVideo">Open camera</button> <button id="switchVideo">switch camera</button></div>js: const constraints = { audio: false, video: true};async function init(e) { try { const stream = await navigator.mediaDevices.getUserMedia(constraints); const video = document.querySelector('video'); video.srcObject = stream; } catch (e) { console.log(e, 'stream init error'); }}document.querySelector('#showVideo').addEventListener('click', (e) => init(e));示例效果: 当然,如果有多个设备,就需要考虑设备选择和设备切换的问题。那就需要用到下面的这个API。 设备我们看看如何用原生的Web API去获取设备(以下示例代码可适用于Chrome,其他浏览器暂未测试;具体浏览器兼容性可参考官方文档,本文档底部有链接)。 navigator.mediaDevices.enumerateDevices()如果枚举成功将会返回一个包含MediaDeviceInfo实例的数组,它包含了可用的多媒体输入输出设备的信息。 下面是调用代码示例。 navigator.mediaDevices.enumerateDevices().then((devices) => { console.log(devices, '-----enumerateDevices------');});设备参数说明: deviceId:设备id,具有唯一性groupId:设备组id,不具有唯一性kind:设备类别(audioinput:音频输入设备,audiooutput:音频输出设备,videoinput:视频输入设备)label:设备名称(未经过授权允许的设备,label值为空,授权允许后可拿到label的值,如下两图所示)获取的所有设备截图(未授权): ...

June 13, 2019 · 4 min · jiezi

给项目加一个骨架屏吧

给项目加一个骨架屏吧骨架屏可以理解为是当数据还未加载进来前,页面的一个空白版本,一个简单的关键渲染路径。用户会看到一个样式简单,描绘了当前页面的大致框架的骨架屏页面,然后骨架屏中各个占位部分被实际资源完全替换,这个过程中用户会觉得内容正在逐渐加载即将呈现,降低了用户的焦躁情绪,使得加载过程主观上变得流畅。 安装这里采用饿了么开源的方案page-skeleton-webpack-plugin。 npm install --save-dev page-skeleton-webpack-pluginnpm install --save-dev html-webpack-plugin安装过程中报错提示如下 ERROR: Failed to download Chromium r515411! Set "PUPPETEER_SKIP_CHROMIUM_DOWNLOAD" env variable to skip download.执行这个命令 npm config set puppeteer_download_host=https://storage.googleapis.com.cnpmjs.org使用我这个项目是基于vue-cli3脚手架开发的。 第一步配置插件创建一个vue.config.js文件。 const { SkeletonPlugin } = require('page-skeleton-webpack-plugin')const path = require('path')module.exports = { configureWebpack: { plugins: [ new SkeletonPlugin({ pathname: path.resolve(__dirname, './shell'), // 用来存储 shell 文件的地址 staticDir: path.resolve(__dirname, './dist'), // 最好和 `output.path` 相同 routes: ['/'], // 将需要生成骨架屏的路由添加到数组中 excludes: ['.van-nav-bar', '.van-tabbar'] // 需要忽略的css选择器 }) ], }, chainWebpack: (config) => { // 解决vue-cli3脚手架创建的项目压缩html 干掉<!-- shell -->导致骨架屏不生效 if (process.env.NODE_ENV !== 'development') { config.plugin('html').tap(opts => { opts[0].minify.removeComments = false return opts }) } },};在项目根目录下面创建一个shell文件夹。chainWebpack配置 这个是解决vue-cli3打包的骨架屏不生效的BUG ...

June 13, 2019 · 1 min · jiezi

老生常谈之响应式开发

什么是响应式设计?作为一名合格的前端开发攻城狮(工程师),做的最多的恐怕就是多端适配,多端兼容的工作了吧,那么如何解决一套代码多端并行且多端适配呢?这个时候响应式开发就应运而生了。什么是响应式设计?什么又是响应式图像呢?我们来了解什么是响应式设计:网页在不同的设备上,都可以达到让使用者感觉比较舒适的合理的视觉体验,叫做“响应式设计”(responsive web design)。由响应式设计的网页图像,就叫做响应式图像 响应式的解决方案有很多,JavaScript 和css都可以实现,这里我们了解一种最简单的,语义最好的HTML的解决方案,而且浏览器都原生支持的。 一、由img标签引起的问题<img src="screen.png">这一行代码在移动端和PC端,插入的都是图片screen.png文件这种方式虽然简单高效,可以多端并行,但是有很多的弊端:1、体积比较大。假设来说我们这个图片有300Kb,在PC端可以使用较大的尺寸,那么在移动端,我么就需要一个看起来比较符合舒服的尺寸,这样既可以节省带宽,降低服务器的压力,也可以更快的让图片渲染出来,提供良好的用户体验。2.像素密度问题。做过移动端的开发的攻城狮都了解过PC的渲染和移动端的渲染是不一样的。PC端一般是单倍的像素密度,而手机上的显示器往往是多倍的像素密度。这样的后果就是我们同样一张图,在PC上很清晰,到手机上渲染的时候看起来就很模糊,因为像素扩充了。3.视觉体验。因为我们桌面级别的显示器屏幕的面积更大,可以暴露出来很多图像的细节,但是手机屏幕比较小,很多细节是无法看清楚的,需要突出重点 二、图片大小的选择 为了解决体积问题希望不同尺寸的屏幕,显示不同大小的图像,我们需要srcset属性搭配sizes属性。 <img srcset="foo-320.jpg 320w, foo-640.jpg 640w, foo-1280.jpg 1980w" sizes="(max-width: 440px) 100vw, (max-width: 900px) 33vw, 254px" src="foo-1280.jpg">上面代码中, srcset:srcset属性列出四张可用的图像,每张图像的 URL 后面是一个空格,再加上宽度描述符。 宽度描述符就是图像原始的宽度,加上字符w。上例的四种图片的原始宽度分别为320像素、640像素和1980像素。 2.sizes:sizes属性给出了三种屏幕条件,以及对应的图像显示宽度。宽度不超过440像素的设备,图像显示宽度为100%;宽度441像素到900像素的设备,图像显示宽度为33%;宽度900像素以上的设备,图像显示宽度为254px。 3.浏览器根据当前设备的宽度,从sizes属性获得图像的显示宽度,然后从srcset属性找出最接近该宽度的图像,进行加载。 假定当前设备的屏幕宽度是960px,浏览器从sizes属性查询得到,图片的显示宽度是33vw(即33%),等于320px。srcset属性里面,正好有宽度等于320px的图片,于是加载foo-320.jpg。 注意,sizes属性必须与srcset属性搭配使用。单独使用sizes属性是无效的。 四、<picture>标签,<source>标签 如果要同时适配不同像素密度、不同大小的屏幕,应该怎么办呢? 这时,就要用到<picture>标签。它是一个容器标签,内部使用<source>和<img>,指定不同情况下加载的图像。 <picture> <source media="(max-width: 500px)" srcset="vertical.svg"> <source media="(min-width: 501px)" srcset="cat-horizontal.svg"> <img src="cat.jpg" alt="cat"></picture>上面代码中,<picture>标签内部有两个<source>标签和一个<img>标签。 <source>标签的media属性给出媒体查询表达式,srcset属性就是<img>标签的srcset属性,给出加载的图像文件。sizes属性其实这里也可以用,但由于有了media属性,就没有必要了。 浏览器按照<source>标签出现的顺序,依次判断当前设备是否满足media属性的媒体查询表达式,如果满足就加载srcset属性指定的图片文件,并且不再执行后面的<source>标签和<img>标签。 <img>标签是默认情况下加载的图像,用来满足上面所有<source>都不匹配的情况。 上面例子中,设备宽度如果不超过500px,就加载竖屏的图像,否则加载横屏的图像。 五、<source>标签的type属性除了响应式图像,<picture>标签还可以用来选择不同格式的图像。比如,如果当前浏览器支持 Webp 格式,就加载这种格式的图像,否则加载 PNG 图像。 <picture> <source type="image.svg" srcset="logo.svg"> <source type="image.webp" srcset="logo.webp"> <img src="logo.png" alt="ACME Corp"></picture>上面代码中,<source>标签的type属性给出图像的 MIME 类型,srcset是对应的图像 URL。 浏览器按照<source>标签出现的顺序,依次检查是否支持type属性指定的图像格式,如果支持就加载图像,并且不再检查后面的<source>标签了。上面例子中,图像加载优先顺序依次为 svg 格式、webp 格式和 png 格式。 六、参考链接 http://www.ruanyifeng.com/blo... 更多优质文章请关注公众号 ...

June 13, 2019 · 1 min · jiezi

2019年前端笔试题

什么是web标准?WEB标准不是某一个标准,而是一系列标准的集合。网页主要由三部分组成:结构(Structure)、表现(Presentation)和行为 (Behavior)。 对应的标准也分三方面:结构化标准语言主要包括XHTML和XML,表现标准语言主要包括CSS,行为标准主要包括对象模型(如 W3C DOM)、ECMAScript等。这些标准大部分由W3C起草和发布,也有一些是其他标准组织制订的标准,比如ECMA(European Computer Manufacturers Association)的ECMAScript标准。 请解释一下DOCTYPE的作用,有DOCTYPE和没有DOCTYPE有什么区别?<!DOCTYPE>声明位于位于HTML文档中的第一行,处于 <html> 标签之前。告知浏览器的解析器用什么文档标准解析这个文档。DOCTYPE不存在或格式不正确会导致文档以兼容模式呈现。 XHTML与HTML有什么区别 XHTML 元素必须被正确地嵌套。XHTML 元素必须被关闭。标签名必须用小写字母。XHTML 文档必须拥有根元素。严格模式与混杂模式——如何触发这两种模式,区分它们有何意义。 当浏览器厂商开始创建与标准兼容的浏览器时,他们希望确保向后兼容性。为了实现这一点,他们创建了两种呈现模式:标准模式和混杂模式。 在标准模式中,浏览器根据规范呈现页面;在混杂模式中,页面以一种比较宽松的向后兼容的方式显示。混杂模式通常模拟老式浏览器的行为以防止老站点无法工作。浏览器根据DOCTYPE是否存在以及使用的哪种DTD来选择要使用的呈现方法。如果XHTML文档包含形式完整的DOCTYPE,那么它一般以标准模式 呈现。对于HTML4.01文档,包含严格DTD的DOCTYPE常常导致页面以标准模式呈现。包含过渡DTD和URI的DOCTYPE也导致页面以标准 模式呈现,但是有过渡DTD而没有URI会导致页面以混杂模式呈现。DOCTYPE不存在或形式不正确会导致HTML和XHTML文档以混杂模式呈现。根据DOCTYPE是否存在选择呈现模式,被称为DOCTYPE切换或DOCTYPE侦测。DOCTYPE切换是浏览器用来区分遗留文档和符合标准的文档的手段。无论是否编写了有效的CSS,如果选择了错误的DOCTYPE,那么页面就将以混杂 模式呈现,其行为就可能会有错误或不可预测。因此一定要在每个页面上包含形式完整的DOCTYPE声明,并且在使用HTML时选择严格的DTD。写出3个使用this的典型应用 (1)在html元素事件属性中使用,如: <input type=”button” onclick=”showInfo(this);” value=”点击一下”/>(2)构造函数 function Animal(name, color) { this.name = name; this.color = color;}(3)input点击,获取值 <input type="button" id="text" value="点击一下" /><script type="text/javascript"> var btn = document.getElementById("text"); btn.onclick = function() { alert(this.value); //此处的this是按钮元素 }</script>(4)apply()/call()求数组最值 var numbers = [5, 458 , 120 , -215 ]; var maxInNumbers = Math.max.apply(this, numbers); console.log(maxInNumbers); // 458var maxInNumbers = Math.max.call(this,5, 458 , 120 , -215); console.log(maxInNumbers); // 458数组去重 ...

June 13, 2019 · 3 min · jiezi

隐藏火狐和谷歌浏览器滚动条

有时候想要实现滚动条隐藏,但是还是可以滚动内容的效果 怎么实现呢? 谷歌浏览器webkit &::-webkit-scrollbar { display: none; }火狐浏览器scrollbar-width: none;

June 13, 2019 · 1 min · jiezi

前端每日实战-169-视频演示如何为世界上最长单词的制作一个数略词交互动画内含2个视频

效果预览按下右侧的“点击预览”按钮可以在当前页面预览,点击链接可以全屏预览。 https://codepen.io/comehope/pen/byvRxB 可交互视频此视频是可以交互的,你可以随时暂停视频,编辑视频中的代码。 请用 chrome, safari, edge 打开观看。 视频1: https://scrimba.com/p/pEgDAM/cR4gpGsa视频2: https://scrimba.com/p/pEgDAM/czNp3MUZ 源代码下载每日前端实战系列的全部源代码请从 github 下载: https://github.com/comehope/front-end-daily-challenges 代码解读大家是否见过 “i18n”、“a11y” 这样的英文单词?它们其实是一些单词的缩写,“i18n” 代表的是 “internationalization”(国际化),“a11y” 代表的是 “accessibility”(可访问性),因为包含的字母太多了,所以缩写时只保留头尾的字母,再把余下的字符个数写在中间,这种写法称为“Numeronym”,我把它翻译成“数略词”。据说最长的单词是 “pneumonoultramicroscopicsilicovolcanoconiosis”,由 45 个字母组成,意思是一种肺部疾病。 本项目将制作一个交互动画效果,令其在单词原词和“数略词”之间切换。整个项目分成二个步骤开发,第一步先实现一个固定单词的交互动画,第二步改写为能自动处理任意的单词,然后扩展应用到多个单词上。 一、一个固定单词的交互动画 dom 结构如下,最外侧的容器名为 .container,其中包含一个名为 .word 的 <div> 元素,它代表一个单词,它的子元素是 4 个 <p> 元素,分别代表单词的第1个字母、中间字符的个数(.middle.short)、中间的若干字符(.middle.long)、单词的最后1个字母。因为动画时将交替显示“中间字符的个数”和“中间的若干字符”,所以为它们设置了特殊类名,以便在随后的 css 代码中引用它们,当要同时选择它们时,就用它们共同的类名 middle,当要分别选择时,就指定它们各自的类名 short 和 long: <div class="container"> <div class="word"> <p>i</p> <p class="middle short"> <span>18</span> </p> <p class="middle long"> <span>nternationalizatio</span> </p> <p>n</p> </div></div>令容器居于页面正中: body { margin: 0; height: 100vh; display: flex; align-items: center; justify-content: center; background-image: linear-gradient(bisque, lightcyan);}让 4 个 <p> 标签包含的文字横向排列在容器中部: ...

June 13, 2019 · 3 min · jiezi

最近正在重构之前开发过的记账本

最近正在重构之前开发过的记账本,之前做得太烂了,现在想重新使用重构一般移动端的记账本,加入了新的功能,主要技术站为 webapp vue.js 后端php,可能原生写。 也可能使用框架写。 也可能使用 node.js写。 也可能使用go语言写。 也可能使用java写小程序版本app安卓版本,还有可能使用IOS版本码云地址 Ken / 记账本,重构 暂时页面的安排,以及目录的排版vueaccountProject setupnpm installCompiles and hot-reloads for developmentnpm run serveCompiles and minifies for productionnpm run buildRun your testsnpm run testLints and fixes filesnpm run lintCustomize configurationSee Configuration Reference. 启动页面|---------loading/ 启动页面 |----component/ 组件模块 |----loading.vue |----common/ 公共模块 |----style/ 样式模块注册页面|---------login/ 注册页面 |--component/ 组件模块 |----login.vue |--common/ 公共模块 |--sytle/ 样式模块首页|---------home/ 首页 |--component/ 组件模块 |----date.vue 日期组件 |----inout.vue 收入支出组件 |----visualize.vue 可视化组件 |----importaccout.vue 导入账单组件 |----voiceaccount.vue 语音账单组件 |--common/ 公共组模块 |--style/ 样式模块账本|---------account/ 账本 |---component/ 组件模块 |-----head.vue 头部组件 |-----account.vue 账本组件 |-----scroll.vue 滚动组件 |---common/ 公共模块 |---style/ 样式模块我的资金|---------usermoney/ 用户资金 |---component/ 组件模块 |---inputmoney.vue 输入资金组件 |---showmoney.vue 展示资金模块 |---common/ 公共模块 |---style/ 样式模块我|---------user/ 用户模块 |---component/ 组件模块 |---head.vue 导航 |---usernote.vue 账号密码修改 |---dailyremind.vue 每日提醒 |---exportbooks.vue 导出账本 |---aboutus.vue 关于我们 |---softwareupdates.vue 软件更新 |---common/ 公共模块 |---style/ 样式模块添加记账页面|---------addaccount/ 添加记账 |-----inaccount 收入页面 |-----component/ |-----head.vue 图表 |-----show.vue 显示各种收入 |-----common/ |-----style/ |-----outaccount 支出页面 |-----component/ |-----head.vue 图标 |-----show.vue 显示各种支出 |-----common/ |-----style/ |------transferaccounts/ 转账页面 |------component/ |----head.vue 图标 |----show.vue 显示转出转入 |------common/ |------style/ |-------blance/ 余额 |------component/ |---inputblance.vue 转入余额 |---showblance.vue 显示余额 |------common/ |------style/ ...

June 13, 2019 · 1 min · jiezi

spydebugger-Charles-移动端调试

简介 移动端调试一直都是一个痛点,因为移动终端对于我们来说是一个黑盒,它无法像PC端一样,我们可以通过F12很方便的调出开发者工具。在开发中经常会遇到同样一份代码在某个型号的手机上运行出现错误,其他手机都好好的,开发的时候Chrome上也没有报错。如果没有调试工具这种情况下我们就很难定位问题,接下来的主题就是介绍如何使用spy-debugger + Charles进行移动端调试。 安装第1步:全局安装 spy-debugger npm install spy-debugger -gspy-debugger 证书其实spy-debugger的代理是基于node-mitmproxy模块实现的,这里安装的证书其实是node-mitmproxy的证书,标题写spy-debugger证书是为了和Charels证书区分开来避免混淆。 电脑安装证书第1步:在命令行中执行spy-debugger启动spy-debugger服务,启动成功后,检查你的用户目录(home目录),会发现多了一个node-mitmproxy文件夹,这个文件夹内放的就是代理需要的证书。 我Mac电脑完整的路径是:/Users/jameswain/node-mitmproxy 第2步:在启动spy-debugger服务的电脑上安装证书,双击node-mitmproxy.ca.crt文件 第3步:双击node-mitmproxy CA 选择为 始终信任 第4步:输入你电脑的用户密码 出现这个+号表示证书已经安装成功 IOS手机安装证书第1步:首先需要将node-mitmproxy.ca.crt上传到手机上,可以通过live-server 在node-mitmproxy.ca.crt文件所在的目录下启动这个服务。如果你还没有live-server命令,可以通过以下命令进行安装: npm i -g live-server在/Users/jameswain/node-mitmproxy目录下执行live-server命令 第2步:在手机浏览器上访问这个服务,输入我电脑的IP地址和端口进行访问,⚠️手机和电脑必须是连接同一个WiFi网络才可以访问。 点击node-mitmproxy.ca.crt文件进行下载安装 第3步:在手机的 设置 > 通用 > 描述文件与设备管理 找到node-mitmproxy CA 证书,并点击安装 输入手机锁屏密码: 选择安装 第4步:在手机的 设置 > 通用 > 关于本机 > 证书信任设置 将 node-mitmproxy CA 打开 此时,spy-debugger的前期准备工作就已经全部完成了 Charles 证书这里简单介绍一下Charles的证书安装,如果你已经是Charles的老手了,可以直接跳过。Charles如果不安装证书的话是无法抓https的请求的。 ...

June 13, 2019 · 1 min · jiezi

WebView的基本使用及相关特性

WebView 是一个显示网页内容的组件,可以显示网络上的一些在线内容并且可以作为 Web 浏览器滚动显示的内容,它使用 WebKit作为渲染引擎来显示网页,里面包括放大、缩小、执行文本搜索等进行前后导航的方法。 注意 :如果要在 WebView 中显示在线网页等内容时,需要在 AndroidManifest.xml 文件中添加网络权限,参考如下: <uses-permission android:name="android.permission.INTERNET" />基本用法默认情况下 WebView 不启用 JavaScript ,网页错误也将被忽略,如果仅仅是在 UI 上显示一段 HTML,这就会非常好, 用户在不需要再阅读之前与用户交互,网页不需要与用户交互 ,如果你需要一个完整的浏览器,你需要调用相应的 Intent 去启动浏览器去执行某些操作,而不是使用 WebView 来显示,调用系统浏览器使用如下代码: Uri uri = Uri.parse("https://www.example.com");Intent intent = new Intent(Intent.ACTION_VIEW, uri);startActivity(intent); 使用 WebView 主要有两种使用方式,在 Activity 等 onCreate() 方法直接创建使用或者在布局文件中引入,参考如下: 1. 在代码中直接创建 WebViewWebView webview = new WebView(this);//这里将整个 Activity 窗口作为 WebView 的显示界面,也可单独放在某个布局中setContentView(webview);2. 在布局文件中使用 WebView<WebView android:id="@+id/webView" android:layout_width="match_parent" android:layout_height="match_parent"></WebView>那么,我们如何加载一个网页呢,如果网页是本地的又如何加载呢,还有如何加载一段 HTML 的片段呢,常用的加载方法主要有两个,如下: 1. 加载一个完整的网页这里测试使用百度首页、CSDN首页、腾讯首页进行测试,测试百度首页时,需要设置如下属性网页内容才能正确显示,如果不设置将显示为白屏: webSettings.setJavaScriptEnabled(true);webSettings.setDomStorageEnabled(true);webView.loadUrl("https://www.baidu.com");测试 CSDN 首页时,会提示打开系统带浏览器的应用去打开该页面,设置如下属性才能直接加载网页内容: ...

June 13, 2019 · 2 min · jiezi

transform-变形

transform 变形 通过 CSS3 变换,我们能够对元素进行移动、缩放、转动、拉长或拉伸。使用transform属性为元素应用变换。 1、Transform:对元素进行变形。 2、Transition:对元素某个属性或多个属性的变化,进行控制(时间等),类似flash的补间动画。但只有两个关键贞。开始,结束。 一.CSS3 2D 转换 1、2D Transform转换属性 2、Transform 方法 ①.移动 translate translate(x,y)水平方向和垂直方向同时移动(也就是X轴和Y轴同时移动) translateX(x)仅水平方向移动(X轴移动) translateY(Y)仅垂直方向移动(Y轴移动) ②.缩放 scale scale(x,y)使元素水平方向和垂直方向同时缩放(也就是X轴和Y轴同时缩放) scaleX(x)元素仅水平方向缩放(X轴缩放) scaleY(y)元素仅垂直方向缩放(Y轴缩放) ③.旋转 rotate 在一个给定度数顺时针旋转的元素。负值是允许的,这样是元素逆时针旋转。 ④.倾斜 skew skew(x,y)使元素在水平和垂直方向同时倾斜(X轴和Y轴同时按一定的角度值进行倾斜变形) skewX(x)仅使元素在水平方向倾斜变形(X轴倾斜变形) skewY(y)仅使元素在垂直方向倾斜变形(Y轴倾斜变形) 如果大家觉得我的文章写的还不错的话,就关注 收藏一下哦! 大家可以一起探讨下前端问题呀! rgz987

June 13, 2019 · 1 min · jiezi

实现跨域通信的9种方法

首先明确,跨域请求只是浏览器对请求的限制,虽然跨域,服务器仍然能收到客户端请求,服务器之间通信不存在跨域问题。1. 什么是跨域?协议域名端口只要协议、域名、端口号其中任意一者不同,均属跨域。2. 实现跨域的9种方法1 jsonp 2 cors 3 nginx 4 websocket 5 postMessage 6 document.domain 7 window.name 8 location.hash 9 http-proxy jsonpcorsAccess-Control-Allow-Origin: * 就不允许跨域携带cookienginx<!-- 访问.json文件时,会去root 下面json文件中查找 -->location ~.*\.json { root json;}postMessagedocument.domain一级域名和二级域名之间的通信window.namelocation.hashhttp-proxywebsocketsocket.io库结论根据不同的应用场景,选择相应的跨域通信方式。

June 12, 2019 · 1 min · jiezi

webpack4大结局加入腾讯IM配置策略实现前端工程化环境极致优化

webpack,打包所有的资源不知道不觉,webpack已经偷偷更新到4.34版本了,本人决定,这是今年最后一篇写webpack的文章,除非它更新到版本5,本人今年剩下的时间都会放在Golang和二进制数据操作以及后端的生态上在看本文前,假设你对webpack有一定了解,如果不了解,可以看看我之前的手写React和Vue脚手架的文章手写优化版React脚手架手写Vue的脚手架前端性能优化不完全手册跨平台webpack配置都是百星star的优质文章在此对webpack的性能优化进行几点声明:在部分极度复杂的环境下,需要双package.json文件,即实行三次打包在代码分割时,低于18K的文件没必要单独打包成一个chunk,http请求次数过多反而影响性能prerender和PWA互斥,这个问题暂时没有解决babel缓存编译缓存的是索引,即hash值,非常吃内存,每次开发完记得清理内存babel-polyfill按需加载在某些非常复杂的场景下比较适合prefetch,preload对首屏优化提升是明显代码分割不管什么技术栈,一定要做,不然就是垃圾项目多线程编译对构建速度提升也很明显代码分割配合PWA+预渲染+preload是首屏优化的巅峰,但是pwa无法缓存预渲染的html文件本文的webpack主要针对React技术栈,实现功能如下:开发模式热更新识别JSX文件识别class组件代码混淆压缩,防止反编译代码,加密代码配置alias别名,简化import的长字段同构直出,SSR的热调试(基于Node做中间件)实现javaScript的tree shaking 摇树优化 删除掉无用代码实现CSS的tree shaking识别 async / await 和 箭头函数react-hot-loader记录react页面留存状态statePWA功能,热刷新,安装后立即接管浏览器 离线后仍让可以访问网站 还可以在手机上添加网站到桌面使用preload 预加载资源 prefetch按需请求资源CSS模块化,不怕命名冲突小图片的base64处理文件后缀省掉jsx js json等实现React懒加载,按需加载 , 代码分割 并且支持服务端渲染支持less sass stylus等预处理code spliting 优化首屏加载时间 不让一个文件体积过大加入dns-prefetch和preload预请求必要的资源,加快首屏渲染(京东策略)加入prerender,极大加快首屏渲染速度提取公共代码,打包成一个chunk每个chunk有对应的chunkhash,每个文件有对应的contenthash,方便浏览器区别缓存图片压缩CSS压缩增加CSS前缀 兼容各种浏览器对于各种不同文件打包输出指定文件夹下缓存babel的编译结果,加快编译速度每个入口文件,对应一个chunk,打包出来后对应一个文件 也是code spliting删除HTML文件的注释等无用内容每次编译删除旧的打包代码将CSS文件单独抽取出来让babel不仅缓存编译结果,还在第一次编译后开启多线程编译,极大加快构建速度等等....本质上,webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler)。当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个 bundlewebpack打包原理识别入口文件通过逐层识别模块依赖。(Commonjs、amd或者es6的import,webpack都会对其进行分析。来获取代码的依赖)webpack做的就是分析代码。转换代码,编译代码,输出代码最终形成打包后的代码这些都是webpack的一些基础知识,对于理解webpack的工作机制很有帮助。舒适的开发体验,有助于提高我们的开发效率,优化开发体验也至关重要组件热刷新、CSS热刷新自从webpack推出热刷新后,前端开发者在开环境下体验大幅提高。没有热刷新能力,我们修改一个组件后 加入热刷新后 主要看一下React技术栈,如何在构建中接入热刷新无论什么技术栈,都需要在dev模式下加上 webpack.HotModuleReplacementPlugin插件 devServer: { contentBase: '../build', open: true, port: 5000, hot: true },注:也可以使用react-hot-loader来实现,具体参考官方文档 在开发模式下也要代码分割,加快打开页面速度optimization: { runtimeChunk: true, splitChunks: { chunks: 'all', minSize: 10000, // 提高缓存利用率,这需要在http2/spdy maxSize: 0,//没有限制 minChunks: 3,// 共享最少的chunk数,使用次数超过这个值才会被提取 maxAsyncRequests: 5,//最多的异步chunk数 maxInitialRequests: 5,// 最多的同步chunks数 automaticNameDelimiter: '~',// 多页面共用chunk命名分隔符 name: true, cacheGroups: {// 声明的公共chunk vendor: { // 过滤需要打入的模块 test: module => { if (module.resource) { const include = [/[\\/]node_modules[\\/]/].every(reg => { return reg.test(module.resource); }); const exclude = [/[\\/]node_modules[\\/](react|redux|antd)/].some(reg => { return reg.test(module.resource); }); return include && !exclude; } return false; }, name: 'vendor', priority: 50,// 确定模块打入的优先级 reuseExistingChunk: true,// 使用复用已经存在的模块 }, react: { test({ resource }) { return /[\\/]node_modules[\\/](react|redux)/.test(resource); }, name: 'react', priority: 20, reuseExistingChunk: true, }, antd: { test: /[\\/]node_modules[\\/]antd/, name: 'antd', priority: 15, reuseExistingChunk: true, }, }, } }简要解释上面这段配置将node_modules共用部分打入vendor.js bundle中;将react全家桶打入react.js bundle中;如果项目依赖了antd,那么将antd打入单独的bundle中;(其实不用这样,可以看我下面的babel配置,性能更高)最后剩下的业务模块超过3次引用的公共模块,将自动提取公共块注意 上面的配置只是为了给大家看,其实这样配置代码分割,性能更高optimization: { runtimeChunk: true, splitChunks: { chunks: 'all', }}react-hot-loader记录react页面留存状态stateyarn add react-hot-loader // 在入口文件里这样写 import React from "react";import ReactDOM from "react-dom";import { AppContainer } from "react-hot-loader";-------------------1、首先引入AppContainreimport { BrowserRouter } from "react-router-dom";import Router from "./router"; /*初始化*/renderWithHotReload(Router);-------------------2、初始化 /*热更新*/if (module.hot) {-------------------3、热更新操作 module.hot.accept("./router/index.js", () => { const Router = require("./router/index.js").default; renderWithHotReload(Router); });} function renderWithHotReload(Router) {-------------------4、定义渲染函数 ReactDOM.render( <AppContainer> <BrowserRouter> <Router /> </BrowserRouter> </AppContainer>, document.getElementById("app") );}然后你再刷新试试React的按需加载,附带代码分割功能 ,每个按需加载的组件打包后都会被单独分割成一个文件 import React from 'react' import loadable from 'react-loadable' import Loading from '../loading' const LoadableComponent = loadable({ loader: () => import('../Test/index.jsx'), loading: Loading, }); class Assets extends React.Component { render() { return ( <div> <div>这即将按需加载</div> <LoadableComponent /> </div> ) } } export default Assets* 加入html-loader识别html文件 { test: /\.(html)$/, loader: 'html-loader' }配置别名 resolve: { modules: [ path.resolve(__dirname, 'src'), path.resolve(__dirname,'node_modules'), ], alias: { components: path.resolve(__dirname, '/src/components'), }, } 加入eslint-loader { enforce:'pre', test:/\.js$/, exclude:/node_modules/, include:resolve(__dirname,'/src/js'), loader:'eslint-loader' }resolve解析配置,为了为了给所有文件后缀省掉 js jsx json,加入配置resolve: { extensions: [".js", ".json", ".jsx"]}加入HTML文件压缩,自动将入门的js文件注入html中,优化HTML文件 new HtmlWebpackPlugin({ template: './public/index.html', minify: { removeComments: true, collapseWhitespace: true, removeRedundantAttributes: true, useShortDoctype: true, removeEmptyAttributes: true, removeStyleLinkTypeAttributes: true, keepClosingSlash: true, minifyJS: true, minifyCSS: true, minifyURLs: true, } }),SSR同构直出热调试, 采用 webpack watch+nodemon 结合的模式实现对SSR热调试的支持。node 服务需要的html/js通过webpack插件动态输出,当nodemon检测到变化后将自动重启,html文件中的静态资源全部替换为dev模式下的资源,并保持socket连接自动更新页面。实现热调试后,调试流程大幅缩短,和普通非直出模式调试体验保持一致。下面是SSR热调试的流程图: ...

June 12, 2019 · 4 min · jiezi

模拟-vue30-rfcs-createComponent-api-中的props类型推导

rfc 中类型推导部分 Type Inference预期想实现的效果createComponent({ props: { foo: { type: String, required: true }, bar: { type: Number }, boo: Boolean, options: (null as any) as { msg: string }, requiredOptions: { type: (null as any) as { msg: string }, required: true } } as const, setup(props) { props.foo; // string props.bar; // number | undefined props.boo; // boolean | undefined props.options; // {msg: string } | undefined props.requiredOptions; // {msg: string } }});String -> string 、 Number -> number 、 Boolean -> boolean在 ts 中 ...

June 12, 2019 · 2 min · jiezi

实现平滑过渡的拖拽排序

最近重读Vue官方文档,在列表的排序过渡这一小节,文档提到,<transition-group> 组件有一个特殊的地方,不仅可以实现进入和离开动画,还可以改变定位,官网示例如下: 例子中实现的效果看起来还是非常不错的,这个效果使我想起来另外一个使用场景,之前我在实现一个列表展示需求的时候,PM想让这个列表具有拖动排序的功能,方便他操作(事实上我最后并没有给他做哈哈),拖动的动画跟这个很像,网上搜索一下,类似插件应该很多,那如果我们自己来实现一个,问题在哪里呢? 首先要拖拽元素,记录元素拖拽开始和结束的信息。将元素由拖拽开始的地方移到拖拽结束地方,这期间,目标元素和目标元素周围的元素要怎么平滑过渡到新的位置。问题1很好解决,翻一下api,HTML5提供了性能很棒的拖放API,PC端兼容性良好,可直接使用问题2刚好可以使用上面学到的<transition-group>组件去实现。 拖放API中提到,一个可拖拽的元素,在用户拖拽这一整个流程中,可以通过这个事件去获取你想要的信息: 这里的话,我们选取dragstart去记录下拖拽元素的信息,dragenter去记录此元素拖拽时经过了哪些元素,dragend事件中去做拖拽结束的操作,动画的事情就交给transition-group去做了。 最终实现的效果如下: demo代码如下: <!DOCTYPE html><html lang="en"><head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta name="viewport" content="initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no, width=device-width"> <title>test</title> <style type="text/css"> .flip-list-move { transition: transform 1s; } .items { width: 300px; height: 50px; line-height: 50px; text-align: center; border: 1px solid red; } </style></head><body> <div id="content"> <transition-group name="flip-list"> <div v-for="item in items" :key="item" draggable="true" class="items" @dragstart="dragstart(item)" @dragenter="dragenter(item)" @dragend="dragend(item)">{{item}}</div> </transition-group> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.14.1/lodash.min.js"></script> <script> var vue = new Vue({ el: '#content', data: { items: [1, 2, 3, 4, 5, 6, 7, 8, 9], oldNum: 0, newNum: 0 }, created: function created () { }, mounted: function mounted () { }, methods: { shuffle: function() { this.items = _.shuffle(this.items); }, // 记录初始信息 dragstart: function(value) { this.oldNum = value; }, // 做最终操作 dragend: function(value) { if (this.oldNum != this.newNum) { let oldIndex = this.items.indexOf(this.oldNum); let newIndex = this.items.indexOf(this.newNum); let newItems = [...this.items]; // 删除老的节点 newItems.splice(oldIndex, 1); // 在列表中目标位置增加新的节点 newItems.splice(newIndex, 0, this.oldNum); // this.items一改变,transition-group就起了作用 this.items = [...newItems]; } }, // 记录移动过程中信息 dragenter: function(value) { this.newNum = value; } } }); </script></body></html>注:你也可以一遍拖拽一遍更改顺序,不用等dragend再做动画,但是一边拖拽一边做动画的时候看起来眼花缭乱的(仅以这个demo来看是这样的,其他插件可以提供别的解决方法,暂且按下不表)所以我选择用户拖拽停止之后再做动画。在这一节中,vue官方还介绍了一个叫FLIP的简单的动画队列,有兴趣可以研究一下,FLIP介绍,打开这个FLIP你会发现它的示例中有介绍另外一个动画库GASP,可以实现很酷炫的动画效果,跟FLIP结合使用效果更佳。 ...

June 12, 2019 · 1 min · jiezi

利用canvas实现环形进度条

前提:有时候在项目中会有用到进度条的情况,使用css3也可以实现,但是对于性能不好的设备,或者网络不好的情况下,卡顿现象非常明显,避免出现不流畅的尴尬情况,所以记录一下,使用canvas来实现的方法。 效果图: DOM中,首先定义canvas画板元素: <canvas id="canvas" width="500" height="500" style="background:#F7F7F7;"> <p>you browser not support canvas!</p> </canvas>对于不支持canvas的浏览器则会显示:you browser not support canvas! 接下来是js编写:定义canvas.js并在页面引入 var canvas = document.getElementById('canvas'), //获取canvas元素 context = canvas.getContext('2d'), //获取画图环境,指明为2d centerX = canvas.width / 2, //Canvas中心点x轴坐标 centerY = canvas.height / 2, //Canvas中心点y轴坐标 rad = Math.PI * 2 / 100, //将360度分成100份,那么每一份就是rad度 speed = 0.1; //加载的快慢就靠它了//绘制蓝色外圈function blueCircle(n) { context.save(); context.beginPath(); context.strokeStyle = "#49f"; context.lineWidth = 12; context.arc(centerX, centerY, 100, -Math.PI / 2, -Math.PI / 2 + n * rad, false); context.stroke(); context.restore();}//绘制白色外圈function whiteCircle() { context.save(); context.beginPath(); context.strokeStyle = "#A5DEF1"; context.lineWidth = 12; context.arc(centerX, centerY, 100, 0, Math.PI * 2, false); context.stroke(); context.closePath(); context.restore();}//百分比文字绘制function text(n) { context.save(); context.fillStyle = "#F47C7C"; context.font = "40px Arial"; context.textAlign = "center"; context.textBaseline = "middle"; context.fillText(n.toFixed(0) + "%", centerX, centerY); context.restore();}//动画循环(function drawFrame() { window.requestAnimationFrame(drawFrame, canvas); context.clearRect(0, 0, canvas.width, canvas.height); whiteCircle(); text(speed); blueCircle(speed); if (speed > 100) speed = 0; speed += 0.1;}());window.requestAnimationFrame(drawFrame, canvas);每行代码的注释标注非常清楚,如果还有不理解的可以去看canvas基础,应该就可以了。 ...

June 12, 2019 · 1 min · jiezi

带着canvas去流浪4绘制散点图

示例代码托管在:http://www.github.com/dashnowords/blogs博客园地址:《大史住在大前端》原创博文目录 华为云社区地址:【你要的前端打怪升级指南】 [TOC] 一. 任务说明使用原生canvasAPI绘制散点图。(截图以及数据来自于百度Echarts官方示例库【查看示例链接】)。 二. 重点提示学习过折线图的绘制后,如果数据点只有坐标数据,则通过基本的坐标转换在对应的点上绘制出散点并不难实现。而在气泡图中,当我们直接将百度Echarts示例中的数据拿来经过一定的线性缩小后作为半径直接绘制散点时,就会出现一些问题,数据集的范围跨度较大,导致大部分点呈现后都非常小,这个时候就需要使用某种方法从真实数据值映射到散点圆半径进行映射,来缩小它们之间的差异,否则一旦数据集中有一个偏离度较大的点,就会造成其他点所对应的散点半径都很大或者都很小,对数据呈现来说是不可取的。例如在下面的示例中,当使用几种不同的映射方法来处理数据后,可以看到绘制的散点图是不一样的。 //求散点半径时所使用的公式//1.直接数值r = value * 5 / 100000000;//2.求对数r = Math.log(value);//3.求指数r = Math.pow(value,0.4) / 100;所绘制出的散点图如下所示: 坐标映射的实现思路其实并不算复杂,它的概念可以参考算法的时间复杂度来进行理解,挑选一个增长更快的映射函数来区分相近的点,或者挑选一个增长更慢的映射函数来减小大跨度数据之间的差异,在数据可视化中是非常实用的技巧。本文示例中的效果是笔者自己手动调的,如果要实现根据数据集自动挑选适当的映射函数,还需要设计一些计算方法,感兴趣的读者可以自行研究。 三. 示例代码气泡散点图绘制示例代码(坐标轴的绘制过程在前述博文中已经出现过很多次,故不再赘述,有需要的小伙伴可以直接翻看这个系列之前的博文或者查看本篇的demo): /*数据点来自于百度Echarts官方示例库,每个数值分别表示[横坐标,纵坐标,数值,国家,年份]*[28604,77,17096869,'Australia',1990]*//** * 绘制数据 */function drawData(options) { let data = options.data;//获取数据集 let xLength = (options.chartZone[2] - options.chartZone[0]); let yLength = (options.chartZone[3] - options.chartZone[1]); let gap = xLength / options.xAxisLabel.length; //遍历两个年份 for(let i = 0; i < data.length ;i++){ let x,y,r,c; context.fillStyle = options.colorPool[i];//从颜色池中选取颜色 context.globalAlpha = 0.8;//为避免点覆盖,采取半透明绘制 //遍历各个数据点 for(let j = 0; j < data[i].length ; j++){ //计算坐标 x = options.chartZone[0] + xLength * data[i][j][0] / 70000; y = options.chartZone[3] - yLength * (data[i][j][4] - 55) / (85 - 55); //直接数值 r = data[i][j][5] * 5 / 100000000; //求对数 r = Math.log(data[i][j][6]); //开根号 r = Math.pow(data[i][j][7],0.4) / 100; //绘制散点 context.beginPath(); context.arc(x, y , r , 0 , 2*Math.PI,false); context.fill(); context.closePath(); } }}浏览器中可查看效果: ...

June 11, 2019 · 3 min · jiezi

EnTanMoETM项目周报5月24日5月30日

项目进展Highlight:ETM-Forum 即将于近期上线 长久以来,ETM项目大部分工作是在一个由诺奖学者领衔设计的学术联盟中进行的,而后ETM实验室的学术人员与研发人员来共同实现。泛学术性质的人员构成,让ETM更多地专注于区块链核心与前沿技术的研究。 但仅仅这样是不够的,一个开源项目的繁荣,离不开广泛的社区开发者与支持者。为了改变目前小团体社区的现状,ETM社区论坛将于近期上线。不同于开发者网站,社区论坛不仅面向开发者,还将成为哲学家、经济学者、社区支持者们讨论与建设ETM生态的地方。 在ETM核心团队的构想中,在推动ETM-Core 1.0 上线后,ETM将由社区主导建设。所有的重大升级都将由社区理事会与全体社区支持者们共同决定。因为ETM不应该由某些人来控制,在花费大量心血打造出大众化的共识机制后,我们不希望某些人为因素使ETM偏离既定轨迹。 ETM-Core 优化交易转发逻辑,缓解大交易量下网络压力,已完成 95%etm-vm 性能优化,提升侧链交易效率,已完成 95%etm-Core 资产发行功能,已完成 30%核心代码阶段性梳理,已完成 25%05.数据库结构优化,已完成 10% ETM-Module 矿机 GUI 客户端,已完成 80%,进行界面进一步优化矿机一键部署脚本新增引导配置,已完成 75%ETM-Mobile ETM 钱包移动端研发,已完成 15%ETM-Web WebSite 新增资讯版块日常更新,已上线02.WebSite SEO 代码部分,已完成 100% Wallet v1.5 全面支持离线签名,交易全程私钥不联网,用户隐私更安全,已完成 98%,待修复安全审计中问题后一并上线修复安全审计中发现的部分 Bug,已完成 50%社区论坛建设,已完成 25%ETM-Doc GitHub 项目文档更新,跟进最新版本,已完成 100%运营进展社群数据 官方微信社群数量:200+ ,活跃率 66%官方微信社群人数:52000+官方微信客服好友:7900+ ,较上周增长 5.3%官方电报群人数:52000+官方微博关注人数:11000+官方微信公众号关注人数:1700+运营数据 官方微信公众号发布 4 篇图文官方微博发布 14 条微博,阅读总量 1.9 万在金色财经、共享财经、一本区块链、币乎、CSDN、简书、大鱼号、百家号、头条号、知乎号、企鹅号等各内容平台发布文章社群活动 “精进课堂”:每周五20:00社群知识共享,本期知识点为《共识机制——区块链世界的运行规则》“圆桌派”话题讨论:本周主题为# 当我们谈论共识的时候,我们在谈论什么?#“分秒必争”:每周二下午16:00争分夺秒时刻,小墨选取上周推送内容出题,墨粉抢答“日拱一卒”:本周知识点为IMO、IFO、IEO等7个名词,后台回复“日拱一卒”查看本周合辑“ETM世界”:每日在小程序签到可领取1积分“百里挑一”:每日在公众号后台回复“早茶”,收获不定期惊喜“Momo答题”:微博每日抢答送出5ETM币一周动态ETM第二次登上区块链头部媒体星球日报头条 5月24日,星球日报头条发布《Staking 时代两大流派,屌丝和贵族谁将胜出?》,文章中ETM首次与EOS、Cosmos 等明星项目一同被提及,UPoS的创新性和独特性再次受到星球日报关注。 本月ETM社区红人榜公布 ETM社区红人榜今日发布,ETM按照用户活跃量等综合指标选出5位社区红人,并将为5位红人送上ETM礼包,点击图片查看详情。 关注ETM更多信息ETM官方网站 www.entanmo.io 官方电报群 https://t.me/entanmo 微信公众号 ETM科学院 ...

June 11, 2019 · 1 min · jiezi

EnTanMoETM项目周报5月31日6月6日

项目进展ETM-Core 优化交易转发逻辑,缓解大交易量下网络压力,已完成 100%ETM-vm 性能优化,提升侧链交易效率,已完成 100%ETM-Core 资产发行功能,已完成 30%核心代码阶段性梳理,已完成 30%数据库结构优化,已完成 15%ETM-Module 矿机 GUI 客户端,已完成 90%矿机 GUI 客户端跨平台研发,已完成 10%矿机一键部署脚本新增引导配置,已完成 85%ETM-Mobile ETM 钱包移动端研发,已完成 18%ETM-Web WebSite 新增资讯版块日常更新,已上线Wallet v1.6 资产发行界面设计,已完成 10%修复安全审计中发现的部分 Bug,已完成 90%社区论坛建设,已完成 45%ETM-Other 相关 Bug 修复后交付神荼科技进行二次审计运营进展社群数据 官方微信社群数量:200+ ,活跃率66%官方微信社群人数:52000+官方微信客服好友:8000+ ,较上周增长5.3%官方电报群人数:52000+官方微博关注人数:11000+ ,较上个周期增长350%官方微信公众号关注人数:1700+运营数据 官方微信公众号发布 3 篇图文官方微博发布 24 条微博,阅读总量54998万,较上个周期上涨 187.95%在金色财经、共享财经、一本区块链、币乎、CSDN、简书、大鱼号、百家号、头条号、知乎号、企鹅号等各内容平台发布文章社群活动 01 . “红人榜”:五月份ETM红人榜已公布,奖品已发放 “圆桌派”:本周主题为# 靠假消息暴力拉盘的操作,你怎么看?#“分秒必争”:每周二下午16:00,小墨选取上周推送内容出题抢答“日拱一卒”:本周知识点为自治性、开放性、可编程等7个名词,后台回复“日拱一卒”查看本周合辑“ETM世界”:小程序签到活动结束,积分兑换已完成,5月31日之后所有积分清零且将不再进行兑换“百里挑一”:回复“早茶”送惊喜活动已结束,回复“早茶”仍可获取当日资讯。“Momo答题”:微博每日抢答送出 1 ETM币一周动态En-Tan-Mo即将登陆OKEX交易所 En-Tan-Mo将于香港时间6月10日于OK Jumpstart进行预约中签销售。第一轮销售时间为6月10日12:00(HKT)第二轮销售时间为6月10日13:00(HKT),每轮销售 1250 万 ETM。6月10日15:00上线 ETM/USDT、ETM/USDK 交易。 销售规则详情戳链接: 《一文看懂OK最新IEO项目En-Tan-Mo》 注:公众号后台回复“上所”,获取抢购指南。 En-Tan-Mo做客星球日报超话社区 6月5日晚20:00,En-Tan-Mo做客星球日报开展社区AMA。团队科学顾问Dr.Aaron Yuan现身星球超话直播间,为社区用户讲解UPoS共识机制,阐释这一双稳态共识机制如何实现用户公平参与。 En-Tan-Mo于reddit(国外网站)直播 6月6日下午17:00,En-Tan-Mo第二场直播启动。本次直播在国外网站reddit上开展AMA,团队科学顾问Dr.Aaron Yuan围绕上所、项目团队、核心技术、未来发展路径等话题,与国外用户进行思维碰撞。 En-Tan-Mo做客蜂巢财经 ...

June 11, 2019 · 1 min · jiezi

ionic-QR-Scanner常见问题解决

扫码页面黑屏1) src -> index.js。修改代码如下 <ion-app style="background: none transparent;"></ion-app>2)src -> theme -> variables.scss // qrScannerion-app.cameraView, ion-app.cameraView ion-content, ion-app.cameraView .nav-decor { background: transparent none !important; .tabbar.show-tabbar{ opacity: 0; }}[app-viewport],[overlay-portal],[nav-viewport],[tab-portal],.nav-decor { display: none !important; background: none transparent !important;}html,body.transparent-body,.transparent-body,.transparent-body ion-app,.transparent-body .app-root,.transparent-body ion-nav,.transparent-body .ion-page,.transparent-body .nav-decor,.transparent-body ion-content,.transparent-body .viewscan,.transparent-body .fixed-content,.transparent-body .scroll-content { background-color: transparent !important; background: transparent none!important;} 多次扫码后摄像头发热的问题 this.qrScanner.hide(); // hide camerathis.qrScanner.destroy(); // destory camera QR Scanner安卓不能扫码条形码问题此问题乃是编码格式的问题,扩充编码格式即可解决。解决办法: 全局搜索formatList。找到QRScanner.java文件,定位到458行。 formatList.add(BarcodeFormat.UPC_A);formatList.add(BarcodeFormat.UPC_E);formatList.add(BarcodeFormat.EAN_13);formatList.add(BarcodeFormat.EAN_8);formatList.add(BarcodeFormat.CODE_39);formatList.add(BarcodeFormat.CODE_93);formatList.add(BarcodeFormat.CODE_128);formatList.add(BarcodeFormat.ITF);formatList.add(BarcodeFormat.DATA_MATRIX);修改源代码后。要重新构建安卓平台 ionic cordova platform remove androidionic cordova platform add android ...

June 11, 2019 · 1 min · jiezi

EnTanMoETM项目周报5月10日5月16日

项目进展Highlight:ETM-Wallet v1.5 重磅升级 ETM-Wallet 将于近期迎来一次重要升级,在 v1.5 版本带来全新的功能与 UI: 支持离线签名,全面提升用户交易安全性,交易全程私钥不联网「矿工模式」让不同用户更直观的了解个人收益信息「帮助与提示」新用户能够更快上手全新的注册流程,再也不怕忘记助记词遗失账户啦用户资产安全是ETM-Wallet 所有功能的前提,此次更新,团队从底层重构了所有交易的实现方式,将构建与签名交易全部离线完成。如此一来,只有用户,也就是私钥的所有者才能够接触到私钥,在所有交易类型的所有交易过程,私钥都不联网。用户的隐私安全、资产安全得到极大保障。 ETM-Core 01.优化交易转发逻辑,缓解大交易量下网络压力,已完成 75% ETM-vm 性能优化,提升侧链交易效率,已完成 75%ETM-Core 资产发行功能,已完成 5%核心代码阶段性梳理启动ETM-Module 矿机 GUI 客户端,已完成 60%矿机增加节点状态查看与管理,已完成 90%,开始稳定性测试矿机一键部署脚本新增引导配置,已完成 65%ETM-Mobile ETM 钱包移动端研发,已完成 10%ETM-Web WebSite 新增资讯版块日常更新,已上线WebSite SEO 代码部分,已完成 80%03.Wallet v1.5 全面支持离线签名,交易全程私钥不联网,用户隐私更安全,已完成75% 社区论坛建设,已完成需求讨论与部分设计ETM-Doc 01.GitHub 项目文档更新,跟进最新版本,已完成 75% 02.官网资讯与开发者文档国际化工作,已完成并提交更新 ETM-Other 委托神荼科技进行全面安全审计,已完成 95%,预计一周内交付运营进展社群数据 官方微信社群数量:200+ ,活跃率68%官方微信社群人数:52000+官方微信好友数:7000+ ,较上周增长 14%官方电报群人数:52000+ ,较上周增长 26.83%官方微博关注人数:11000+ ,较上周增长 33.3%官方微信公众号关注人数:1600+ ,较上周增长 6.55%运营数据 官方微信公众号发布 3 篇图文官方微博发布 18 条微博,阅读总量 27468在巴比特、共享财经、一本区块链、简书、大鱼号、百家号、头条号、知乎号、企鹅号等各内容平台发布文章社群活动 01.中文名征集:中文名征集活动进入评选、公示阶段,Pick奖投票结果在首条图文公布。 02.“圆桌派”话题讨论:#从今以后,你就是ETM的人了#,发言被翻牌即送5ETM。 “Momo答题”:微博每日抢答送出5ETM币04.“日拱一卒”:本周知识点为全节点钱包、SPV——轻钱包、中心化钱包等7个名词,后台回复“日拱一卒”可查看本周合辑 “ETM世界”:每日在小程序签到可领取1积分,邀请1个好友可获2积分社群签到:每日在ETM社群签到可获1积分,积分可兑换相应ETM奖励“百里挑一”:在公众号后台回复“早茶”,收获不定期惊喜一周动态等你“出名”——全球有奖中文名征集活动进入评选、公示阶段 ETM评委会从453个中文名投稿中选出10个Pick中文名进行社区投票,今日公布投票排行以及最终采用中文名,详情见今日首条图文。 项目黄皮书收尾 黄皮书撰写与排版已完成,文稿正在印刷中 ...

June 11, 2019 · 1 min · jiezi

EnTanMoETM项目周报5月17日5月23日

项目进展Highlight:ETM 通过神荼科技全面安全审计 经过一个多月的全面审计工作,神荼科技于本周交付相关安全审计测试报告,给出初步整改建议。 在报告中,ETM 项目安全级别较高,无高、中风险级别漏洞,仅有 8 项一般风险级别的低强度问题,其中部分已在近期更新中得到修复。剩余问题也已反馈到研发部门,将在近期得到解决并进一步与神荼科技沟通,进行二次审计。 ETM-Core 优化交易转发逻辑,缓解大交易量下网络压力,已完成 85%etm-vm 性能优化,提升侧链交易效率,已完成 85%etm-Core 资产发行功能,已完成 25%核心代码阶段性梳理,已完成 20%ETM-Module 矿机 GUI 客户端,已完成 70%矿机增加节点状态查看与管理,已提交矿机一键部署脚本新增引导配置,已完成 75%第三方钱包接口,已完成 js、python、go 语言版本,开始持续性测试ETM-Mobile ETM 钱包移动端研发,已完成 15%ETM-Web WebSite 新增资讯版块日常更新,已上线WebSite SEO 代码部分,已完成 90%Wallet v1.5 全面支持离线签名,交易全程私钥不联网,用户隐私更安全,已完成95%社区论坛建设,已完成相关设计内容ETM-Doc GitHub 项目文档更新,跟进最新版本,已完成 95%官网资讯与开发者文档国际化工作,已完成并提交更新ETM-Other 委托神荼科技进行全面安全审计,已交付运营进展社群数据 官方微信社群数量:200+,活跃率 66%官方微信社群人数:52000+官方微信客服好友:7500+,较上周增长 7.2%官方电报群人数:52000+官方微博关注人数:11000+,较上周增长10%官方微信公众号关注人数:1600+运营数据 官方微信公众号发布 6 篇图文官方微博发布 17 条微博,阅读总量 2.15万在金色财经、共享财经、一本区块链、币乎、CSDN、简书、大鱼号、百家号、头条号、知乎号、企鹅号等各内容平台发布文章社群活动 “日拱一卒”:本周知识点为热钱包、钱包地址、助记词、密码、哈希值等7个名词,后台回复“日拱一卒”查看本周合辑“ETM世界”:每日在小程序签到可领取1积分,邀请1个好友可获2积分“圆桌派”话题讨论:# 中美贸易战与数字货币暴涨背后有啥关系?#5·20活动:开展520「三行情书」有奖征集活动,后台留言你给TA的三行情书,小墨从中抽取三位“情话王”发放奖励“百里挑一”:每日在公众号后台回复“早茶”,收获不定期惊喜“Momo答题”:微博每日抢答送出5ETM币一周动态ETM登上区块链头部媒体星球日报头条,引起广泛关注 5月22日,《两位诺奖得主加持、解决“不可能三角”的UPoS机制来了》一文登上星球日报头条,引起区块链媒体及行业广泛关注 文章深度剖析了ETM的UPoS机制、两位诺奖与ETM的理念的契合,以及创始团队对中本聪精神的追随,将ETM的理念、内涵、团队文化诠释得淋漓尽致,为大众认识ETM打开了一扇窗。 此外,文章被36氪、金色财经、链闻ChianNews、币乎等二十余家综合媒体、区块链媒体及自媒体转发;En-Tan-Mo作为底层公链被区块链导航网站Block123收录进项目库并公开发布。 ETM中文名正式确定为「以太墨」 ETM全球中文名征集活动圆满结束,活动奖励均已发放。 黄皮书撰写与排版已完成,刊印样本已出。 关注ETM更多信息ETM官方网站 www.entanmo.io 官方电报群 https://t.me/entanmo 微信公众号 ETM科学院 官方微博 @En-Tan-Mo

June 11, 2019 · 1 min · jiezi

EnTanMoETM项目周报5月3日5月9日

项目进展Highlight:共识机制UPoS v1.5 稳定性全面提升 etm-Core v1.0 的基本建设全面完成,实现了 UPoS v1.0 共识机制:由具有时间增益、抑制权益、不确定化特性的 DPoS 与改进的 PoW+ 构成。同时加入了优选机制、分红机制、混沌排序等独有功能。经过三次全球公测,在稳定性方面已达到主网上线标准。 共识机制是区块链项目的灵魂所在,etm-Core 中的 UPoS 是创造性的混合机制,更是专为区块链设计的共识机制。它保障了区块的正确性,一旦交易确认并上链,就无法撤消或取消。同时,具有诸多特性的 UPoS 真正做到了源于大众而服务于大众(点击查看:什么是UPoS?)。 在此基础上,研发团队将进一步改进 UPoS,在 UPoS v1.5 中加入一种恢复/回退机制,能极大提升共识机制与主网的稳定性。由此,在发生节点故障、网络故障或数据库错误等极端情况时,主网都能够快速恢复。 ETM-Core 优化回退机制,降低资源占用,已提交,UPoS 1.5 进入最后测试阶段02.P2P 网络优化,增加节点状态管理,已提交 03.优化交易转发逻辑,缓解大交易量下网络压力,已完成65% etm-vm 性能优化,提升侧链交易效率,已完成 65%05.etm-Core 资产发行功能研发启动,包括「发行商注册」、「资产注册」、「资产发行」、「资产转账」等功能 ETM-Module 矿机 GUI 客户端,已完成 40%02.矿机增加节点状态查看与管理,已完成 70% 03.矿机一键部署脚本新增引导配置,已完成 48% 接口自动化测试框架,已部署05.提供第三方钱包接口,已提交 ETM-Mobile ETM 钱包移动端开始研发,已完成 8%ETM-Web WebSite 新增资讯版块日常更新,已上线02.WebSite SEO 代码部分,已完成80% 03.Wallet v1.5 新界面与结构优化,已完成90% Wallet v1.5 新增帮助与提示,已完成 70%05.社区论坛项目启动,加速社区建设 ETM-Doc GitHub 项目文档更新,跟进最新版本,已完成 65%02.官网资讯与开发者文档国际化工作,已完成80% ETM-Other 委托神荼科技进行全面安全审计,已完成 90%运营进展社群数据 ...

June 11, 2019 · 1 min · jiezi

EnTanMo项目周报4月19日4月25日

项目进展ETM-Core 优化回退机制,降低资源占用,已完成 95% 开始稳定性测试02.P2P 网络优化,增加节点状态管理,已完成 90% 优化交易转发逻辑,缓解大交易量下网络压力,已完成 65%etm-vm 性能优化,提升侧链交易效率,已完成65%ETM-Module 矿机 GUI 客户端,已完成 35%02.矿机增加节点状态查看与管理,已完成 60% 矿机一键部署脚本新增引导配置,已完成 45%接口自动化测试框架,已完成 90%05.提供第三方钱包接口,已完成 90%,开始功能测试 ETM-Mobile ETM 钱包移动端已完成技术选型02.ETM 钱包移动端开始研发,已完成5% ETM-Web WebSite 新增资讯版块日常更新,已上线02.ETM-tools 基于 webUI 的开发测试工具,已上线(内部使用) 03.WebSite SEO 代码部分,已完成 50% Wallet v1.5 新界面与结构优化,已完成 30%05.Wallet v1.5 新增帮助页面,已完成 50% 06.开发者中心网站前期预研 ETM-Doc GitHub 项目文档更新,跟进最新版本,已完成 65%02.官网资讯与开发者文档国际化工作,已完成 30% ETM-Other 委托神荼科技进行全面安全审计,已完成 80%委托慢雾科技进行智能合约审计,所有安全功能均已通过测试运营进展社群数据 官方微信社群数量:200+,活跃率 62%官方微信社群人数:52000+官方微信客服好友:5900+,较上周增长 1.73%官方电报群人数:41000+官方微博关注人数:10000+官方微信公众号关注人数:1000+运营数据 官方微信公众号发布 3 篇图文官方微博发布12 条微博,阅读总量 1.44万在巴比特、共享财经、一本区块链、简书、大鱼号、百家号、头条号、知乎号、企鹅号等各内容平台发布文章社群活动 “日拱一卒”:本周知识点为挖矿、矿工、矿池、公有链、私有链等7个名词,后台回复“日拱一卒”查看本周合辑“ETM世界”:每日在小程序签到可领取1积分,邀请1个好友可获2积分“圆桌派”话题讨论:# 澳本聪人设崩塌,其代币该不该被下架?#征集活动:4月24日发布ETM中文名有奖征集活动“百里挑一”:每日在公众号后台回复“早茶”,收获不定期惊喜“极限挑战”:微信社群百日签到活动“Momo答题”:微博每日抢答送礼微博抽奖:转发中文名征集活动的微博,抽取3名幸运儿发放现金奖励一周动态等你“出名”——全球有奖中文名征集活动启动 ETM开启全球中文名征集活动,入围者将获得丰厚奖品,并有机会参加ETM相关主题活动 ETM出席币安、火币线下活动 ETM作为受邀团队,参加4月20日币安武汉线下见面会和4月22日火币全球行武汉站等活动 项目黄皮书收尾 黄皮书撰写与排版已完成,刊印设计工作进入最后阶段 关注ETM更多信息ETM官方网站 www.entanmo.io ...

June 11, 2019 · 1 min · jiezi

献礼6181700集前端教程免费看

一年一度“618”,岁岁年年狂剁手。随着网购时代的到来,越来越多的剁手节让大家谜一样的沉浸其中,无法自拔,什么618、双十一、双十二、双旦等等年前定下的攒钱目标还没开始就要宣告结束这就是人生不得不承认的事实 然而比618来得更猝不及防的是各大电商的营销文案一个比一个精彩一个比一个诱惑 所谓清空购物车一时爽,事后剁手火葬场小妙深知购物狂+剁手党的疯狂也深知这样一个“节日”对自媒体人来说意味着什么当然是拼文案拼营销拼姿势啊反正,钱是越花越少的经验是越攒越多的精彩文案给你摆在这这个手你剁不剁? 小妙作为剁手大军的一员,深深了解大家的纠结与痛苦而我今年就不一样了,不但不剁手,还可以免费学到知识 免费看?免费?是的,你没看错,真的免费!!! 即日起,注册妙味视频平台的新用户,即可获得价值239元包含1700+集的前端优质视频教程的7天观看权限无论你是在学布局还是在学小程序,亦或是在学Vue、react,这里应有尽有,爱学习的你,还没心动么,心动了的话就赶快行动起来吧 活动详情见海报:

June 11, 2019 · 1 min · jiezi

HTML5-离线缓存

离线缓存applicationCache 第一次加载后将数据缓存,如果没有清除缓存,下一次没有网络也能加载。使用1. 使用 manifest 属性,引入 .appcache 文件 每个指定了 manifest 的页面在用户对其访问时都会被缓存。如果未指定 manifest 属性,则页面不会被缓存(除非在 manifest 文件中直接指定了该页面)manifest 文件的 建议 的文件扩展名是:.appcache<!DOCTYPE html><html lang="en" manifest="demo.appcache"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> </body></html>2. 编写 demo.appcache 文件 CACHE MANIFEST 必须的,下面写需要缓存的文件,将在首次下载后进行缓存NETWORK: 下面的文件永远不会被缓存,且离线时是不可用的可以使用星号来指示所有其他资源/文件都需要因特网连接 NETWORK:*FALLBACK: 如果无法建立因特网连接,则用 "offline.html" 替代 /html5/ 目录中的所有文件,第一个 url 是资源,第二个是替补CACHE MANIFESTlogo.pngmain.jsNETWORK:index.cssFALLBACK: # 访问失败后 重定向/html5/ /404.html目前为止就实现了离线缓存 缓存状态 window.applicationCache.status 查看缓存的当前状态 0 == UNCACHED === 未缓存1 == IDLE === 空闲(缓存为最新状态)2 == CHECKING === 检查中3 == DOWNLOADING === 下载中4 == UPDATEREADY === 更新就绪5 == OBSOLETE === 缓存过期相关方法 1. applicationCache.update() 主动更新缓存 ...

June 11, 2019 · 1 min · jiezi

ETM项目周报3月22日3月28日

项目进展新增: 01.官网新增资讯版块,待测试并完善内容后上线 02.Wallet 新增投票分红收益展示 改进: 01.修订分红策略、新增分红收益字段 (1)50%给投中入选矿工的投票人,依入选矿工数量分成 101 份后,每名矿工的投票人按票数比例分配。 (2)剩下的50%,累积一轮后随机选一名入选矿工,该矿工的投票人按票数比例分配。 02.完善了 GitHub 项目相关 Readme 文档 完成: 01.Developer WebSite 1.0 的建设全部完成,并已正式上线 运营进展社群数据 01.ETM官方中文社群人数52249 02.ETM官方电报人数41548 03.ETM官方微博粉丝量10855 04.ETM微信公众号粉丝量 800(上线四天) 运营数据 01.官方微信公众号发布3 篇图文 截至推文前,单篇阅读量最高达1925 02.官方微博更新17 条微博 截至推文前,累计阅读量达1.65 万 03.在百家号、头条号、知乎等内容平台发布文章 社群活动 01.“入门挑战”答题有礼(ETM社群注册新玩法) 02.“极限挑战”微信社群百日签到有礼 03.“圆桌派”社区话题讨论#IEO翻红,你怎么看# 04.“Momo答题”微博每日上线 05.“极客挑战”微信社群知识抢答 一周动态黄皮书已经在设计制作阶段 3月,ETM黄皮书被提上日程,目前黄皮书正在筹备中,已完成科学、技术等板块内容,正在进行英文版本的梳理。 微信公众号ETM科学院上线 3月25日,新公众号 「ETM科学院」 正式上线,首篇推文《给中本聪的一封信》引起社区强烈反响,图文转化率高达2.375。 关注ETM更多信息ETM官方网站 www.entanmo.io 官方电报群 https://t.me/entanmo 微信公众号 ETM区科学院 官方微博 @En-Tan-Mo

June 11, 2019 · 1 min · jiezi

vue的事件冒泡

什么是事件冒泡?先说冒泡,我们都知道水中有气泡的时候,气泡会从水底往上升,由深往浅的。但是水在上升的过程中会经历不同的深度的水。那么我们再来解释一下什么是事件冒泡,如果属性浏览器原理的同学就知道,页面是由文档流(即dom树组成的),当我们在一个时间触发的时候,这个事件就像这个气泡一样,从dom树的底层,一层一层的往上面传递,一直传递到dom的根节点,如果子元素和父级元素触发的是相同事件的时候,当子元素被触发的时候父元素也会被触发冒泡机制,这就是冒泡的基本原理。 在不同的内核浏览器中,冒泡是不一样的 IE<11: div => body => html => document 在其他内核中:div => body =>html => window 注意:在JavaScript中,并非所有的事件都可以冒泡,像:blur、unload、load等事件就不能冒泡 示例代码:Html <div id="app"> <div id="father"> <div id="child"> 我是子元素 </div> 我是父级元素 </div> </div>css #app{ width: 500px; height: 500px; margin: 200px auto; background-color: #f5f5f5; border:2px solid #dddddd; } #father{ width: 400px; height: 400px; background-color: rgb(168, 125, 125); text-align: center; color:red; } #child{ width: 200px; height: 200px; background-color: #fff; color:blue; }js var father = document.getElementById('father');var child = document.getElementById('child');father.addEventListener("click", function () { console.log('我是父级元素')}, false)child.addEventListener("click", function () { console.log('我是子集元素')}, false) ...

June 11, 2019 · 2 min · jiezi

告别单机linux面板的臃肿使用云端轻平台运维

时间进入2019年,linux服务器市场现在使用的还是各个企业或有能力的站长,对于linux服务器很多小白站长是不敢搞的,不懂代码操作,习惯里windows下界面操作,都很担心使用linux系统不会操作可麻烦,这点我要讲一下,window服务器最不好的一点就是界面化,因为会浪费服务器大量的资源,本来服务器安装linux服务器版,没有界面消耗内存等,可以同时让1000个人访问服务器,可你安装了windows系统只能让600人访问网站,再多的人系统吃不消了。针对于windows这个消耗内存大bug,linux系统为啥领导大型服务器市场份额,就是因为把没必要的资源给了界面,这样本来服务器可以干一件事,现在只能干半件事。所以企业和技术站长都采用linux服务器,尤其是centos 7.6 系统,是消耗资源最好,功能最好的linux服务器,像阿里云、华为云、百度云、腾讯云等默认都是centos系统,这是因为程序员都知道哪个好,肯定主动推送。说完服务器系统,都知道要选linux,但对于远端linux服务器如何管理,如何操作这点,很多人想到了linux面板,对于很对站长想用linux系统是都会了解到linux面板。最早的linux面板是为了让不懂代码的小白站长,能够实现一键搭建web环境,建站而来的,多以市场上诞生了很多国内的单机linux面板。慢慢用户发现,不只是使用linux面板,还需要安全,不然服务器就是一层窗户纸,由于插件工具越来越多,linux面板本来是解决服务器轻量级使用的,现在单机版linux面板必须要在服务器上安装一个网站,再安装各种插件工具,一大堆东西,才能够使用,这就违背了当初linux面板的初衷,是轻量级便捷化。完完全全的软件功能了,现在大环境云端下轻量级设计理念,显然单机版linux面板已经可以淘汰了。现在市场上出现了云端版linux面板,旗鱼云梯这个品牌,能够让服务器和云端平台加密链接,所有功能页面插件等都安装在云端,你的服务器只需要和云端平台链接,就可以直接使用这些工具,让运维网站可以实现批量化,而不是只能管理一台主机。由于旗鱼云梯的集群化批量化功能,让云端linux面板变得可能,让个人站长能够使用这种平台化方式来管理自己的服务器。大大减少了站长对于运维价格高,管理难度大,尤其安全防护方面,云端版通过大数据可以拦截攻击,让服务器一直处于防火墙的保护下,避免服务器遭受黑客攻击等事故而宕机。总结:旗鱼云梯是现在linux系统下云服务器最好的管理平台,可以实现同时管理上百条服务器,批量管理批量操作,让运维服务器变得很简单。

June 11, 2019 · 1 min · jiezi

SEER新网页钱包UI设计第一版开发完毕

目前,SEER新网页钱包的UI设计工作已基本完成,目前已设计96个页面,随后的几天将向社区征集建议。 https://org.modao.cc/app/2da4... 目前的UI设计,不包括正在同步开发的赛事众筹功能,等主网赛事众筹功能上线以后,将进行相应前端的开发。目前赛事众筹功能正在测试网络(API节点:ws://192.144.171.138:8002 进行开发,但因为功能还在开发和调试,暂无法提供相应文档) UI定稿以后,将进入前端开发环节。 值得一提的是,此项工作有多位社区开发者的参与,感谢大家的支持。 1、在创建、备份钱包页面,出于安全考虑,开发者们还是采用了bin钱包备份+助记词备份的形式,但注册流程相比此前版本人性化许多,注册时提醒用户备份助记词,以提醒用户此账号和币比等DAPP账号的通用。2、 作为SEER核心之一的预测市场板块,将抛弃此前前端产品中以平台(房主)作为入口的不人性化设计,直接在首页中列出全网所有房间,并依据参与度、标签、类型等元素分类,方便大家找到自己感兴趣的主题。3、 房间详情页,增加了最近参加该房间预测的用户的参与情况,以及派奖等信息。4、 创建房间页提供了高级模式,会自动生成一个识别码,同时创建同一主题的多种玩法,前端根据识别码把多个房间组合在一起,例如北京VS天津,可以同时开设胜负、大小球、净胜球等玩法,集中预测各种可能性,提高开设者的工作效率。5、 账户总览页提供了用户钱包首页的功能,方便用户一目了然自己的各种资产、保证金、抵押品,以及已参与的预测等信息。6、在我参与/创建的预测页面,可以查看自己参与预测的情况,并方便的输入结果。7、 在预言机输入结果页面,不仅展示相关房间描述、选项,还附有预言机奖励等信息,方便预言机用户判断自己的输入是否合算。此后可以设立一些奖励活动,鼓励大家作为预言机为爱好者开设的房间输入结果并获得输入结果的回报,建立并活跃预言机社区。说到底就是培养用户黏性,让大家可以“薅羊毛”,当然输入的同时也会为社区创造价值,让预测更加“去中心化”。8、 在预言机页面,将开发预言机提醒功能。预言机用户可以设置提醒参数,当符合设定的房间即将结束时,用户会收到提醒,点击链接直接跳转到上面的输入结果页面。9、因为此前的产品中,平台的概念太“高大上”,容易让向开设房间的用户望而却步,以为要“平台”级的用户才能开设房间,在此版本中,开发者们把“平台”的描述更接地气了,以“交保证金”代称。10、 创建见证人页面加入了生成密钥对的功能,让用户可以直接在网页钱包生成密钥对和完成见证人所有操作,而完全不用依靠命令行钱包。这样持有很多SEER的用户也可以更方便的成为主力见证人或候选见证人,通过锁定持有的SEER竞选见证人并获得出块收益和抵押利息。11、 区块浏览器对区块链项目是十分重要的,是普通用户查询链上交易的重要渠道。SEER钱包一直集成了区块浏览器,而新版网页钱包将把内置区块浏览器做的更加完善。12、 例如,TXID功能。别小看这一长串hash,区块数据里是不会记录这些信息的,甚至TXID会在区块生产或被确认前产生,目前链上的参与预测等操作只是对应到区块,而区块里面可能有多个交易,当一个区块里包含了几百条交易的时候,要找自己的那个操作会找疯的。而TXID需要通过一致的算法来额外计算,才能保证例如交易所等第三方网关产生的TXID和区块浏览器生成的TXID是一样的,并通过API服务供网页钱包调用。13、 SEER内置去中心化交易所,会按照中心化交易所的操作体验,让大家能在SEER主网上方便的进行各种资产的兑换。欢迎大家移步SEER爱好者论坛,对UI设计提出宝贵意见: https://forum.seerchain.org/t...

June 11, 2019 · 1 min · jiezi

ETM上线首日暴涨220-最高涨幅达250

OK Jumpstart三期项目En-Tan-Mo(简称ETM)于今日15:00正式开放交易,并上线ETM/USDK、ETM/USDT交易对。截至20:00,较预约销售价格涨了220%,最高涨幅达250%。   据悉,En-Tan-Mo(ETM)是一个打通金融、能源、商业、生活等生态环境的新一代价值互联网平台,首次提出并实现SHD完备性的基础公链项目,团队由两位诺贝尔奖得主担任高级顾问,其他成员均为来自海外顶尖高校通信、数学、计算机等方面的专家和学者。  

June 10, 2019 · 1 min · jiezi

iconfont在react中完整使用教程

hello,各位小伙伴们,很久没写文章了。突然要自己搭建项目了,项目中对于阿里巴巴iconfont的使用,大家都清楚吗? 第一步:将图标加入购物车 第二步:将图标下载到本地,将如下文件放置在react项目中assets目录下 第三步:导入iconfont.css到项目目录,鄙人踩坑点在此。查阅部分文件,找到相关资料,发现是在纯html页面中导入是完全OK的。<link rel="stylesheet" type="text/css" href="iconfont.css">但是请注意,咱们将静态资源放置在src目录下,public中的index.html不可采用。于是,正确做法如下:在src文件下的index.js或者app.js等文件中写入如下语句即可。import './assets/fonts/iconfont.css'; 第四步:介绍使用方法 unicode: <i className="iconfont">&#xe72e;</i>font-class:<i class="iconfont icon-gouwuche"></i>symbol:待我研究去吧。。。备注:如果发现页面没有更新,可以重启一下服务。以上就是关于iconfont的介绍了,大家可以踊跃查阅资料,在此希望能够给到小伙伴们一些帮助呀!

June 10, 2019 · 1 min · jiezi

react中antd的引用完整流程介绍

今天的第二篇小记来了。 antd官网中有关于react中导入antd的介绍 https://ant.design/docs/react/use-with-create-react-app-cn但是却没有得到我们想要的效果。 错误如下:The "injectBabelPlugin" helper has been deprecated as of v2.0 解决办法如下:https://github.com/ant-design...。 但是我还是把流程写下吧,需要自取哟! 第一步:npm i antd --save 第二步:npm i react-app-rewired -D 后更改package.json文件 /* package.json */"scripts": {- "start": "react-scripts start",+ "start": "react-app-rewired start",- "build": "react-scripts build",+ "build": "react-app-rewired build",- "test": "react-scripts test",+ "test": "react-app-rewired test",}第三步:安装按需加载插件 npm install babel-plugin-import 第四步: npm install customize-cra --save 第四步:在项目根目录创建一个 config-overrides.js 用于修改默认配置。 const { override, fixBabelImports } = require("customize-cra"); module.exports = override( fixBabelImports("babel-plugin-import", { libraryName: "antd", style: "css" }) );以上流程介绍完毕,antd官网关于这方面的介绍需要更新啦。。。如果需要less等支持,还是需要参考官网的,请大家积极查阅相关资料啦!本文就不做叙述啦,嘻嘻嘻! ...

June 10, 2019 · 1 min · jiezi

轮椅上的程序员夜店传说

2019年6月9号,星期天,晴,33度 今天的bug格外的难解 对面商店的小姐姐,依然是我不敢奢求的梦 我是小蝌蚪,一名低级前端程序员搬砖六年,一事无成 经过这些年的努力拼搏,终于向那些曾经看不起我的人证明 ,他们是对的 今晚又加班到了十二点,身心俱疲公司楼下的夜店又响起了战歌我就像一个小丑,穿梭在灯红酒绿的街路边的美女和豪车都与我无关因为程序员不允许沾染世俗的烟火 话还没说完就对一家夜店着了迷因为店门口站着一排黑丝大长腿一直在加班,我好像三个月没见过异性了吧不得不感慨,穿着黑丝的她们,真的好美黑丝对程序员来说是一种圣物,同时也是个迷黑丝套在头上,你就是劫匪黑丝套在腿上,妳就是神明同样是一双人类的腿,加了一层黑布,就能对程序狗产生致命的吸引力上帝在设计男人的时候,还是留下了bug 就在这时,天边突然响起了师傅的佛音:“小蝌蚪,美色是你职业道路上的绊脚石还在意女人,你就成为不了江湖第一的程序员 ”我瞬间恢复了神智,赶紧把头扭开狠狠扇了自己一巴掌我果然不是一个好的程序员一个真正厉害的程序员应该是心无旁骛 ,只有代码 心中有码,到哪里都是比基尼 真的很感谢师傅每次受到黑丝的诱惑师傅的教诲总是能帮助我走出困境,打败心魔 我的师傅是一个高级前端工程师离至尊级程序员就差一步在一次修炼中,为了突破到至尊级凌晨一点钟,孤身一人进入夜店后来就再也没有回来消失前一小时他在微信工作群留下了两个字:“黑丝” 从那以后,黑丝就变成了我心中的魔鬼,既着迷又害怕导致敲代码的技术一直没法突破 可是那天晚上,师傅在夜店到底发生了什么呢看了一下时间,晚上12点59分夜店就在面前,穿着黑丝的妖孽就站在我旁边天时地利人和我不入地狱,谁入地狱 背起自己的大书包,一瘸一拐的进了店平时习惯了昏暗的办公室,见不得光被夜店里的聚光灯一照,差点亮瞎了我的狗眼 深夜中的男男女女,在舞池中央群魔乱舞我的身上穿着公司十周年发的屎黄色战服在舞池里蹦起来就好像一个小儿麻痹与周围的环境格格不入 随着音乐摇到一半 突然看到夜店后排蜷缩着一个面黄肌瘦的男人小蝌蚪:师傅!是你吗师傅:小。。。小蝌蚪?你为什么会在这里小蝌蚪:师傅~!我找了你好多年,终于找到你了。快跟我回去师傅:走不了,我的灵魂中毒了。小蝌蚪:中毒?师傅:我要找到一个女孩,她是我唯一的解药小蝌蚪:怎样才能找到她师傅:她的代号叫“黑丝”,传说中的夜店女皇,她藏的很深,几乎没有人能找到她。小蝌蚪:她是个什么样的女人师傅:黑丝是一个极度危险的女人,所有被她撩过的男人,都会瞬间沉沦,然后日渐消瘦,思念至死。师傅:三年前,她亲吻了我一下,然后、然后、然后。。。。。。黑丝、黑丝、黑丝、黑丝、黑丝、黑丝、黑丝、黑丝、黑丝、黑丝。。。话还没说完,师傅就像毒瘾发作疯狂的抓自己头发,口里不断重复着“黑丝”两个字师傅身边的一群男人,也是灵魂被操控,不断念着“黑丝”两个字 我终于意识到问题的严重性。哭着告诉自己不要慌,一定要找到黑丝,把师傅救出来。可是,这茫茫人海,黑丝在哪呢?看来只能用程序员的神技------心眼心眼是程序员的一个高阶技巧程序员平时在找bug的时候,几十万行代码如果用眼睛去找,那是会瞎的一旦你启用了心眼,就能一目千行瞬间找到几十万行代码里的bug所在 心眼讲究用心去感受周围的环境,而不是用眼睛我闭上眼睛,气运丹田,周围吵杂的环境逐渐安静了下来用心眼感受身边每个人的细微蠕动寻找每一个穿黑丝的女人 最终,锁定人群中的九点钟方向那里坐着一个清纯型妹纸 我很震惊,以为黑丝一定是个妖艳贱货型女子没想到她却是一副清纯学生的样子别的女人在夜店都是穿着黑丝上身的穿着尽可能妖娆和邪魅可她却只穿一件简单的白色短袖和一件粉红色超短裙与周围意乱情迷的环境形成强烈反差给人一种“出淤泥而不染,濯清涟而不妖”的既视感 她白皙的皮肤上没有任何的装饰和打扮将我们程序员敲代码的“the less is more”原则诠释到极致 一个真正的高富帅,就偏偏喜欢这样清纯简单的女人因为高富帅已经厌倦了庸脂俗粉和妖艳贱货鲁迅曾点评过男女之间的情爱秘籍:“喜欢一个女孩:若她涉世未深,就带她看尽人间繁华;若她心已沧桑,就带她坐旋转木马。 喜欢一个男孩:若他情窦初开,你就宽衣解带;若他阅人无数,你就灶边炉台.” 显然,黑丝她只是看起来纯洁,其实她不纯洁,她只是利用了纯洁 一个真正的高手,她的外表看起来永远都不像一个高手清纯只是她的障眼法我们程序员善于突破思维的禁锢,用辩证的思想看问题不被问题的表象所迷惑,透过现象看本质。这是一个优秀的程序员必须具备的品质。 我的心眼感受到了她娇羞清纯的容颜下藏着一颗高傲冷艳的野心既然已找到了黑丝,我要怎么撩她呢首先必须要让自己帅起来 小蝌蚪急中生智,在屎黄色的公司战服上,用圆珠笔画了一个“supreme”,逼格瞬间爆炸 用口水湿润头发,将低沉的发型上扬露出额头,眼镜一摘,混入舞池 进入蹦迪的舞池后,不会摇摆怎么办?师傅曾说过:“如果你在夜店里不会摇摆,那就用脸在天上画一个<粪>字”平时刻苦学习的知识今天终于派上了用场 头在摇摆的时候,手应该怎么晃动呢?师傅又曾经说过:“如果在夜店里你的手不知道怎么晃,那就想象天花板是一个巨大的键盘,将手举过头顶动用单身三十年的手速,对着天空一顿盲敲想象自己在用代码敲一条龙那样你就是夜店里最厉害的仔” 为了让自己看起来更像一个夜店高手小蝌蚪举一反三,融会贯通佯装自己是一个会rap的饶舌歌手小蝌蚪一面摇晃着脑袋一面将程序员的加班战歌《no-sex(无性繁殖)》大声唱了出来歌词大意如下:“来 跟我一起念药药 切克闹 哟哟 嘿V够 i don't need sex, the code 发可 me everyday大声跟我一起唱 i don't need sex, the code 发可 me everyday发可!发可!me!me!eve!ry!Day!”小蝌蚪一边rap一边嘲讽旁边的年轻人,不懂得什么才是真正的music 旁边的年轻人听不懂小蝌蚪在唱什么,他们也不敢问反正一切听不懂的,都一定是比他们厉害的东西 才用不到半小时,小蝌蚪已经是整个夜店里最狂的仔所有女人都为之倾倒。 经过一个小时的摇摆,小蝌蚪体力不支瘫软在吧台上把汗一擦,背挺直,假装自己一副人帅腰好的样子 小蝌蚪的骚操作,终于引起了黑丝的注意黑丝主动坐到了小蝌蚪身边这一切都在意料之中,就好像代码的运行流程,每一行都胸有成竹 桌上早已为黑丝点了杯名叫“烈焰红唇”的高端鸡尾酒小蝌蚪在杯壁上用口红写了首情诗 “ ...

June 10, 2019 · 1 min · jiezi

开发者进阶之路-UIBPlayer-视频播放demo分享

本文出自APICloud官方论坛 UIBPlayer 封装了百度云播放器 SDK。本模块带有UI方案,打开后为一个具有完整功能的播放器界面。百度云播放器突破 Android、iOS 平台对视频格式的限制,支持目前所有主流的媒体格式(mp4、avi、wmv、flv、mkv、mov、 rmvb 等)。 模块亮点介绍: 自带UI,用户只需自己设计图标,调整参数。具有双击播放、暂停,手势滑动改变播放进度、屏幕亮度和音量的功能iOS 支持横竖屏自动切换(设置中打开竖屏锁定)顶部、底部按钮播放时自动隐藏,点击唤起。使用前先去百度开放平台获取AccessKey,配置到config.xml文件中,否则会出现闪退等异常。参考模块文档说明。直接调用open接口即可打开播放器。代码如下:var UIBPlayer = api.require('UIBPlayer'); UIBPlayer.open({ rect: { x: 0, y: 0, w: api.winWidth, h: 300 }, videoScalingMode:"FIT_WITH_CROPPING", path: 'http://wvideo.spriteapp.cn/video/2016/0328/56f8ec01d9bfe_wpd.mp4', autoPlay: false, enableLooping: true, pauseInBackground: true, coverImg: 'widget://image/uibplayer/cover.png', styles: { head: { bg: 'rgba(161,161,161,0.5)', height: 44, marginTop: api.safeArea.top, hide: false, backBtn: { size: 30, backImg: 'widget://image/uibplayer/back.png', marginLeft: 5 }, titleLabel: { title: '蝙蝠侠', size: 20, color: '#fff', width: 200, numberLines: 1, leftMargin: 5, backgroundColor: 'rgba(0,0,0,0)' }, customButtons: [{ w: 30, h: 30, rightMagin: 5, img: 'widget://image/uibplayer/setting.png', imgSelected: 'widget://image/uibplayer/settinged.png', }, { w: 30, h: 30, rightMagin: 5, img: 'widget://image/uibplayer/mess.png', imgSelected: 'widget://image/uibplayer/messed.png', }] }, foot: { bg: 'rgba(161,161,161,0.5)', height: 44, marginBottom: 0, hide: false, playBtn: { size: 44, playImg: 'widget://image/uibplayer/play.png', pauseImg: 'widget://image/uibplayer/pause.png', marginLeft: 0 }, currentTimeLabel: { textSize: 14, textColor: "#FFF", marginLeft: 5 }, seekBar: { sliderImg: 'widget://image/uibplayer/slide.png', progressColor: '#696969', progressSelectedColor: '#333333', marginLeft: 5, marginRight: 5 }, totalTimeLabel: { textSize: 14, textColor: "#FFF", marginRight: 5 }, fullScreenBtn: { size: 30, img: 'widget://image/uibplayer/unfullscreen.png', fullScreenImg: 'widget://image/uibplayer/fullscreen.png', marginRight: 10 } } }, fixedOn: api.frameName, fixed: false });复制代码 ...

June 10, 2019 · 1 min · jiezi

初识混合内容

无意发现官网中的一个页面报了如图所示的错误,Google出的内容是跟混合内容有关,于是我就这样偶然的知道了混合内容这么一个玩意,作为一个靠技术吃饭的人(此处内心有点小慌张,嘻嘻),接下来当然是要查看文档了解它了(特此感谢https://developers.google.com...) 1、它是谁?当一个页面开始是用https请求,但是页面里的其它内容(比如:图片、视频、样式表,脚本文件等)有用http请求的,这时这个页面就出现了混合内容,使用https加载的内容比http加载的内容安全,现代浏览器会针对此类型的内容显示警告,以向用户表明此页面包含不安全的资源。 2、它带来的问题 混合内容会降低网站的安全性和用户体验

June 10, 2019 · 1 min · jiezi

Git常用命令小结

Git版本库原理Git的版本库里存了很多东西,其中最重要的就是称为stage(或者叫index)的暂存区,还有Git为我们自动创建的第一个分支master,以及指向master的一个指针叫HEAD。工作区有一个隐藏目录.git,这个不算工作区,而是Git的版本库 创建版本库:#创建文件$ mkdir myapp#进入文件$ cd myapp#初始化代码仓库$ git init#把需要提交的所有修改放到暂存区(Stage)$ git add file#提交所有文件#$ git add . #提交所有.js格式文件#$ git add *.js#强制添加#$ git add -f file#提交代码$ git commit -m "commit info"查看#查看历史记录,git log命令显示从最近到最远的提交日志$ git log#查看分支合并图$ git log --graph#Git提供了一个命令git reflog用来记录你的每一次命令:$ git reflog#git status命令用于显示工作目录和暂存区的状态。使用此命令能看到那些修改被暂存到了, 哪些没有, 哪些文件没有被Git tracked到。git status不显示已经commit到项目历史中去的信息。$ git status#当暂存区中没有文件时,git diff比较的是,工作区中的文件与上次提交到版本库中的文件。#当暂存区中有文件时,git diff则比较的是,当前工作区中的文件与暂存区中的文$ git diff#比较工作区中的文件与版本库中文件的差异。HEAD指向的是版本库中的当前版本,而file指的是当前工作区中的文件。$ git diff HEAD -- file版本回退:#Git必须知道当前版本是哪个版本,在Git中,用HEAD表示当前版本,上一个版本就是HEAD^,上上一个版本就是HEAD^^,当回退版本较早时可以写成HEAD~100。#版本回退$ git reset --hard HEAD^#取消回退,commitId为你想要回到的未来版本号$ git re**set** --hard commitId撤销修改命令git checkout ——file 把文件在工作区的修改全部撤销,这里有两种情况: * 一种是file修改后还没有被放到暂存区,现在,撤销修改就回到和版本库一模一样的状态;* 一种是file已经添加到暂存区后,又作了修改,现在,撤销修改就回到添加到暂存区后的状态。#文件在工作区的修改全部撤销$ git checkout --file删除文件命令git rm用于从版本库删除一个文件。如果一个文件已经被提交到版本库,那么你永远不用担心误删,但是要小心,你只能恢复文件到最新版本,你会丢失最近一次提交后你修改的内容。 ...

June 10, 2019 · 1 min · jiezi

StepByStep一周面试题深入解析-周刊-03

关于【Step-By-Step】Step-By-Step (点击进入项目) 是我于 2019-05-20 开始的一个项目,每个工作日发布一道面试题。每个周末我会仔细阅读大家的答案,整理最一份较优答案出来,因本人水平有限,有误的地方,大家及时指正。 如果想 加群 学习,关注公众号,添加我为好友,我拉你进群。 本周面试题一览:什么是XSS攻击,XSS 攻击可以分为哪几类?我们如何防范XSS攻击?如何隐藏页面中的某个元素?浏览器事件代理机制的原理是什么?setTimeout 倒计时为什么会出现误差?11. 什么是XSS攻击,XSS攻击可以分为哪几类?我们如何防范XSS攻击?1. XSS攻击XSS(Cross-Site Scripting,跨站脚本攻击)是一种代码注入攻击。攻击者在目标网站上注入恶意代码,当被攻击者登陆网站时就会执行这些恶意代码,这些脚本可以读取 cookie,session tokens,或者其它敏感的网站信息,对用户进行钓鱼欺诈,甚至发起蠕虫攻击等。 XSS 的本质是:恶意代码未经过滤,与网站正常的代码混在一起;浏览器无法分辨哪些脚本是可信的,导致恶意脚本被执行。由于直接在用户的终端执行,恶意代码能够直接获取用户的信息,利用这些信息冒充用户向网站发起攻击者定义的请求。 XSS分类根据攻击的来源,XSS攻击可以分为存储型(持久性)、反射型(非持久型)和DOM型三种。下面我们来详细了解一下这三种XSS攻击: 1.1 反射型XSS当用户点击一个恶意链接,或者提交一个表单,或者进入一个恶意网站时,注入脚本进入被攻击者的网站。Web服务器将注入脚本,比如一个错误信息,搜索结果等,未进行过滤直接返回到用户的浏览器上。 反射型 XSS 的攻击步骤:攻击者构造出特殊的 URL,其中包含恶意代码。用户打开带有恶意代码的 URL 时,网站服务端将恶意代码从 URL 中取出,拼接在 HTML 中返回给浏览器。用户浏览器接收到响应后解析执行,混在其中的恶意代码也被执行。恶意代码窃取用户数据并发送到攻击者的网站,或者冒充用户的行为,调用目标网站接口执行攻击者指定的操作。反射型 XSS 漏洞常见于通过 URL 传递参数的功能,如网站搜索、跳转等。由于需要用户主动打开恶意的 URL 才能生效,攻击者往往会结合多种手段诱导用户点击。 POST 的内容也可以触发反射型 XSS,只不过其触发条件比较苛刻(需要构造表单提交页面,并引导用户点击),所以非常少见。 如果不希望被前端拿到cookie,后端可以设置 httpOnly (不过这不是 XSS攻击 的解决方案,只能降低受损范围) 如何防范反射型XSS攻击对字符串进行编码。 对url的查询参数进行转义后再输出到页面。 app.get('/welcome', function(req, res) { //对查询参数进行编码,避免反射型 XSS攻击 res.send(`${encodeURIComponent(req.query.type)}`); });1.2 DOM 型 XSSDOM 型 XSS 攻击,实际上就是前端 JavaScript 代码不够严谨,把不可信的内容插入到了页面。在使用 .innerHTML、.outerHTML、.appendChild、document.write()等API时要特别小心,不要把不可信的数据作为 HTML 插到页面上,尽量使用 .innerText、.textContent、.setAttribute() 等。 ...

June 10, 2019 · 3 min · jiezi