WooCommerce-43发布-WP站长

<!-- wp:paragraph --><p>WooCommerce 4.3现已公开公布!它自2020年4月以来始终在开发中,其外围已更新,来自24个贡献者的272次提交。</p><!-- /wp:paragraph --> <!-- wp:paragraph --><p>这是一个主要发行版,这意味着所有内容都与先前版本向后兼容。</p><!-- /wp:paragraph --> <!-- wp:paragraph --><p>与平常一样,建议您创立网站的备份,并确保主题和插件在更新之前兼容。您能够查看此更新指南以理解更多信息。</p><!-- /wp:paragraph --> <!-- wp:heading --><h2>WooCommerce 4.3中有什么新性能?</h2><!-- /wp:heading --> <!-- wp:paragraph --><p>与所有主要版本一样,咱们为您带来了几个咱们要强调的新性能:</p><!-- /wp:paragraph --> <!-- wp:heading {"level":3} --><h3>新首页体验</h3><!-- /wp:heading --> <!-- wp:paragraph --><p>咱们为您提供了一个全新的主页,以提供更加集中的体验,从而使商店治理更加轻松。它仅蕴含3个最重要的我的项目,供商家浏览:</p><!-- /wp:paragraph --> <!-- wp:list --><ul><li>收件箱音讯,</li><li>常见商店指标的疾速概述,以及</li><li>指向最罕用设置的快捷方式</li></ul><!-- /wp:list --> <!-- wp:image {"align":"center","id":6745,"linkDestination":"custom"} --><div class="wp-block-image"><figure class="aligncenter"><img src="https://woocommerce.files.wordpress.com/2020/06/home-screen.png?w=580" alt="WooCommerce 4.3公布!" class="wp-image-6745"/></figure></div><!-- /wp:image --> <!-- wp:paragraph --><p>咱们很快乐在新首页上听到您的反馈和想法,心愿咱们能够将其置于WooCommerce体验的核心地位。</p><!-- /wp:paragraph --> <!-- wp:paragraph --><p>默认状况下,新主页可用于所有新客户。如果要从晚期版本升级,则能够通过WooCommerce>设置>高级>性能>主屏幕将其关上。</p><!-- /wp:paragraph --> <!-- wp:paragraph --><p>您还能够查看波及主屏幕性能的新文档局部。</p><!-- /wp:paragraph --> <!-- wp:heading {"level":3} --><h3>Block块更新</h3><!-- /wp:heading --> ...

July 11, 2020 · 1 min · jiezi

H5之外部浏览器唤起微信分享

最近在做一个手机站,要求点击分享能够间接关上微信分享进来。而不是jiathis,share分享这种的点击进去二维码。在网上看了很多,都说APP能唤起微信,手机网页实现不了。也找了很多都不能间接唤起微信。 总结进去一个能够间接唤起微信的。适应手机qq浏览器和uc浏览器。 上面上代码,把这些间接放到要转发的页面里就能够了: html局部: <script src="mshare.js"></script>//引进mshare.js<button data-mshare="0">点击弹出原生分享面板</button><button data-mshare="1">点击触发朋友圈分享</button><button data-mshare="2">点击触发发送给微信敌人</button>js局部: <script>var mshare = new mShare({ title: 'Lorem ipsum dolor sit.', url: 'http://m.ly.com', desc: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quaerat inventore minima voluptates.', img: 'http://placehold.it/150x150'});$('button').click(function () { // 1 ==> 朋友圈 2 ==> 敌人 0 ==> 间接弹出原生 mshare.init(+$(this).data('mshare'));});</script>上面是mshare.js的代码分享,把这些代码新建一个js文件放进去,而后在页面中引进就ok了。亨达返佣https://www.fx61.com/brokerli... /** * 此插件次要作用是在UC和QQ两个支流浏览器 * 下面触发微信分享到朋友圈或发送给敌人的性能 */'use strict';var UA = navigator.appVersion; /** * 是否是 UC 浏览器 */var uc = UA.split('UCBrowser/').length > 1 ? 1 : 0; /** * 判断 qq 浏览器 * 然而qq浏览器分高下版本 * 2 代表高版本 * 1 代表低版本 */var qq = UA.split('MQQBrowser/').length > 1 ? 2 : 0; /** * 是否是微信 */var wx = /micromessenger/i.test(UA); /** * 浏览器版本 */var qqVs = qq ? parseFloat(UA.split('MQQBrowser/')[1]) : 0;var ucVs = uc ? parseFloat(UA.split('UCBrowser/')[1]) : 0; /** * 获取操作系统信息 iPhone(1) Android(2) */var os = (function () { var ua = navigator.userAgent; if (/iphone|ipod/i.test(ua)) { return 1; } else if (/android/i.test(ua)) { return 2; } else { return 0; }}()); /** * qq浏览器上面 是否加载好了相应的api文件 */var qqBridgeLoaded = false; // 进一步细化版本和平台判断if ((qq && qqVs < 5.4 && os == 1) || (qq && qqVs < 5.3 && os == 1)) { qq = 0;} else { if (qq && qqVs < 5.4 && os == 2) { qq = 1; } else { if (uc && ((ucVs < 10.2 && os == 1) || (ucVs < 9.7 && os == 2))) { uc = 0; } }}/** * qq浏览器上面 依据不同版本 加载对应的bridge * @method loadqqApi * @param {Function} cb 回调函数 */function loadqqApi(cb) { // qq == 0 if (!qq) { return cb && cb(); } var script = document.createElement('script'); script.src = (+qq === 1) ? '//3gimg.qq.com/html5/js/qb.js' : '//jsapi.qq.com/get?api=app.share'; /** * 须要等加载过 qq 的 bridge 脚本之后 * 再去初始化分享组件 */ script.onload = function () { cb && cb(); }; document.body.appendChild(script);}/** * UC浏览器分享 * @method ucShare */function ucShare(config) { // ['title', 'content', 'url', 'platform', 'disablePlatform', 'source', 'htmlID'] // 对于platform // ios: kWeixin || kWeixinFriend; // android: WechatFriends || WechatTimeline // uc 分享会间接应用截图 var platform = ''; var shareInfo = null; // 指定了分享类型 if (config.type) { if (os == 2) { platform = config.type == 1 ? 'WechatTimeline' : 'WechatFriends'; } else if (os == 1) { platform = config.type == 1 ? 'kWeixinFriend' : 'kWeixin'; } } shareInfo = [config.title, config.desc, config.url, platform, '', '', '']; // android if (window.ucweb) { ucweb.startRequest && ucweb.startRequest('shell.page_share', shareInfo); return; } if (window.ucbrowser) { ucbrowser.web_share && ucbrowser.web_share.apply(null, shareInfo); return; }}/** * qq 浏览器分享函数 * @method qqShare */function qqShare(config) { var type = config.type; //微信好友 1, 微信朋友圈 8 type = type ? ((type == 1) ? 8 : 1) : ''; var share = function () { var shareInfo = { 'url': config.url, 'title': config.title, 'description': config.desc, 'img_url': config.img, 'img_title': config.title, 'to_app': type, 'cus_txt': '' }; if (window.browser) { browser.app && browser.app.share(shareInfo); } else if (window.qb) { qb.share && qb.share(shareInfo); } }; if (qqBridgeLoaded) { share(); } else { loadqqApi(share); }}/** * 对外裸露的接口函数 * @method mShare * @param {Object} config 配置对象 */function mShare(config) { this.config = config; this.init = function (type) { if (typeof type != 'undefined') this.config.type = type; try { if (uc) { ucShare(this.config); } else if (qq && !wx) { qqShare(this.config); } } catch (e) {} }}// 预加载 qq bridgeloadqqApi(function () { qqBridgeLoaded = true;});if (typeof module === 'object' && module.exports) { module.exports = mShare;} else { window.mShare = mShare;}

July 10, 2020 · 3 min · jiezi

h5中video标签的使用

video标签参数参数值形容x5-video-player-typeh5-page在x5内核浏览器中(安卓的qq、微信),视频不脱离文档流webkit-playsinlinetrueios 10中设置能够让视频在小窗内播放playsinlinetrue视频在小窗内播放preloadautononemetaauto时,主动进行预加载,none时,不进行预加载,meta时,只载入元数据autoplayautoplay则视频在就绪后马上播放。looploop循环播放事件事件形容play播放视频pause暂停视频play事件管制视频播放,返回一个promise对象,可用于判断视频是否能播放let video=this.$refs.video[0]video.load()video.play().then(res=>{ 视频播放胜利回调}).catch(function(err) { 视频播放失败回调 Toast('该视频暂不反对播放');});非凡场景1. ios零碎的微信中,非click状况下,video.play()生效场景: 须要页面滑动到指定地位时播放视频,但视频播放失败起因: 可能微信做了某些解决,必须click事件内,video.play()才有成果解决办法:暂无2. 低版本的安卓(安卓7)中,多个video标签场景: 低版本的安卓零碎中,点击多个视频播放后会导致一些视频首帧置灰展现起因: 可能是内存问题解决办法: 只应用一个video标签,每次要播放时再加载视频

July 8, 2020 · 1 min · jiezi

HTML5开发动态音频图

概要本次我们会使用html5和js开发一个动态音频图用到的技术点:(1)js(2)canvas + audio(3)Web Audio API 实现方式:(1)首先对于界面实现的考虑,由于区块非常多,我们使用传统dom节点实现是非常困难的(会占用大量的电脑CPU)。在这里,我们考虑使用canvas进行渲染(2)前端中,我们遵循尽量少用js控制dom节点的原则。能用css3实现的特效,就不要用js实现。(因为js不是标记语言,而是脚本语言,与html5不是同一种语言。会浪费浏览器大量时间加载,造成浏览器性能的浪费)。因此,用js就少用dom,用dom就尽量用css。(3)通过Web Audio API在音频节点上进行音频操作(即实现音频可视化),流程图如下: 在图中,音频上下文提供了音频处理的一套系统方法。输入源指音乐文件,通过名称引入;效果就是对输入源进行加工,如制作音频图、音波图、3D环绕、低音音效等;输出就是把效果输出到耳机、扬声器等目的地。 canvas引入在当下,除了布局使用dom节点外,特效基本都是通过canvas实现了。canvas好处:(1)写特效非常强大,性能优(2)用于做游戏。由于flash将于2020年退役,现在的游戏开始转向用html5制作(3)前端渲染大数据,数据可视化,大屏数据展示 canvas流程:通过js创建画笔<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style type="text/css"> *{ margin: 0; /* 外边距为0,使canvas能够占满全屏 */ } #canvas{ background: linear-gradient( 135deg, rgb(142,132,133) 0%, rgb(230,132,110) 100% ); /*创建线性渐变图像*/ } </style></head><body> <canvas id="canvas" width="500" height="500"></canvas> <script> var cxt=canvas.getContext('2d');//创建了画笔 cxt.beginPath();//开始画 cxt.closePath();//画完了 cxt.fillStyle='#f2f'; cxt.arc(250,250,100,0,2*Math.PI,false); cxt.fill(); </script></body></html>在创建线性渐变图像时,若100%后边加“,”,谷歌便加载不出来;若不加,便能加载出来。但是不知道为何这里尤其注意js里canvas的流程,创建画笔-》开始画-》画完了-》补充颜色、形状信息。其中前三步都是套路,只有如何去画根据任务的不同,代码不同Web Audio APi流程<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title></head><body> <audio id="audio" src="mp3/1.mp3" controls></audio> <script> var oCtx=new AudioContext();//创建音频对象 var oAudio=document.querySelector('audio'); var audioSrc=oCtx.createMediaElementSource(oAudio); //给音频对象创建媒体源 var analyser=oCtx.createAnalyser();//创建分析机 audioSrc.connect(analyser);//把分析机连接到媒体源上 analyser.connect(oCtx.destination);//把分析机得到的结果和扬声器相连 </script></body></html>这里要注意的是,audio中的autoplay、js中的audio.play()已经失效(谷歌浏览器的安全策略:声音不能自动播放,必须在用户有了操作后才能播放)上述流程中少了最关键的一步:如何分析音频数据,这一步根据实现的任务不同,内容不同。但是其余的步骤都是一样的,满满的套路动态音频图的开发<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style type="text/css"> *{ margin: 0; } #canvas{ background:linear-gradient( 135deg, rgb(142,132,133) 0%, rgb(230,132,110) 100% ); } </style></head><body> <audio id="audio" src="mp3/1.mp3" controls></audio> <button type="button" onclick="play()"></button> <canvas id="canvas"></canvas> <script> //先引入canvas画笔的创建流程 var cCxt=canvas.getContext('2d');//创建2D画笔 cCxt.beginPath();//开始画 cCxt.closePath();//画完了 //设计画布的样式 //设置画布大小为整个屏幕 canvas.width=window.innerWidth; canvas.height=window.innerHeight; //设置线条的渐变颜色 var oW=canvas.width; var oH=canvas.height; var color=cCxt.createLinearGradient(oW/2,oH/2,oW/2,oH/2-100); color.addColorStop(0,'#000'); color.addColorStop(.5,'#069'); color.addColorStop(1,'#f6f'); function play(){ //先引入API函数,走完Web Audio API的流程 var oCtx=new AudioContext();//创建音频对象 var oAudio=document.querySelector('audio'); var audioSrc=oCtx.createMediaElementSource(oAudio);//为音频对象创建媒体源 var analyser=oCtx.createAnalyser();//为音频对象创建分析机 audioSrc.connect(analyser);//将分析机与媒体源连接 analyser.connect(oCtx.destination);//将分析机与扬声器相连接 var count=80;//音频条的条数 var voiceHeight=new Uint8Array(analyser.frequencyBinCount);//建立一个数据缓冲区(此时为空) setInterval(draw(analyser,voiceHeight,count),1000); oAudio.play(); } function draw(analyser,voiceHeight,count){ analyser.getByteFrequencyData(voiceHeight);//将当前频率数据传入到无符号字节数组中,进行实时连接 var step=Math.round(voiceHeight.length/count);//每隔step个数,取一个数组里的数 for(var i=0;i<count;i++){ var audioHeight=voiceHeight[step*i]; cCxt.fillStyle=color; cCxt.fillRect(oW/2+(i*10),oH/2,7,-audioHeight); cCxt.fillRect(oW/2-(i*10),oH/2,7,-audioHeight); } //console.log(voiceHeight); } </script></body></html>上边的代码是不可行的,找了一下午也没找出错误到底出在哪里...问题主要如下:(1)在谷歌浏览器中,显示歌在播放,但是没有声音。console.log(voiceHeight)即图中注释部分没有注释掉时,voiceHeight只出现一次,而不是1000ms出现一次。没有图像 ...

July 1, 2020 · 1 min · jiezi

多图上传兼容微信小程序只能单图上传-开发uniapp项目遇到的问题主H5微信小程序

Demo:uni-app template GitHub Address问题需求中,需要上传多张图片,但是微信小程序只能单图上传,多图上传只支持App、H5。 如果只能一张一张上传图片的话,用户体验相当差,我相信上传的用户,会疯的…… 思路对此官方文档也给出了解决方案,就是重复调用api uni.uploadFile 解决方法我使用了uni-app插件市场中luck-request插件(仿axios封装request网络请求库,支持拦截器以及task操作),对于uni.uploadFile,也有封装。 在此,我在api.js的文件中又定义封装了上传图片的方法。 // 上传图片,接口名称根据自己后端定义,此接口调用不通export const uploadToOss = (params) => axios.upload('/api/upload/xxx', { ...params, custom: { loading: true, loadingTitle: '正在上传...' }})UploadPic.vue <template> <view class="upload_box"> <view class="image_list"> <view class="image_item" v-for="(item, index) in files" :key="index"> <view class="icon iconfont iconshanchu" @click="removeItem(index)"></view> <image :src="item"></image> </view> <view class="upload" v-if="files.length < limit" @click="handleUpload"> <view class="icon iconfont iconshangchuan"></view> <text>{{ btnText }}</text> </view> </view> <view class="upload_tip" v-if="tip">{{ tip }}</view> </view></template><script>import { uploadToOss } from '@/api/http';export default { props: { // 提示信息 tip: { type: String, default: '' }, // 按钮文字 btnText: { type: String, default: '' }, // 最多限制张数,默认1张 limit: { type: Number, default: 1 }, // 图片类型,用于同个页面多个图片上传组件区分 imgType: { type: String, default: 'image' } }, data() { return { files: [] // 上传图片后的图片地址集合 }; }, methods: { /** * @description 删除图片 * @param {Number} index 图片所在索引值 */ removeItem(index) { this.files.splice(index, 1); this.sendMessage(); // 发送信息父组件 }, /** * @description 上传图片 * @param {String} url 图片临时地址 */ uploadImg(url) { return new Promise((resolve, reject) => { uploadToOss({ filePath: url, fileType: 'image', name: 'file', }).then(res => { if(res._OK) { resolve(res.data.data); } else { uni.showModal({ title: '提示', content: res.data.message || '上传失败' }) return new Promise.reject(res); } }).catch(err => { return new Promise.reject(err); }) }) }, /** * @description 遍历调用upload接口 * @param {Array} tempFilePaths uni.chooseImage选择图片后返回的临时图片地址集合 * @returns {Array} arr 异步调用upload接口返回的图片服务器上的地址集合 */ async uploads(tempFilePaths) { let arr = []; for(let i = 0; i < tempFilePaths.length; i++) { arr[i] = await this.uploadImg(tempFilePaths[i]); } return arr; }, /** * @description 上传图片 */ handleUpload() { let _this = this; uni.chooseImage({ count: _this.limit, async success(chooseImageRes) { // 选择图片后,立即调用图片上传的接口,es6的await必须被async包含。 let files = await _this.uploads(chooseImageRes.tempFilePaths); _this.files = [..._this.files, ...files]; _this.sendMessage(); // 发送信息父组件 } }); }, /** * @description 发送信息给父组件 */ sendMessage() { this.$emit('on-change', { files: this.files, imgType: this.imgType }); } }};</script><style lang="scss" scoped>.upload_box { .upload { width: 120rpx; height: 120rpx; border: 2rpx solid #d9d9d9; font-size: 24rpx; color: #999999; display: flex; justify-content: center; flex-direction: column; align-items: center; margin-bottom: 20rpx; .iconfont { margin-bottom: 8rpx; } } .image_list { display: flex; flex-wrap: wrap; .image_item { position: relative; width: 120rpx; height: 120rpx; margin: 0 20rpx 20rpx 0; z-index: 1; image { width: 120rpx; height: 120rpx; } .iconfont { color: #ff0000; font-size: 30rpx; position: absolute; z-index: 10; right: 0; top: 0; } } }}.upload_tip { color: #999999; font-size: 24rpx; margin-top: -10rpx;}</style>总结该多图上传组件的交互跟拓展性还不够好,但基本满足了目前产品的需求,之后还是会持续迭代更新的,也希望大家多多提意见???????????? ...

June 29, 2020 · 2 min · jiezi

HTML5CSS3知识总结

愿你被整个世界温柔以待 新增语义化标签header:头部标签nav:导航标签article:文章内容标签section:块级标签aside:侧边栏标签footer:底部标签注意: 语义化标签主要针对于搜索引擎的可以在界面使用多次的,主要适用于移动端开发在IE9中,需要把这些元素转换为块级元素(很重要)新增input表单 ????这个新增的表单属性,在实际开发中是运用的比较广的,需要掌握: 代码示例: CSS3新增属性伪类(伪类选择器)伪类:同一个标签,根据其不同的种状态,有不同的样式。这就叫做“伪类”。伪类用冒号来表示。 比如div是属于box类,这一点很明确,就是属于box类。但是a属于什么类?不明确。因为需要看用户点击前是什么状态,点击后是什么状态。所以,就叫做“伪类”。 静态伪类和动态伪类伪类选择器分为两种。 (1)静态伪类:只能用于超链接的样式。如下: :link 超链接点击之前:visited 链接被访问过之后PS:以上两种样式,只能用于超链接。 (2)动态伪类:针对所有标签都适用的样式。如下: :hover “悬停”:鼠标放到标签上的时候:active “激活”: 鼠标点击标签,但是不松手时。:focus 是某个标签获得焦点时的样式(比如某个输入框获得焦点)PS:以上三种样式,只能用于超链接。 超链接a标签超链接的四种状态a标签有4种伪类(即对应四种状态),要求背诵。如下: :link “链接”:超链接点击之前:visited “访问过的”:链接被访问过之后:hover “悬停”:鼠标放到标签上的时候:active “激活”: 鼠标点击标签,但是不松手时。对应的代码如下:(不带注释) a:link{ color:red; } a:visited{ color:orange; } a:hover{ color:green; } a:active{ color:black; }对应的代码如下:(带注释) /*让超链接点击之前是红色*/ a:link{ color:red; } /*让超链接点击之后是绿色*/ a:visited{ color:orange; } /*鼠标悬停,放到标签上的时候*/ a:hover{ color:green; } /*鼠标点击链接,但是不松手的时候*/ a:active{ color:black;记住,在css中,这四种状态必须按照固定的顺序写: a:link 、a:visited 、a:hover 、a:active如果不按照顺序,那么将失效。“爱恨准则”:love hate。必须先爱,后恨。 看一下这四种状态的动图效果: 超链接的美化问:既然a{}定义了超链的属性,和a:link{}定义了超链点击之前的属性,那这两个有啥区别呢? 答: a{}和a:link{}的区别: a{}定义的样式针对所有的超链接(包括锚点)a:link{}定义的样式针对所有写了href属性的超链接(不包括锚点)超链接a标签在使用的时候,比较难。因为不仅仅要控制a这个盒子,也要控制它的伪类。 ...

June 28, 2020 · 2 min · jiezi

学习笔记HTML入门基础一

1.文本格式合并单元格colspan(横向合并)rowspan(纵向合并)input元素的多种形态,如 文本 密码 单选 按钮等type属性来定义<form action="url地址" method="get/post" name="表单名称"><p>文本</p>用户名:<input type="text" name="username">密码:<input type="password" name="password">单选:<input tyype="radio" name="sex" value="nan">男<input tyype="radio" name="sex" value="nv">女多选:<input type="checkbox" name="n">吃饭<input type="checkbox" name="n">睡觉重置:<input type="reset" name="">提交:<input type="submit" name=""> input的属性:只读:readonly禁用:disabled默认选:checked提示文本:placehoder输入光标显示:autofocus 2.映入、文件引入、框架<select size="2"> <option>苹果</option><option>西瓜</option><option>南瓜</option></select> size:出现下拉框 disable:不可以选 multiple:多选 selected:默认选<textarea rows="4" cols="5" maxlength="5">rows行数 cols:输入可见宽度 maxlength:输入最大字符数 网页<a href="http://www.baidu.com"> 链接</a> 文档

June 27, 2020 · 1 min · jiezi

如何理解HTML5语义化的

以前的html结构,就是 DIV + CSS,代码很难理解,为了改变这种这种状况,提出了让HTML语义化。 例如:段落用 p 标签,标题用 h 系列标签。 优点: 更省代码:更少的HTML代码。 更清晰的DOM结构,有利于书写css和js;更有利于SEO:可以提高搜索引擎的有效爬取,提高网站的流量;可读性:如果不幸网站的CSS样式丢失,清晰的结构依然使你的页面可读性较高;互用性:语义化的HTML代码,让你的团队维护更轻松。

June 16, 2020 · 1 min · jiezi

2020最新微信域名防封技术打破谣言

<!-- /\* Font Definitions \*/ @font-face {font-family:宋体; panose-1:2 1 6 0 3 1 1 1 1 1; mso-font-alt:SimSun; mso-font-charset:134; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:3 680460288 22 0 262145 0;} @font-face {font-family:"Cambria Math"; panose-1:2 4 5 3 5 4 6 3 2 4; mso-font-charset:1; mso-generic-font-family:roman; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:0 0 0 0 0 0;} @font-face {font-family:微软雅黑; panose-1:2 11 5 3 2 2 4 2 2 4; mso-font-charset:134; mso-generic-font-family:swiss; mso-font-pitch:variable; mso-font-signature:-2147483001 672087122 22 0 262175 0;} @font-face {font-family:Tahoma; panose-1:2 11 6 4 3 5 4 4 2 4; mso-font-charset:0; mso-generic-font-family:swiss; mso-font-pitch:variable; mso-font-signature:-520081665 -1073717157 41 0 66047 0;} @font-face {font-family:Consolas; panose-1:2 11 6 9 2 2 4 3 2 4; mso-font-charset:0; mso-generic-font-family:modern; mso-font-pitch:fixed; mso-font-signature:-520092929 1073806591 9 0 415 0;} @font-face {font-family:"\\@微软雅黑"; panose-1:2 11 5 3 2 2 4 2 2 4; mso-font-charset:134; mso-generic-font-family:swiss; mso-font-pitch:variable; mso-font-signature:-2147483001 672087122 22 0 262175 0;} @font-face {font-family:"\\@宋体"; panose-1:2 1 6 0 3 1 1 1 1 1; mso-font-charset:134; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:3 680460288 22 0 262145 0;} /\* Style Definitions \*/ p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-unhide:no; mso-style-qformat:yes; mso-style-parent:""; margin-top:0cm; margin-right:0cm; margin-bottom:10.0pt; margin-left:0cm; mso-pagination:widow-orphan; layout-grid-mode:char; mso-layout-grid-align:none; font-size:11.0pt; font-family:"Tahoma","sans-serif"; mso-fareast-font-family:微软雅黑; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi;} span.hljs-number {mso-style-name:hljs-number; mso-style-unhide:no;} .MsoChpDefault {mso-style-type:export-only; mso-default-props:yes; font-size:11.0pt; mso-ansi-font-size:11.0pt; mso-fareast-font-family:微软雅黑; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi; mso-font-kerning:0pt;} .MsoPapDefault {mso-style-type:export-only; margin-bottom:10.0pt; line-height:11.0pt;} /\* Page Definitions \*/ @page {mso-page-border-surround-header:no; mso-page-border-surround-footer:no;} @page WordSection1 {size:595.3pt 841.9pt; margin:72.0pt 90.0pt 72.0pt 90.0pt; mso-header-margin:35.4pt; mso-footer-margin:35.4pt; mso-paper-source:0;} div.WordSection1 {page:WordSection1;} /\* List Definitions \*/ @list l0 {mso-list-id:279725072; mso-list-template-ids:-1797495592;} ol {margin-bottom:0cm;} ul {margin-bottom:0cm;} --> 2020最新微信域名防封技术打破谣言 ...

June 10, 2020 · 2 min · jiezi

Egret-536-正式发布大幅改进编译速度

各位开发者大家好, 我们今天正式发布 Egret 5.3.6 版本。Egret 5.3.6 仍然是一个抢先预览版,在这个版本中我们为各位开发者带来如下功能: JavaScript模块支持全新的 EuiCompiler运行时改进Inspector更新其中 JavaScript模块支持和EuiCompiler我们建议正在开发中尚未上线的项目使用,运行时以及 Inspector 更新所有项目均可使用。 JavaScript 模块支持,大幅改进编译速度(beta)这项技术我们率先使用在 EgretPro中,在这个版本我们将其移植到了 Egret 5.3 版本中,以保证尽可能多的存量开发者可以使用此功能。 在不支持模块的老式浏览器中,如果一个 JavaScript 文件要想给另外一个文件暴露出去一部分数据或者一个变量,那只能将它定义在全局的作用域下,并根据他们的依赖关系来决定加载顺序。 白鹭引擎构建管线中的 IncrementBuild 插件将会分析您的游戏逻辑依赖关系,并生成一个 manifest.json 文件,游戏在调试时会加载这个 manifest.json ,根据其中的脚本顺序逐个加载 JavaScript 代码。 这种方式带来的问题是,随着项目不断变大,IncrementBuild 插件的依赖关系检查会使游戏的编译速度会越来越慢,而 JavaScript 模块中,由于所有的依赖关系都是显式设置的,所以不存在此问题。 在 5.3.6 版本中,我们允许开发者使用 JavaScript模块,并提供了 webpack 打包器,它会将多个 JavaScript 模块文件打包为一个文件,使得其可以在不支持JavaScript模块的旧式浏览器上运行。 经过与白鹭合作的开发者抢先测试,将一个代码总量20万行,包含1700个 TypeScript 文件的重度挂机游戏项目迁移至 JavaScript Module 格式花费了一人一个星期时间,而这份投入非常的值得。经过开发者的实际反馈,在修改前编译速度大约为40秒一次,修改后仅需3-4秒,这可以为每位前端开发人员每天节省一小时的时间。 如果您对这项改动感兴趣,但是担心项目过大而感觉无从下手,可以联系白鹭引擎的官方技术支持(微信号:egretengine),寻求白鹭引擎官方团队的支持。 全新的 EuiCompiler (beta)在使用白鹭引擎开发的游戏中,UI以及相关逻辑是工作量最大的部分之一。在 Egret 5.3 系列版本中,我们决定全面改进 UI的 开发体验。为此我们先是发布了全新的 Egret UI Editor,并逐步迭代至1.9版本。除此之外,我们将在这个版本中为大家带来全新的 EuiCompiler。 EuiCompiler 是引擎中的 ExmlPlugin 的升级版本,他实现了和 ExmlPlugin 一致的功能,但是内部代码结构更加清晰并具备可扩展性。开发者可以扩展 EuiCompiler,为其加入符合自己游戏需求的定制功能,诸如:浮点数值擦除,国际化语言包、资源文件检查等。 ...

June 4, 2020 · 1 min · jiezi

庆祝DCloud手机引擎月活突破10亿

成绩,来自于开发者的支持和信任。 成绩,只属于历史。 未来,我们将继续认真、扎实的做好每件事,为开发者提供更好的产品和服务!

June 4, 2020 · 1 min · jiezi

CSS样式书写顺序和命名规范

书写顺序的意义减少浏览器reflow(回流),提升浏览器渲染dom的性能①:解析html构建dom树,解析css构建css树:将html解析成树形的数据结构,将css解析成树形的数据结构 ②:构建render树:DOM树和CSS树合并之后形成的render树。 ③:布局render树:有了render树,浏览器已经知道那些网页中有哪些节点,各个节点的css定义和以及它们的从属关系,从而计算出每个节点在屏幕中的位置。 ④:绘制render树:按照计算出来的规则,通过显卡把内容画在屏幕上。 css样式解析到显示至浏览器屏幕上就发生在②③④步骤,可见浏览器并不是一获取到css样式就立马开始解析而是根据css样式的书写顺序将之按照dom树的结构分布render样式,完成第②步,然后开始遍历每个树结点的css样式进行解析,此时的css样式的遍历顺序完全是按照之前的书写顺序。 优先级第一--定位属性: { display 规定元素应该生成的框的类型。 position 定位规定元素的定位类型。 float 规定框是否应该浮动。 left top right bottom overflow 规定当内容溢出元素框时发生的事情。 clear 清除 z-index 设置元素的堆叠顺序。 content 内容 list-style visibility 可见性/显示 } 优先级第二--自身属性: { width height border padding margin background} 优先级第三--文字样式: { font-family font-size font-style 规定文本的字体样式。 font-weight font-varient 规定是否以小型大写字母的字体显示文本 color } 优先级第四--文本属性: { text-align 规定文本的水平对齐方式。 vertical-align 设置元素的垂直对齐方式。 text-wrap 规定文本的换行规则。 text-transform 控制文本的大小写。 text-indent 规定文本块首行的缩进。 text-decoration 规定添加到文本的装饰效果。 letter-spacing 设置字符间距。 word-spacing 设置单词间距。 white-space 规定如何处理元素中的空白。 text-overflow 规定当文本溢出包含元素时发生的事情。 } 优先级第五--CC3中新增属性: { box-shadow 向方框添加一个或多个阴影。 cursor 规定要显示的光标的类型(形状)。 border-radius background:linear-gradient transform…… 向元素应用 2D 或 3D 转换。 }CSS代码的命名规范必须以字母开头命名选择器,这样可保证在所有浏览器下都能兼容;不允许单个字母的类选择器出现;不允许命名带有广告等英文的单词,例如ad,adv,adver,advertising,已防止该模块被浏览器当成垃圾广告过滤掉。任何文件的命名均如此。下划线 ’ _ ’ 禁止出现在class命名中,全小写,统一使用’-‘连字符.禁止驼峰命名 className见名知意CSS代码注意事项不要以完全没有语义的标签作为选择器,这会造成大面积污染简写CSS颜色属性值删除CSS属性值为0的单位删除无用CSS样式为单个CSS选择器或新申明开启新行避免过度简写 , .ico足够表示这是一个图标 , 而.i不代表任何意思使用有意义的名称,使用结构化或者作用目标相关的,而不是抽象的名称

June 3, 2020 · 1 min · jiezi

应用connectedreactrouter和reduxthunk打通react路由孤立

redux在我们开发过程中,很多时候,我们需要让组件共享某些数据,虽然可以通过组件传递数据实现数据共享,但是如果组件之间不是父子关系的话,数据传递是非常麻烦的,而且容易让代码的可读性降低,这时候我们就需要一个 state(状态)管理工具。常见的状态管理工具有 redux,mobx,这里选择 redux 进行状态管理。值得注意的是 React 16.3 带来了全新的Context API,我们也可以使用新的 Context API 做状态管理。Redux 是负责组织 state 的工具,但你也要考虑它是否适合你的情况。 在下面的场景中,引入 Redux 是比较明智的: 你有着相当大量的、随时间变化的数据你的 state 需要有一个单一可靠数据来源你觉得把所有 state 放在最顶层组件中已经无法满足需要了的确,这些场景很主观笼统。因为对于何时应该引入 Redux 这个问题,对于每个使用者和每个应用来说都是不同的。 对于 Redux 应该如何、何时使用的更多建议,请看: “您可能不需要Redux”Redux之道,第1部分-实现和意图Redux之道,第2部分-实践与哲学Redux 常见问题Redux 的创造者 Dan Abramov 又补充了一句 "只有遇到 React 实在解决不了的问题,你才需要 Redux 。" react-reduxreact-redux 提供Provider组件通过 context 的方式向应用注入 store,然后组件使用connect高阶方法获取并监听 store,然后根据 store state 和组件自身的 props 计算得到新的 props,注入该组件,并且可以通过监听 store,比较计算出的新 props 判断是否需要更新组件。 render( <Provider store={store}> <ConnectedRouter history={history}> <App /> </ConnectedRouter> </Provider>, document.getElementById('app'))复制代码整合 redux 到 react 应用合并 reducer在一个 react 应用中只有一个 store,组件通过调用 action 函数,传递数据到 reducer,reducer 根据数据更改对应的 state。但是随着应用复杂度的提升,reducer 也会变得越来越大,此时可以考虑将 reducer 拆分成多个单独的函数,拆分后的每个函数负责独立管理 state 的一部分。 ...

May 31, 2020 · 4 min · jiezi

canvas实现稍复杂的财务报表

<!DOCTYPE html><html> <head> <meta charset="UTF-8"> <title></title> <style> /*#oCan{ width: 1000px; height: 650px; }*/ </style> </head> <body style="background-color:#fff"> <canvas id="oCan" width="1600" height="650"> ~~~~</canvas> <script> var canvas = document.getElementById('oCan'); let dateArr = []; let years = 2016; let month = 0; var startX = 100; var startY = 600; var ctx = canvas.getContext('2d'); const salary = ['0','50k','100k','150k']; const data = [89815.85,65441.37,68983.43,80520.7,71360.8,71308.09,97843.1,74963.94,72430.98,81891.22,126140.22,57712.01,85631.15, 68464.57,73150.3,91573.05,81404.2,76903.97,71145.33,81884.51,90759.47,80811.97,76918.84,99999.56]; for(let i = 0 ; i<24;i++){ ++month; month = transFromMonthType(month); dateArr.push(years + '-' + month); if(month === 12){ years++; month = 0; } } function transFromMonthType (date) { if(date < 10){ return "0" + date + '' } return date } console.log(dateArr); //建立坐标系 function create(){ ctx.beginPath(); //轴线 ctx.moveTo(startX,startY); ctx.lineTo(startX,0); ctx.moveTo(startX,startY); ctx.lineTo(1600,startY); ctx.strokeStyle="#ccc"; ctx.stroke(); ctx.closePath(); ctx.beginPath(); //横线 ctx.moveTo(startX,400); ctx.lineTo(1600,400); ctx.moveTo(startX,200); ctx.lineTo(1600,200); ctx.moveTo(startX,0); ctx.lineTo(1600,0); ctx.strokeStyle="#ccc"; ctx.stroke(); ctx.closePath(); } //填充横纵坐标 function insert(){ var x = 100; var y = 600; var offsetY = 600 * (1-(data[0]/150000)); //绘制横坐标 ctx.moveTo(125,offsetY); ctx.fillText(data[0],110,offsetY-5); for(var i= 0; i <dateArr.length;i++){ ctx.textAlign="start"; ctx.fillText(dateArr[i],x,y+20); x += 50; if(i > 0){ offsetY = 600 * (1-(data[i]/150000)); ctx.textAlign="right"; ctx.fillText(data[i],x,offsetY-5); buildLineChart(x,offsetY); } } x = 100; y = 600; //绘制纵坐标 for(let j = 0 ;j < salary.length;j++){ ctx.textAlign = 'center'; ctx.fillText(salary[j],x-40,y); y -= 197;//偏差问题,如果设置200那么salary[3]的文本‘15k’就会被隐藏~~~~ } } //建立折线图 function buildLineChart(x,y){ let yet1 = y; ctx.lineTo(x-25,yet1); ctx.strokeStyle = "#3FA7DC"; ctx.stroke(); } insert(); create(); </script> </body></html>整体思路:1.设计y轴价格和x轴日期区间。注意:此demo的价格区间只限于0<=price<150000;超出的部分会被省略2.日期区间主要通过for循环将字符串日期推送到特定数组中,并调用特定函数来实现个位数加0操作。3.create方法主要用来创建x和y轴,以及特定数量的横线。利用ctx.beginPath();ctx.closePath();~~~~实现开辟以及结束一个工作区,在工作区给线条改颜色。4.调用insert()来设置和填充横纵坐标,以及通过moveTo()开始一条路径buildLineChart()方法用来绘制折线图,具体通过lineTo方法连接这些线,然后就呈现成折线。5.此文章难点还是在于lineTo的y轴坐标问题,要让他和金额以及距离canvas对象原点y轴比例的问题。即纵坐标offsetY = 600 * (1-(data[i]/150000)); ...

May 28, 2020 · 1 min · jiezi

HBY火币源系统开发

1、新的html5文件类型,HBY火币源系统开发(T:I8O-285I-O282 V林)仅需申明在html的第一行,即 <!DOCTYPE html> 2、图形元素 figure ,将<figure>与<figcaption>相结合,使图片标题与图片相搭配 1 <figure>2 <img src="img/2.jpg">3 <figcaption>4 <p>尝试一下</p>5 </figcaption>6 </figure> 3、不需要为链接和脚本标签添加类型的属性 <script src=”script.js”></script>4、h5中不需要用引号将属性包裹起来 <p class=one></p>5、使得内容可编辑。"contenteditable",它将允许用户编辑元素(包括他的子元素)内包含的任何文本内容。 6、增加电子邮件的输入类型 <input id=”email” name=”email” type=”email” /> 注意:opera只有在指定了name属性的前提下,才可以使用 7、占位符 paceholder=' ' <input name=”email” type=”email” placeholder=”xingyuyu27@163.com” />8、本地储存 local storage 9、语义性header和footer 在书写代码时可以使用<header>和<footer>标签注意:使用IE浏览器时,为了确保新的HTML5元素能够以块级元素正确显示,有必要将它们用下面的代码定义风格: header, footer, article, section, nav, menu, hgroup {display: block;} 就算如此,IE还是不知道这些元素究竟是什么,因而会无视这些格式,还需要用到下面的代码来解决这个问题: document.createElement(“article”); document.createElement(“footer”); document.createElement(“header”); document.createElement(“hgroup”); document.createElement(“nav”); document.createElement(“menu”); 11、群组标题(hgroup) 将标题之间的关系更好的表达出来,不影响文章整体纲要 <hgroup> <h1>标题</h1> <h2>副标题</h2></hgroup> 12、必要(require)属性 两种不同方式来声明这个属性:<input type=”text” name=”someInput” required>或者,更严谨:<input type=”text” name=”someInput” required=”required”>13、自动对焦(autofocus)属性 ...

November 5, 2019 · 1 min · jiezi

vue-input标签通用指令校验

移动端通常对于input标签要求输入有一些校验,vue的指令可达到完美校验的作用预期效果<input v-model="times" :data-last_value="lastTimes" v-int v-max="8" v-min="2" />属性data-last_value的值用来缓存用户输入框上一次失去焦点后输入的值,lastTimes是初始化的变量,后续不会再随意更改此值, v-model一定不要和data-last_value绑定同一个变量, 因为这样就起不到记住用户上一次输入值,并利用该值在校验不通过的情况下使用它 指令实现以下3个指令可完全独立使用校验整数 const util = { isNumber(str) { const num = Number(str); return Math.floor(num) === num; } }; directives: { int: { inserted: (el) => { let oldListener = el.onblur; el.onblur = (e) => { if (oldListener) { oldListener(e); } const blurValue = Number(el.value); // 用data-last_value属性值缓存上一次的值,以便恢复 const lastValue = el.getAttribute('data-last_value'); if (!util.isNumber(blurValue)) { util.toast('请输入数字'); el.value = lastValue; el.dispatchEvent(new Event('input')); } if (el.value === lastValue) return; // 更新上一次的值 el.setAttribute('data-last_value', el.value); } }, }, }校验最小值directives: { min: { inserted: (el, binding) => { const oldListener = el.onblur; el.onblur = (e) => { if (oldListener) { oldListener(e); } const blurValue = Number(el.value); const min = binding.value; if (blurValue < min) { // util.toast替换成自己业务的toast提示弹窗 util.toast(`最小值不能小于${min}`); el.value = min; el.dispatchEvent(new Event('input')); } const lastValue = el.getAttribute('data-last_value'); if (el.value === lastValue) return; // 更新上一次的值 el.setAttribute('data-last_value', el.value); } }, }, }校验最大值 directives: { max: { // 指令的定义 inserted: (el, binding) => { const oldListener = el.onblur; el.onblur = (e) => { if (oldListener) { oldListener(e); } const blurValue = Number(el.value); const max = binding.value; if (blurValue > max) { util.toast(`最大值不能大于${max}`); el.value = max; el.dispatchEvent(new Event('input')); } const lastValue = el.getAttribute('data-last_value'); if (el.value === lastValue) return; // 更新上一次的值 el.setAttribute('data-last_value', el.value); } }, }, }小小的校验指令没想到里面还有那么多细节~~~ ...

November 5, 2019 · 1 min · jiezi

解决h5华为浏览器底部栏兼容问题

现状产品需求是做一个带底部吸底支付的支付页面,如下图所示: 但是在部分(大多数)华为系统原生浏览器上会显示如下:下拉页面,就会发现,是因为华为浏览器下方的工具栏,遮住了支付组件,造成了这个样式兼容问题。也就是说,在华为浏览器中下方工具条的高度不算在浏览器自身bom高度上,而是算网页dom的一部分。更通俗地理解可以为,它就是个z-index:无限高;position:fixed;bottom:0的<div/>,坑啊! 那么随之而来的几种解决思路是:1.有没有那么一种设置,可以让这个浏览器组件像ios或vivo oppo等其它手机的浏览器一样正常算在其自身高度内? 经百度,并没有。但是有个x5内核强制“开启全屏”的meta设置: // 开启x5内核浏览器的全屏模式<meta name="x5-fullscreen" content="true">相对应的,还有个亲测也是可以的: // 据称是uc浏览器开始全屏模式,但是我在x5内核中测试也是可以的<meta name=”full-screen” content=”yes”>本来很开心地看到页面完美地如期展现。但是几番操作,发现这种方法不稳定,主要有两个问题: 全屏模式下,x5浏览器会自动开启一个悬浮按钮,来进行“全屏-非全屏”状态的切换。这个是设计图之外的东西,在一定程度上对设计图的实现造成了破坏,且会给用户带来迷茫感。全屏模式的保持并不稳定。在某些路由跳转时刻、某些布局下,会退出全屏模式,没有根治样式兼容性缺陷。比如上图中的支付页面的确样式正常了,但是点击支付跳转到“选择支付方式”页面时,就不知所以地退出了全屏模式,下方“立即支付”按钮,又被遮住了。2.处理交互障碍。也就是说,这个缺陷带来的问题是,用户在第一屏看不到支付渠道,且无法通过下拉显示(因为它不是不存在,而是被一个更高层的div盖住了),那么我们就把支付组件的padding-bottom增高: .pay-btn-container{ padding-bottom: 95px; // 因为95px是后面讲到的,在移动浏览器中实际算出的 // 距离差,所以不需要换算为rem,直接使用即可。}撑起下部被遮挡部分;或者将document的height增高,同样达到撑起被遮挡部分的作用。 document,.root{ height: calc(100vh + 95px);}但是这样带来的问题是,用户现在确实可以通过下拉页面,最终看到支付按钮了。但依旧不是在一屏以内。这种改进方式和产品、设计的初始预期出入较大,很容易被否掉,后期还是要改。且作为一名有良好“产品感”的前端设计师,本身应该也很难接受这种调整方案。 3.将非全屏模式下,底部工具栏占用的空间减掉,作为下方支付组件的bottom值。就是算出在“全屏和非全屏模式”下,由于底部虚拟工具栏的出现,而造成浏览器视窗的高度差。将其作为底部支付组件距离下方的距离值即可。这种解决方式主要有一点需要考虑:改虚拟工具栏,在多台设备上的高度是否统一。若不统一,那么此方法不可行,更难受的是,那么就面临着此题无解的尴尬局面。于是我找测试人员借来4台华为设备,通过计算发现高度几乎完全一致(长吁一口粗气),其值大概是95px,那么我们修改支付组件: .pay-btn-container{ position: fixed; bottom: 95px;}综合考虑三种方式,最终选择最后一种方式,他相对第一种比较稳定,相对第二种对交互侵入性最小,是目前最适合的答案。 但是因为x5内核并没有给出一个方法获取虚拟工具栏的实际高度,且发现其在多台设备上高度确有2px的差距,所以这点也算是隐患。 最后想说,x5真的巨坑,比u4还坑,不亏其“移动端IE6”的大名。腾讯在加入一些安全措施的同时,将本来很好用的webkit改得一团乱麻,严重影响它的可用性。最可恨的是,还没有完全文档,对开发者十分不友好。而那些将自己系统浏览器套用x5内核的“拿来者”也是不友好团队的簇拥。 最后附上一个x5内核坑汇总的链接,希望有用:《QQ浏览器X5内核问题汇总》,如有问题欢迎留言。

November 5, 2019 · 1 min · jiezi

docker安装AriaNg下载器

AriaNg是一个非常优秀的下载工具,基于aria2。个人感觉可以替代迅雷。 效果图: 代码:docker-compose.yml version: '3'services: ariang: image: wahyd4/aria2-ui:latest container_name: dapps-ariang ports: - "${ARIANG_HOST_PORT}:80" volumes: - ${ARIANG_DATA_DIR}:/data restart: always.env文件 # app infoAUTHOR_UID=10000000AUTHOR_NAME=kakaAPP_ID=ariangAPP_NAME=ariang高速下载器APP_INTRODUCTION=2倍迅雷下载速度APP_UPDATE_CONTENT=APP_VERSION=1.0.0APP_PORT=8011/ui# environment config fileSOURCE_DIR=./www# TimezoneTZ=Asia/Shanghai# environment configARIANG_HOST_PORT=8011ARIANG_DATA_DIR=./downloads对docker不太熟悉的同学,可以使用dapps应用商店,一键安装。 Dapps项目:使用

November 5, 2019 · 1 min · jiezi

NET-Core中使用OOM框架AutoMapper的使用介绍

(一)什么是OOM:OOM顾名思义,Object-Object-Mapping实体间相互转换,AutoMapper其意义在于帮助你无需手动的转换简单而又麻烦的实体间关系。 (二)AutoMapper是什么:AutoMapper是基于对象到对象约定的映射工具,常用于(但并不仅限制于)把复杂的对象模型转为DTO,一般用于ViewModel模式和跨 服务范畴。 (三)在.NET Core项目中如何使用它:1.通过Nuget安装AutoMapper到项目:Install-Package AutoMapper2.定义好Model类和DTO类:`//Model类public class ProjectEntity{ public int ID { get; set; }public string ProjectName { get; set; }public string ProjectImg { get; set; }public string ProjectCreateDate { get; set; }public List<ProjectTaskEntity> Tasks { get; set; }}` `//DTO类public class ProjectDto{ public int ProjectID { get; set; }public string ProjectName { get; set; }public string ProjectImg { get; set; }public string ProjectCreateDate { get; set; }public List<ProjectTaskDto> Tasks { get; set; }}` ...

November 4, 2019 · 1 min · jiezi

前端路由Hash与History模式

了解SPA现代前端项目多为单页Web应用(SPA),在单页Web应用中路由是其中的重要环节。SPA 是 single page web application 的简称,译为单页Web应用。 简单的说 SPA 就是一个WEB项目只有一个 HTML 页面,一旦页面加载完成,SPA 不会因为用户的操作而进行页面的重新加载或跳转。 取而代之的是利用 JS 动态的变换 HTML 的内容,从而来模拟多个视图间跳转。 前度路由简单的说,就是在保证只有一个 HTML 页面,且与用户交互时不刷新和跳转页面的同时,为 SPA 中的每个视图展示形式匹配一个特殊的 url。在刷新、前进、后退和SEO时均通过这个特殊的 url 来实现。我们需要实现下满两点: 改变 url 且不让浏览器像服务器发送请求。可以监听到 url 的变化可以在不刷新页面的前提下动态改变浏览器地址栏中的URL地址hash 模式和 history 模式,就是用来实现上面功能的 Hash模式在url后面加上#,如http://127.0.0.1:5500/前端路由/hash.html#/page1这个url后面的#/page1就是hash值 hash 值的变化不会导致浏览器像服务器发送请求location.hash可以获取hash值hashchange是hash值发生改变的调用的函数基于以上三点我们可以写一个路由实例 <!DOCTYPE html><html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta http-equiv="X-UA-Compatible" content="ie=edge" /> <title>Document</title> </head> <body> <ul> <li><a href="#/">/</a></li> <li><a href="#/page1">page1</a></li> <li><a href="#/page2">page2</a></li> </ul> <div class="content-div"></div> </body> <script> class RouterClass { constructor() { this.routes = {}; // 记录路径标识符对应的cb this.currentUrl = ""; // 记录hash只为方便执行cb window.addEventListener("load", () => this.render()); window.addEventListener("hashchange", () => this.render()); } /* 初始化 */ static init() { window.Router = new RouterClass(); } /* 注册路由和回调 */ route(path, cb) { this.routes[path] = cb || function() {}; } /* 记录当前hash,执行cb */ render() { this.currentUrl = window.location.hash.slice(1) || "/"; this.routes[this.currentUrl](); } } RouterClass.init(); const ContentDom = document.querySelector(".content-div"); const changeContent = content => (ContentDom.innerHTML = content); Router.route("/", () => changeContent("默认页面")); Router.route("/page1", () => changeContent("page1页面")); Router.route("/page2", () => changeContent("page2页面")); </script></html>History模式History 接口允许操作浏览器的曾经在标签页或者框架里访问的会话历史记录。可以参考下两篇文章对history的说明https://css-tricks.com/using-the-html5-history-api/https://developer.mozilla.org/zh-CN/docs/Web/API/History下面介绍在这个模式下需要用到的api ...

November 4, 2019 · 2 min · jiezi

使用Eclipse开发Web项目JSP-tomcat

1.使用Eclipse开发Web项目(JSP) tomcat 2.在Eclipse中创建的Web项目: 浏览器可以直接访问webContent中的文件 例如http://localhost:8080/MyJspProject/index1.jsp 其中的index1.jsp就在WebContent目录中; 但是WEB-INF中的文件 无法通过客户端(浏览器)直接访问,只能通过请求转发来访问 注意:并不是任何的内部跳转都能访问WEB-INF;原因是跳转有两种方式:请求转发、重定向 3.配置tomcat运行时环境 jsp <->Servlet a.将tomcat/lib中的servlet-api.jar加入项目的构建路径(只加一个) b.右键项目 -> Build Path -> Add library - Server Runtime(加一堆jar)【推荐】 4.部署tomcat 在servers面板新建一个tomcat实例,再在该实例中部署项目(右键-add) 注意:一般建议将eclipse中的tomcat与本地tomcat保持一致; 将eclipse中的tomcat设置为托管模式:【第一次】创建tomcat实例之后,双击,选择Server Location的第二个 5.统一字符集编码 a.编码分类: 设计jsp文件的编码(jsp文件中的pageEncodeing属性):jsp -> java 设置浏览器读取jsp文件的编码(jsp文件中content属性) 一般将上述设置成一致的编码,推荐使用UTF-8 b.文本编码: i.将整个Eclipse中的文件统一设置(以后的jsp编码都会utf-8)【推荐】 ii.设置某一项目(右键文件-properties) iii.设置单独文件 6.JSP的页面元素 HTML java代码(脚本Scriptlet) 指令 注释 a.脚本Scriptlet i. 1 <%2 局部变量、java语句3 %>ii. 1 <%!2 全局变量、定义方法3 %>iii. 1 <%=2 输出表达式3 %>修改web.xml、配置文件、java需要重启tomcat服务,但是如果修改Jsp/html/js/css代码不需要重启 注意:out.println()不能回车;要想回车:

November 4, 2019 · 1 min · jiezi

记一次大厂的面试过程

前言2019年6月中旬,实在厌倦了之前平平淡淡的工作和毫不起眼的薪资,不顾亲人的反对,毅然决然地决定只身前往沿海城市,想着找到一份更加具有挑战性的工作,来彻彻底底地重新打磨自己,同时去追求更好的薪资待遇。当然在此之前,自己每天下班后都会利用业余时间抓紧复习巩固刷题等等,大概从3月份开始的吧,持续了3个多月。而后从6月中旬面试一直到6月底,中间大概两个星期,其实我的学历和背景并不突出,但是我个人感觉可能是因为自己简历做的稍微还行(后面我可能会单独出一篇文章,来聊聊我做简历时的一点点心得),让大厂的HR能够多看几眼,中间面过的公司包括喜马拉雅、携程、哔哩哔哩、流利说、蜻蜓FM、爱回收等,陆陆续续拿到4,5个Offer吧,如今已经转正,所以在这里记录下之前的部分面试题,和大家一起分享交流。 正文1. 烈熊网络这家公司其实我也没有太了解过,是我前同事推荐的,说里面的薪资待遇不错,然后我当时也有空闲时间,所以就去试试了,虽然公司名气没有上面提到的公司大,但是他的面试题我觉得还是挺有分量的。1.1 请说出下面代码的执行顺序async function async1() { console.log(1); const result = await async2(); console.log(3);}async function async2() { console.log(2);}Promise.resolve().then(() => { console.log(4);});setTimeout(() => { console.log(5);});async1();console.log(6);我的回答是[1,2,6,4,3,5]。这道题目主要考对JS宏任务和微任务的理解程度,JS的事件循环中每个宏任务称为一个Tick(标记),在每个标记的末尾会追加一个微任务队列,一个宏任务执行完后会执行所有的微任务,直到队列清空。上题中我觉得稍微复杂点的在于async1函数,async1函数本身会返回一个Promise,同时await后面紧跟着async2函数返回的Promise,console.log(3)其实是在async2函数返回的Promise的then语句中执行的,then语句本身也会返回一个Promise然后追加到微任务队列中,所以在微任务队列中console.log(3)在console.log(4)后面,不太清楚的同学可以网上查下资料或者关注我的公众号「前端之境」,我们可以一起交流学习。 1.2 手动实现Promise,写出伪代码幸运的是在面试前刚好查阅了下这部分的资料,所以回答过程中还算得心应手,主要是需要遵循Promise/A+规范: (1) 一个promise必须具备三种状态(pending|fulfilled(resolved)|rejected),当处于pending状态时,可以转移到fulfilled(resolved)状态或rejected状态,处于fulfilled(resolved)状态或rejected状态时,状态不再可变; (2) 一个promise必须有then方法,then方法必须接受两个参数: // onFulfilled在状态由pending -> fulfilled(resolved) 时执行,参数为resolve()中传递的值// onRejected在状态由pending -> rejected 时执行,参数为reject()中传递的值promise.then(onFulfilled,onRejected)(3) then方法必须返回一个promise: promise2 = promise1.then(onFulfilled, onRejected);实现代码直接贴出来吧: 参考自:实现一个完美符合Promise/A+规范的Promisefunction myPromise(constructor){ let self=this; self.status="pending" //定义状态改变前的初始状态 self.value=undefined;//定义状态为resolved的时候的状态 self.reason=undefined;//定义状态为rejected的时候的状态 self.onFullfilledArray=[]; self.onRejectedArray=[]; function resolve(value){ if(self.status==="pending"){ self.value=value; self.status="resolved"; self.onFullfilledArray.forEach(function(f){ f(self.value); //如果状态从pending变为resolved, //那么就遍历执行里面的异步方法 }); } } function reject(reason){ if(self.status==="pending"){ self.reason=reason; self.status="rejected"; self.onRejectedArray.forEach(function(f){ f(self.reason); //如果状态从pending变为rejected, //那么就遍历执行里面的异步方法 }) } } //捕获构造异常 try{ constructor(resolve,reject); }catch(e){ reject(e); }}myPromise.prototype.then=function(onFullfilled,onRejected){ let self=this; let promise2; switch(self.status){ case "pending": promise2 = new myPromise(function(resolve,reject){ self.onFullfilledArray.push(function(){ setTimeout(function(){ try{ let temple=onFullfilled(self.value); resolvePromise(temple) }catch(e){ reject(e) //error catch } }) }); self.onRejectedArray.push(function(){ setTimeout(function(){ try{ let temple=onRejected(self.reason); resolvePromise(temple) }catch(e){ reject(e)// error catch } }) }); }) case "resolved": promise2=new myPromise(function(resolve,reject){ setTimeout(function(){ try{ let temple=onFullfilled(self.value); //将上次一then里面的方法传递进下一个Promise状态 resolvePromise(temple); }catch(e){ reject(e);//error catch } }) }) break; case "rejected": promise2=new myPromise(function(resolve,reject){ setTimeout(function(){ try{ let temple=onRejected(self.reason); //将then里面的方法传递到下一个Promise的状态里 resolvePromise(temple); }catch(e){ reject(e); } }) }) break; default: } return promise2;}function resolvePromise(promise,x,resolve,reject){ if(promise===x){ throw new TypeError("type error") } let isUsed; if(x!==null&&(typeof x==="object"||typeof x==="function")){ try{ let then=x.then; if(typeof then==="function"){ //是一个promise的情况 then.call(x,function(y){ if(isUsed)return; isUsed=true; resolvePromise(promise,y,resolve,reject); },function(e){ if(isUsed)return; isUsed=true; reject(e); }) }else{ //仅仅是一个函数或者是对象 resolve(x) } }catch(e){ if(isUsed)return; isUsed=true; reject(e); } }else{ //返回的基本类型,直接resolve resolve(x) }}1.3 请说出以下打印结果let a = {a: 10};let b = {b: 10};let obj = { a: 10};obj[b] = 20;console.log(obj[a]);我的回答是:20。这道题目主要考对JS数据类型的熟练度以及对ES6中属性名表达式的理解。在上题中obj[b] = 20的赋值操作后,obj其实已经变成了{a: 10, [object Object]: 20},这是因为如果属性名表达式是一个对象的话,那么默认情况下会自动将对象转为字符串[object Object],最后一步获取obj[a]时,a本身也是一个对象,所以会被转换为获取obj[object Object]也就是上一步赋值的20。 ...

November 3, 2019 · 6 min · jiezi

网易易盾再次获得年度内容安全优秀服务商奖

2019 中国(南通)短视频与直播产业发展峰会暨首届中国短视频与直播联盟奖颁奖典礼,于11月1日在江苏南通金陵能达酒店隆重举行。在今天的颁奖典礼上,网易易盾获得主办方颁发的年度内容安全优秀服务商奖。这是自今年5月份上海视频文娱大会获得最佳内容审核服务商奖后,网易易盾再次获得此类荣誉。 本次短视频与直播产业发展峰会在江苏省委网信办指导下,由中国网络视频研究中心联手南通开发区管委会主办,中国短视频与直播联盟联盟、南通开发区管委会承办。 据悉,中国网络视频研究中心(China online video research center)成立于2014年9月,主要致力于打造连接政府与业界桥梁为主要职能的产、学、研一体化的研究平台;而中国短视频与直播联盟(China Short Videos and Live Streaming Alliance)是由中国网络视频研究中心牵头,多家互联网直播和短视频行业的龙头企业联合组成的视频产业联盟,致力于加快直播和短视频行业的规范化、产业化建设,促进行业良性发展。 江苏省委网信办信息化技术协调处处长陈辉(左)与中国网络视频研究中心研究部主任顾洁(右)共同为网易易盾的代表(中间)颁奖 年度内容安全优秀服务商证书和奖杯 在这个背景下,网易易盾获得主办方颁发的年度内容安全优秀服务商奖,说明易盾的内容安全服务的确优秀,因此才获得了政府、短视频与直播的科研机构、产业和行业认可。 实际上,网易易盾的内容安全服务一直被各方不断认可。 内容安全能力上,今年8月底网易易盾获数据中心联盟(DCA)颁发的“网络治理能力评测证书”。根据当时的性能专项评测结果显示,网易易盾的文本类和视频类识别率表现尤为突出,获得了四星——本轮测试中最好的测试成绩(最高星级为五星,但无厂商获得五星的测试成绩)。 技术实力上,网易易盾在首个全国范围大型人工智能领域竞赛上获得最高级证书(旗帜识别领域A级证书),此外网易在同源图像检索、LOGO识别、人脸识别、印刷体OCR也取得了优异成绩,成为那次多媒体信息识别技术竞赛A级认证的十一家企业之一。 研究上实力上,网易易盾深度学习资深研发工程师姚益武在全球计算机多媒体顶级会议ICME 2019(国际多媒体与博览会议)上,发表了题为《Efficient Implementation of Convolutional Neural Networks with End to End Integer Only Dataflow》的学术论文,展示了有助于构建端到端的纯整数运算通路的int8量化新算法,该技术应用于易盾内容安全图像识别上,在确保业务模型推理精度的前提下,其服务的响应时间能得到显著降低。而在2018年ICIP 2018 图像处理大会上,网易易盾实验室研究员提出了一种新的对数据多视角特征进行融合和特征提取的自编码器网络,应用到易盾内容安全服务上,能有效提高有害内容的识别率。因该论文具有创新性及应用价值大,后被IEEE数据库收录。 在自身产品上,网易易盾也在不断迭代,努力拿更好的产品和服务去解决企业面临的各种内容安全难题。在对音频过滤服务再次迭代新增音频实时检测以及发布广告合规检测解决方案、政企网站安全方案后,今年9月份,网易易盾还在国内首发了智能审核管理系统,助力内容平台对审核工作实现全程可溯源追踪,实时掌握内容安全动态,提高效率,降低安全风险。 网易易盾是国内领先的内容安全&业务安全服务商。依靠网易20多年丰富的安全经验以及云计算、人工智能方面的积累,面向数字化业务提供内容安全、业务安全、移动安全和网络安全服务,保障客户业务合规、稳健和安全运营,使客户可以免受黑灰产组织非法侵害,专注创新发展。 当下,易盾其对外提供的内容安全服务为第三代人工智能技术,提供涉黄、涉政、暴恐、广告等十几大类上千小类的有害内容智能识别过滤服务,智能识别精准率超过99.8%,每天检测信息上十亿条。 获得客户认可 目前,易盾已拥有超过25万的注册开发者、数千家付费客户,其中不乏知乎、OPPO、ViVO、小咖秀、挖财、中信证券、触电新闻等知名企业。 点击免费体验网易易盾音视频内容安全解决方案。

November 2, 2019 · 1 min · jiezi

10月第5周业务风控关注-网络平台泄露用户信息500条以上可入罪

易盾业务风控周报每周报道值得关注的安全技术和事件,包括但不限于内容安全、移动安全、业务安全和网络安全,帮助企业提高警惕,规避这些似小实大、影响业务健康发展的安全风险。 1、两高《解释》令互联网江湖闻风丧胆:风控不到位  就有机会犯罪 近期,最高法和最高检联合发布了一份《司法解释》。各大巨头纷纷从中嗅到了“杀气”,具备政治敏感性的企业都立即加强了风控审核和违规处罚的力度,还相继推出了各种警示性公告。 2、上海检方:涉互联网企业刑事案件数上升明显 据解放日报消息,2015年至2019年6月,上海市普陀区人民检察院共受理审查起诉各类涉互联网企业刑事案件44件70人,案件数和涉案人数呈明显上升趋势。针对辖区内互联网企业发展特点,普陀检察院昨天发布《互联网企业常见刑事法律风险防控提示》,归纳出公民个人信息泄露、知识产权保护、互联网技术应用等常见风险点,并为企业提出防控建议,筑牢“防火墙”,护航企业健康发展。 3、暗网上出售130万张印度支付卡的详细信息 Group-IB是一家总部位于新加坡的网络安全公司,日前,该公司检测到一个庞大的数据库,该数据库可能保存了超过130万张印度银行客户信用卡和借记卡的记录,并于10月28日上传到Joker’s Stash。该数据库的暗网价值接近1.3亿美元。 4、网络平台泄露用户信息500条以上可入罪 据新华社报道,11月起,包括网络平台泄露用户信息500条以上可入罪在内的法律法规开始施行。刑法规定,网络服务提供者不履行法律、行政法规规定的信息网络安全管理义务,经监管部门责令采取改正措施而拒不改正,致使用户信息泄露,造成严重后果的,处三年以下有期徒刑、拘役或者管制,并处或者单处罚金。 5、由恶意GIF文件引发的RCE漏洞,超过40000个应用受影响 本月初,新加坡安全研究员@Awakened披露了关于WhatsApp(2.19.244之前版本)存在的RCE漏洞(CVE-2019-11932)利用的文章,该漏洞由Android-gif-Drawable开源库中double-free错误触发。全球范围内43619个使用该GIF开源库开发的安卓APP可能受此漏洞影响。 6、欧盟要求谷歌Facebook采取更多措施打击虚假新闻 欧盟委员会近日表示,Facebook、谷歌和Twitter必须采取更多措施来解决虚假新闻问题,否则将面临监管行动。事实上,在欧盟委员会发出这一威胁的一年前,微软和Mozilla等美国科技巨头已经与七家欧洲贸易机构签署了一项自愿行为准则,以打击虚假新闻。但批评人士指出,这些企业签字以来采取的措施还不够。 7、微博打击非法荐股类信息,关停@金鹰解盘 等37个财经账号 微博发布的打击非法荐股等违法信息的处理公告显示,为了落实企业主体责任,严格贯彻执行《微博社区公约》、《微博商业行为规范办法》管理规定,站方接用户投诉,对冒充他人账号,通过虚假材料骗取认证,通过微博博文、私信等渠道导流至QQ群、微信群、公众号等站外平台的违规营销信息进行集中排查和处理。 8、勒索软件、移动恶意程序攻击将在2020年激增 根据Check Point Software的最新预测,针对性勒索软件,移动恶意软件和复杂的网络钓鱼攻击等网络威胁将在2020年升级。同时,人工智能,网络保险和更快的安全响应等防御能力也将增强,从而帮助企业抵御迫在眉睫的威胁。Check Point在博客文章中概述“关键安全性和相关趋势”,其中包括一系列可用于攻击系统并缓解威胁的技术趋势。 点击免费体验网易易盾安全解决方案。

November 2, 2019 · 1 min · jiezi

prettier了解一下

1.两大linter说起eslint 为js而设计的可插拔的检查程序tslint 为ts语言而设计的可扩展的检查工具(将在2019年取消更新,建议使用eslint)两种linter都可以实现fix功能,所谓fix就是将原代码转化为符合一定规则的新代码。虽然linter工具fix之后的代码,解决了大部分问题,但可能有些地方并不符合我们的阅读代码的习惯,比如一行代码过长。 在强迫症的影响下,不同的人对自己的代码进行不同程度的”美化“,甚至遇到他人代码时也会顺手美化一把。 最终导致项目中的代码风格不能统一。 2.prettier简介prettier是一种保证代码一致性、兼具美化效果的代码格式化工具 2.1 not only js前有jslint,而后由于eslint过于成功,导致了jslint已经无人问津,这也让我们误以为eslint只专注于js下面列举了它所支持的其他语言 javascript、jsxflow、typescriptjsoncss、less、scssgraphqlmarkdownyaml2.2 IDE有人的地方就有江湖,有编辑器的地方就有prettier,目前流行的ide都能支持prettier vscodewebstormatomvisual studiosublime以上列举了前端比较常用的几个工具,需要确定所使用的的编辑器是否支持prettier是否支持,请移步官网 2.3 parserprettier针对不同的语言,所使用的的parser有多个,例如编译graphql时所使用的就是graphql/language。而编译js的目前有两个,即babylon(默认)、flow,由于babylon的bug较少,对编译工作支持度较好,所以默认情况下选用babylon即可。babylon即babel6的编译工具,在babel7中已更名为@babel/parser 3.eslint融合eslint作为强大的linter工具,与vscode配合后能降低代码问题的风险,在coding的过程中就发现潜在问题,提高代码质量。 3.1 eslint-config-prettiereslint的config可以继承自第三方包的config,config中定义了rules的开关规则,eslint-config-prettier主要定义了prettier格式化后导致eslint报错的那些规则 3.2 eslint-plugin-prettiereslint与prettier的格式化需要分别进行,如果想要让eslint fix的同时,也能兼顾prettier的规则进行格式化,就需要使用到eslint-plugin-prettier这个插件。 它的主要作用就是专门定义了eslint fix的prettier规则3.3 融合写法在.eslintrc文件中加入以下配置 { "extends": ["plugin:prettier/recommended"]}这段代码有三个作用 继承prettier的config规则开启rules的 "prettier/prettier": "error"eslint fix的同时执行prettier格式化

November 2, 2019 · 1 min · jiezi

关于Vue路由的一些简单笔记

路由简单来说就是不同的路径调用不同的代码块。在配置路由之前,首先当然是把他们引进来了: <script src="garage/vue.js"></script><script src="garage/vue-router.js"></script>要配置一个路由,一共分为两个步骤: 创建路由表创建vue对象创建路由表使用以下方式创建一个router对象: let router=new VueRouter();他接受一个json对象,对象里的key是routes属性: let router = new VueRouter({ routes: [ { path: '/user', component: { template: '<div>我是买家,今天啥也没买</div>' } }, { path: '/company', component: { template: '<div>我是卖家,今天卖了好几百万的服装</div>' } } ] });path顾名思义就是路径,component是一个组件,组件里面必须包含有template,当然,component本身也是一个vue对象,也可以有vue对象的那些属性 创建vue对象let vm = new Vue({ el: '#div1', router })如果我们创建的router对象的名字和router属性同名,就可以用上面的简写方式。其实到这里vue的路由就算配置好了,接下来的事是需要把他显示在页面上,为此vue给我们提供了一个占位符: <router-view></router-view>当然我们还需要执行路由的动作: <router-link to='/user'>买家平台</router-link><router-link to='/company'>卖家平台</router-link>这个router-link的本质就是一个a标签,里面的to属性必须和上面路由配置表的path对上,不然,他也找不到你要to哪儿 完整代码:<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <script src="garage/vue.js"></script> <script src="garage/vue-router.js"></script> <script> window.onload = function () { //创建路由表 let router = new VueRouter({ routes: [ { path: '/user', component: { template: '<div>我是买家,今天啥也没买</div>' } }, { path: '/company', component: { template: '<div>我是卖家,今天卖了好几百万的服装</div>' } } ] }); let vm = new Vue({ el: '#div1', router }) } </script></head><body> <div id="div1"> <router-link to='/user'>买家平台</router-link> <router-link to='/company'>卖家平台</router-link> <router-view></router-view> </div></body></html>

November 2, 2019 · 1 min · jiezi

JavaScript中发布订阅模式观察者模式

发布/订阅模式的前身-观察者模式观察者模式定义了对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知,并自动更新。观察者模式属于行为型模式,行为型模式关注的是对象之间的通讯,观察者模式就是观察者和被观察者之间的通讯。 观察者模式有一个别名叫“发布-订阅模式”,或者说是“订阅-发布模式”,订阅者和订阅目标是联系在一起的,当订阅目标发生改变时,逐个通知订阅者。 什么是发布/订阅模式其实24种基本的设计模式中并没有发布订阅模式,上面也说了,他只是观察者模式的一个别称。但是经过时间的沉淀,似乎他已经强大了起来,已经独立于观察者模式,成为另外一种不同的设计模式。在现在的发布订阅模式中,称为发布者的消息发送者不会将消息直接发送给订阅者,这意味着发布者和订阅者不知道彼此的存在。在发布者和订阅者之间存在第三个组件,称为消息代理或调度中心或中间件,它维持着发布者和订阅者之间的联系,过滤所有发布者传入的消息并相应地分发它们给订阅者。 根本作用广泛应用于异步编程中(替代了传递回调函数)对象之间松散耦合的编写代码基本案例介绍背景:成都老妈兔头真香,买的人太多需要预定才能买到,所以顾客就等于了订阅者,订阅老妈兔头。而老妈兔头有货了得通知顾客来买啊,不然没有钱赚,得通知所有的订阅者有货了来提兔头,这时老妈兔头这家店就是发布者。 /*兔头店*/ var shop={ listenList:[],//缓存列表 addlisten:function(fn){//增加订阅者 this.listenList.push(fn); }, trigger:function(){//发布消息 for(var i=0,fn;fn=this.listenList[i++];){ fn.apply(this,arguments); } }}/*小明订阅了商店*/shop.addlisten(function(taste){ console.log("通知小明,"+taste+"味道的好了");});/*小龙订阅了商店*/shop.addlisten(function(taste){ console.log("通知小龙,"+taste+"味道的好了");});/*小红订阅了商店*/shop.addlisten(function(taste){ console.log("通知小红,"+taste+"味道的好了");}); // 发布订阅shop.trigger("中辣");//console通知小明,中辣味道的好了通知小龙,中辣味道的好了通知小红,中辣味道的好了案例升级上面的案例存在问题,因为在触发的时候是将所以的订阅都触发了,并没有区分和判断,所以需要一个Key来区分订阅的类型,并且根据不同的情况触发。而且订阅是可以取消的。 升级思路: 创建一个对象(缓存列表)addlisten方法用来把订阅回调函数fn都加到缓存列表listenList中trigger方法取到arguments里第一个当做key,根据key值去执行对应缓存列表中的函数remove方法可以根据key值取消订阅/*兔头店*/ var shop={ listenList:{},//缓存对象 addlisten:function(key,fn){ // 没有没有key给个初值避免调用报错 if (!this.listenList[key]) { this.listenList[key] = []; } // 增加订阅者,一个key就是一种订阅类型 this.listenList[key].push(fn); }, trigger:function(){ const key = Array.from(arguments).shift() const fns = this.listenList[key] // 这里排除两种特殊情况,第一种为触发的一种从未订阅的类型,第二种订阅后取消了所有订阅的 if(!fns || fns.length===0){ return false; } // 发布消息,触发同类型的所有订阅, fns.forEach((fn)=>{ fn.apply(this,arguments); })/* for(var i=0,fn;fn=fns[i++];){ fn.apply(this,arguments); } */ }, remove:function(key,fn){ var fns=this.listenList[key];//取出该类型的对应的消息集合 if(!fns){//如果对应的key没有订阅直接返回 return false; } if(!fn){//如果没有传入具体的回掉,则表示需要取消所有订阅 fns && (fns.length=0); }else{ for(var l=fns.length-1;l>=0;l--){//遍历回掉函数列表 if(fn===fns[l]){ // 这里是传入地址的比较,所以不能直接用匿名函数了 fns.splice(l,1);//删除订阅者的回掉 } } } }}function xiaoming(taste){ console.log("通知小明,"+taste+"味道的好了");}function xiaolong(taste){ console.log("通知小龙,"+taste+"味道的好了");}function xiaohong(taste){ console.log("通知小红,"+taste+"味道的好了");}// 小明订阅了商店shop.addlisten('中辣',xiaoming);shop.addlisten('特辣',xiaoming);// 小龙订阅了商店shop.addlisten('微辣',xiaolong);// 小红订阅了商店shop.addlisten('中辣',xiaohong);// 小红突然不想吃了shop.remove("中辣",xiaohong);// 中辣口味做好后,发布订阅shop.trigger("中辣");shop.trigger("微辣");shop.trigger("特辣"); ...

November 2, 2019 · 1 min · jiezi

基于SEER的区块链版赛亚麻将游戏Pre-alpha版本内测啦

游戏基于SEER测试网络文体平台模块(Culture and Sports Platform,CSP),正在进行数据调试等工作,大家可以尝鲜体验。此游戏账户和资金等核心系统完全基于区块链,但目前运行于SEER测试网络,和SEER主网并不在一条链上,切勿充入主网资产,由此造成资金损失将无法寻回。需要参与测试并充值的用户请登录SEER测试网络钱包 http://192.144.171.138/ 在 设置 - 接入点 中 添加 API 服务器节点 ,添加 ADDRESS 为 ws://192.144.171.138:8003 的测试网络API,然后在 设置 - 恢复/导入 中 点击从钱包备份文件恢复(.bin)下拉菜单,选择 导入私钥 ,在下方输入框中 粘贴 5HxSqrcNu6nZ5xaLK9f6RTVKghJsVGZejz8CnC8e3qnPc14LUdP 然后点击 提交 , 导入私钥 ,完成。导入测试账号tester。然后使用此账号向您在游戏中注册的账号转账,进行充值。体验和测试流程: 下载游戏APK测试包:https://www.seer.best/downloa...,打开后可以看到如下界面: 请点击微信登陆完成授权,之后进入游戏,会提示创建SEER账户,此账户会是您在SEER(测试)链上的唯一标识,注意不能是纯字母组成,需要加横杠或数字; *赛亚麻将的开发者在此版本的开发中,考虑到用户操作门槛问题,未使用类似币比的助记词权限验证形式,而是直接使用微信授权登陆并和游戏帐户、区块链账户联合绑定的形式进行登陆验证,此种方式虽然不够“去中心化”,但操作足够简便。之后可能会根据用户需求开发更多形式的登陆和授权模式。 点击左上角带有链标识的图标,会提示前往交易所充值,在主网中大家将可以用网关、转账等各种形式向你的SEER账户充值,但这里我们在测试网络网页钱包上用tester向您的账户充值就可以了。这里示例转账了100万测试SEER,测试网络链上如下: 充值后,退出游戏再重新进入,左上角可以看到有链标识的图标后显示了100万,充值成功,代表此账号余额为100万,和SEER链上的账户余额一致。 同时可能会弹出绑定代理的弹窗,这是一个推广功能设计,代理就是帮忙推广此游戏的用户,你填写的游戏ID的用户可以得到推广奖励。这里随便填一个100001就好了。 我们任意点击一个游戏,进入房间,会提示SEER不足。这是因为我们的SEER全部在账户余额中,并没有划转给平台,只有划转给平台的资产,才能参与游戏(文体平台只能对用户划转的资产有操作权限,比如输赢之类),这是一层保护机制。我们需要点击取SEER,或是提前点击顶部有SEER标识的图标进行授权划转操作。 在币箱页面 输入金额,例如10万,确定,可以看到余额减少了相应金额,并扣除了一些手续费,而SEER图标后增加了相应金额。 区块链上可以看到相应的划转操作提示。 现在可以加入游戏了。游戏开始后,会自动收取一定的房费,这是游戏运营方的主要收入来源。 在区块链上可以看到相应的资金操作,两位玩家分别向GM转了房费,这会从用户划转给平台的资金中自动扣除。 游戏结束后,会进行结算。 在区块链上可以看到相应的资金操作,失败的一方或多方会将资金先转给GM,然后GM会根据各方的输赢情况将相应比例的资金自动分配给胜利的一方玩家。 在SEER文体平台模块中,任何SEER用户可以在主网抵押一笔保证金后获得文体平台权限,文体平台有平台资金池,其他SEER用户可以直接在链上授权一定资产额度给平台,能获得多少用户“授权”和其抵押的保证金有关。 平台通过调用接口控制用户授权的资产额度进行各种链上操作,且可以将亚秒时间内的操作统一打包,这些操作手续费都由平台支付。这样既能保证用户对资产的所有权,又能保证游戏等文体平台原有的游戏核心之类的应用逻辑不作太大的变化,具有很高的效率和可操作性,可以让游戏内积分等完全区块链化,第三方也可以很方便的做成完全合规的区块链应用。 文体平台不光可以应用到游戏领域,票务等文化体育领域的众多方向都可以进行扩展。 详情请参考SEER文体平台模块(Culture and Sports Platform,CSP)使用指南:https://mp.weixin.qq.com/s/mJ...

November 2, 2019 · 1 min · jiezi

分享一个页面平滑滚动小技巧

背景今天写需求的时候发现一个一个小的优化点:用户选择了一些数据之后, 选择的条目需要高亮, 有时候列表很长, 为了提升用户体验,需要加个滚动, 自动滚动到目标位置。 下午简单的查了一下, 问题顺利解决, 就把这个小技巧分享一下给大家。 正文有几种不同的方式来解决这个小问题。 1.scrollTop第一想到的还是scrollTop, 获取元素的位置, 然后直接设置: // 设置滚动的距离element.scrollTop = value;不过这样子有点生硬, 可以加个缓动: var scrollSmoothTo = function (position) { if (!window.requestAnimationFrame) { window.requestAnimationFrame = function(callback, element) { return setTimeout(callback, 17); }; } // 当前滚动高度 var scrollTop = document.documentElement.scrollTop || document.body.scrollTop; // 滚动step方法 var step = function () { // 距离目标滚动距离 var distance = position - scrollTop; // 目标滚动位置 scrollTop = scrollTop + distance / 5; if (Math.abs(distance) < 1) { window.scrollTo(0, position); } else { window.scrollTo(0, scrollTop); requestAnimationFrame(step); } }; step();};// 平滑滚动到顶部,可以直接:scrollSmoothTo(0)jQuery 中重的animate 方法也可以实现类似的效果: ...

October 22, 2019 · 1 min · jiezi

基于HTML5的WebGL实现的2D3D迷宫小游戏

为了实现一个基于HTML5的场景小游戏,我采用了HT for Web来实现,短短200行代码,我就能实现用“第一人称”来操作前进后退上下左右,并且实现了碰撞检测。 先来看下实现的效果: http://hightopo.com/guide/guide/core/3d/ht-3d-guide.html#ref_collision 或者http://v.youku.com/v_show/id_XMzA5MzUzODc4NA==.html?spm=a2h3j.8428770.3416059.1视频中出现的帧的问题是我屏幕录制器的问题,真正操作的时候不会有,建议用上面的链接自己操作 玩玩,鼠标或者触屏都可以,不过我觉得最方便的还是操作键盘wsad控制上下左右。 我的想法是先把场景布局好,代码如下: createHT([100, -20, 100], '#E74C3C'); createHT([-100, -20, 100], '#1ABC9C'); createHT([100, -20, -100], '#3498DB'); createHT([-100, -20, -100], '#9B59B6'); createCurve([0, -20, 0]);createCircle();这几个都是自定义的函数,createHT为描绘HT形状的图,场景中有四个,所以调用了四次;createCurve是描绘场景中间的黄色的曲线;createCircle是描绘最外层的圆,因为不是全包的圆,所以也是描点画的。 HT中封装了一个组件,ht.Shape(以下简称Shape),能够根据描点来自由描绘图形,可以通过shape.setPoints(pointsArray)将所有的点添加进数组中,并且设置到shape中,然后通过setSegments()设置线段数组信息,也就是用什么样的方式来连接两点,在Shape手册中有着重描写,感兴趣的可以参考HT for Web Shape 手册。抽其中的一个描绘点的函数来看看: function createHT(p3, color){ shape = new ht.Shape(); shape.s({ 'shape.background': null, 'shape.border.width': 10, 'shape.border.color': color, 'all.color': color }); shape.setTall(40); shape.setThickness(5); shape.setPoints([ // draw H {x: 20, y: 0}, {x: 20, y: 100}, {x: 20, y: 50}, {x: 80, y: 50}, {x: 80, y: 0}, {x: 80, y: 100}, // draw T {x: 120, y: 0}, {x: 180, y: 0}, {x: 150, y: 0}, {x: 150, y: 100} ]); shape.setSegments([ // draw H 1, // moveTo 2, // lineTo 1, // moveTo 2, // lineTo 1, // moveTo 2, // lineTo // draw T 1, // moveTo 2, // lineTo 1, // moveTo 2 // lineTo ]); shape.p3(p3); dataModel.add(shape); return shape;} 因为“HT”这个字眼要描绘的点比较多,所以代码看起来有点大,如果你看到如何描绘一个不完全的圆用20行代码来完成,而且包括样式,还是会惊讶的: ...

October 22, 2019 · 2 min · jiezi

开发-HTML5-小游戏

Html5小游戏 在介绍小游戏之前,先看一个框架 Phaser。Phaser 框架是一个 快速、免费且开源的 HTML5 游戏开发框架,它提供了 Canvas 和 WebGL 两种渲染方式,兼容 PC 端与移动端浏览器。 一、Phaser 版本在启动 Phaser 游戏前,需要定义一个 Phaser.Game 对象实例,并同时将配置信息传至该实例:var game = Phaser.Game(config)。在 Phaser2 版本中,定义的是一个全局变量,并作为几乎全部的系统或者场景的入口。但升级至 Phaser3 版本之后,不再使用全局变量来存储游戏实例了。 Phaser2 版本之前// Phaser.Game(// width,// height,// renderer,// parent,// state,// transparent,// antialias,// physicsConfig// );Phaser.Game(800, 600, 'Phaser.AUTO', 'game');Phaser3 版本之后const config = {};Phaser.Game(config);二、游戏配置 configconst config = { type: 'Phaser.AUTO', title: "Starfall", width: 800, height: 600, parent: "game", backgroundColor: "#18216D", scene: [WelcomeScene, PrizeScene, GameScene, ScoreScene], transparent: false, antialias: true, loader: { baseURL: 'https://raw.githubusercontent.com/wqjiao/phaser-prize/master/', // 资源基本地址 crossOrigin: 'anonymous' } physics: { default: "arcade", arcade: { debug: false } },}1.type 游戏使用的渲染环境可选值: Phaser.AUTO、Phaser.WEBGL、Phaser.CANVAS推荐值: Phaser.AUTO 自动尝试使用 WebGL,如果浏览器或设备不支持,它将回退为 Canvas父节点: Phaser 生成的画布元素 canvas 将径直添加到文档中调用脚本的那个节点上,也可以在游戏配置中指定一个父容器 parent。2.title 游戏界面标题3.width、height Phaser 生成的画布尺寸,即游戏界面的分辨率默认:width -- 800、height -- 6004.parent 自定义 Phaser 生成画布(游戏界面)的父容器5.backgroundColor 游戏界面的背景颜色,Phaser3 版本配置项6.scene 游戏场景 ...

October 17, 2019 · 3 min · jiezi

SEER流量众筹模块开发测试网络及使用文档发布

SEER利用区块链奖励机制,可解决传统体育赛事痛点,提高行业运转效率。比如提高赛事方收入,让观众自由选择想看的比赛,给予赛事众筹的参与者贡献影响力,使其获得由智能合约量化的激励等。此功能可广泛应用于包括但不限于演出、赛事等文体产业中的各种场景。 只有资产发行者能够创建新众筹。在SEER开发者网页钱包中,可在资产发行者的资产页,看到资产功能中有“众筹列表”按钮,进入可查看当前用户已有众筹列表或创建新的众筹。 在创建众筹时,可设置众筹开始结束时间、代理人等。代理人的设计初衷,是出于安全考虑,资产拥有者账号/DAPP官方账号不可以长期在线,众筹创建后由代理者行使后续权力,同时,代理人也可以作为水龙头,负责推广和注册账号。 创建众筹时,还需要设置各种激励的名称及每份奖励数量。例如每次助力奖励10ABC,朋友助力奖励5ABC。 创建众筹时需要添加受益人角色,例如合作媒体、明星、举办方等,在创建时为这些角色设定众筹成功后,资金池的分配比例,并且可以单独为每位角色设置线性解锁、不锁定、到期解锁等锁定方式和锁定天数。 众筹进行中时,需要配合相应的前端程序和活动程序使用,在链上解决的主要是通过智能合约进行筹得资产的增发、销毁、分配、锁定等步骤。而用户贡献流量这一步,则需要特定的活动程序向区块链提供数据,由创建人或代理人权限根据活动数据为本场众筹注入新资产。 例如,一场活动在某一周期内有10000人通过微信授权登陆进行助力,另外这些用户产生了5000人次的邀请朋友助力数据,根据每次助力奖励10ABC,朋友助力奖励5ABC的设定,该周期共计为资金池注入10000 10 + 5000 5 = 125000 ABC,同时,另有 150 位用户通过参与众筹的形式,捐赠或打赏了 50000 ABC,该周期可供受益人各方分配的资产为175000 ABC,这些资产将在活动成功后将根据预先设定的比例进行分配,若失败,捐赠部分将退回给用户。根据活动数据,发起方可根据用户的捐赠和助力贡献或排名,给与大到冠名、广告露出,小到明星签名周边之类的各种名誉奖励。 若有问题,欢迎在开发者论坛参与讨论:https://forum.seerchain.org/t... 体验流程开发者可首先在本地下载配置命令行钱包,连接到此测试网络。导入测试账号tester的私钥,生成多个密钥对,注册多个测试账号。使用tester向自行注册的账号转账测试的SEER,之后使用自行注册的账号创建资产,随后创建众筹,开启众筹。然后使用创建的多个其它账号向自行创建的众筹捐赠资产,使用代理账号或众筹发起账号模拟流量价值进行的增发,众筹到期后输入众筹成功或失败的结果,使用创建或更新时设置的受益人账号领取收益等。 接口说明流量众筹模块需要配合链上原有的资产发行、销毁等功能使用,主要包含六个新的接口:competition_create、competition_update、competition_participate、competition_input、competition_claim、competition_result。其中创建众筹competition_create、更新众筹competition_update参数较复杂、连同收益领取competition_claim、输入结果competition_result,一般使用网页钱包操作即可。 以下介绍参与众筹competition_participate和注入新资产competition_input接口。 competition_participate格式:competition_participate(string account,competition_id_type competition,asset amount,bool broadcast = false); 参数:account:发起者、competition:众筹ID、amount:参与的数额(带精度)以及资产类型、broadcast:是否广播; 作用:普通用户参与众筹(向本次众筹资金池捐赠资产)。 命令行钱包示例:competition_participate 1.2.13 1.18.7 {"amount":10000000,"asset_id":"1.3.3"} true RPC示例:{"jsonrpc": "2.0", "method": "competition_participate", "params": ["1.2.13","1.18.7",{"amount":10000000,"asset_id":"1.3.3"},true], "id": 1} 参数说明(RPC形式): { "jsonrpc": "2.0", "method": "competition_participate", "params": [ "1.2.13",//发起者 "1.18.7", {//众筹ID "amount": 10000000,//参与的数额 "asset_id": "1.3.3"//资产类型 }, true ], "id": 1}返回信息示例: { "id": 1, "jsonrpc": "2.0", "result": { "ref_block_num": 3404, "ref_block_prefix": 135777280, "expiration": "2019-10-16T15:32:36", "operations": [ [65, { "fee": {//手续费 "amount": 500000, "asset_id": "1.3.0" }, "issuer": "1.2.13",//发起者 "competition": "1.18.7",//众筹ID "amount": { "amount": 10000000,//参与的数额 "asset_id": "1.3.3"//资产类型 } }] ], "extensions": [], "signatures": ["2071d05......2e491"] }}competition_input格式:competition_input(string account,competition_id_type competition,map<uint8_t,uint32_t> input,bool broadcast = false); ...

October 17, 2019 · 2 min · jiezi

webpackdevserver-代理服务返回的-json-内容被截断或部分乱码

原因Original problem spdy-http2/node-spdy#357. Unfortunately we can fix it right now, it was be fixed after express will be support http2. Now we implement http2 option in master to disable http2, you can use this as workaround由于 webpack-dev-server 默认启用了http2, 使用的是 spdy-http2/node-spdy 库的实现, 这个 bug 是该库造成的, 并在3.4.7版本被修复.该问题发生在Node v8中, v10不存在此问题. 解决方法1webpack.config.js devServer: { ..., http2: false }方法2Node升级到v10 参考https://github.com/webpack/webpack-dev-server/issues/1574https://github.com/spdy-http2/node-spdy/issues/357

October 17, 2019 · 1 min · jiezi

关于echarts图表根据父元素宽度进行自适应

有时候echarts设置了图表后,放大浏览器和缩小浏览器,父元素会跟着浏览器大小进行放大和缩小,而图表不会跟着父元素大小进行变化,这时候我们可以设置echarts对象,让他可以实现这样的效果。 官方文档如下: ECharts没有绑定resize事件,显示区域大小发生改变内部并不知道,使用方可以根据自己的需求绑定关心的事件,主动调用resize达到自适应的效果,常见如window.onresize = myChart.resize。注意: 如果这个页面有多个图表://多图表自适应window.addEventListener("resize", function () {myChart.resize();myChart2.resize();});

October 16, 2019 · 1 min · jiezi

web前端以文件流的形式导出Excel文件

一般web前端处理导出文件有两种方法:1、服务端返回完整URL,直接打开URL即可;2、服务端返回数据流,前端解析数据流完成导出功能;今天主要分享下第二种方式,直接上代码(兼容ie10以上): // url为服务端返回的流数据const exportParams = (url) => { const aLink = document.createElement('a'); const blob = new Blob([url],{type: "application/vnd.ms-excel"}); // 创建一个当前文件的内存URL const _href = URL.createObjectURL(blob); aLink.style.display = 'none'; aLink.href = _href; document.body.appendChild(aLink); aLink.setAttribute('download', '用户数据.xlsx'); aLink.click(); document.body.removeChild(aLink); // 手动释放创建的URL对象所占内存 URL.revokeObjectURL(_href);}其实现原理就是先把服务端返回的数据流通过URL.createObjectURL()方法转成一个URL,这个URL是存放在内存中的,URL的生命周期是和创建的它的document绑定,也就是说在document unload的时候也会得到内存释放;然后通过设置<a></a>的download属性值,从而实现导出功能,最后再手动释放下创建的URL对象的内存。

October 16, 2019 · 1 min · jiezi

基于-WebGL-实现的-HTML5-3D-弹力布局

分子力(molecular force),又称分子间作用力、范得瓦耳斯力,是指分子间的相互作用。当二分子相距较远时,主要表现为吸引力,这种力主要来源于一个分子被另一个分子随时间迅速变化的电偶极矩所极化而引起的相互作用;当二分子非常接近时,则排斥力成为主要的,这是由于各分子的外层电子云开始重叠而产生的排斥作用。 HT for Web 提供了弹力布局(也称为力导向布局)的功能,即根据节点之间存在互斥力,相互连接的节点间存在引力, 弹力布局运行一段时间后,整体拓扑网络结构会逐渐达到收敛稳定的平衡状态。这个功能很有趣,今天我们就将它的魅力展现出来。 本例地址:http://www.hightopo.com/demo/...使用弹力布局功能需要在引入 ht.js 核心库之后,再引入一个 ht-forcelayout.js 的弹力布局插件库,因为还用到了 form 表单,所以要引入 ht-form.js 的表单插件库: <script src="../../guide/lib/core/ht.js"></script><script src="../../guide/lib/plugin/ht-forcelayout.js"></script><script src="../../guide/lib/plugin/ht-form.js"></script>ht.layout.Force3dLayout 类提供 3D 弹力布局,构造函数可传入 DataModel 和 Graph3dView 两种参数。 默认仅对未选中图元进行布局,如果构造函数参数为 Graph3dView 时,则视图组件的 isMovable 和 isVisible 函数将影响图元是否可布局, 图元 style 上的 layoutable 属性也可设为 false 阻止图元参与布局。 介绍完 HT 封装的弹力布局的背景之后,接下来就是帮助你们也能轻松地实现这个效果。 首先我们定义一个颜色数组变量,存储各个弹力球的颜色,还定义了一个随机函数,用来生成数随机的数组中的颜色: var colorList = ['#FFAFA4', '#B887C5', '#B9EA9C', '#CFD9E7', '#4590B8', '#FF9C30'], colorLen = colorList.length;var randomColor = function() { var ran = Math.random() * colorLen; return colorList[Math.floor(ran)]; // 随机 6 种颜色};接着创建弹力球,简单生成一个 3D 节点,通过设置这个节点的 style 样式属性来控制节点的显示方式,其中将“shape3d”设置为“sphere”即可将 ht.Node 六面体变成 3D 球体模型,再设置“shape3d”属性为前面定义的随机颜色,s3 是 HT 封装的设置 3D 节点大小的 setSize3d 函数的简写,最后将这个节点添加进数据模型 dataModel 中: ...

October 16, 2019 · 3 min · jiezi

掌游天下带你走进全面的h5游戏开发实战

简介: 一个超级详细全面介绍响应式h5游戏的项目大全。技术栈为原生JS(es5) + create.js(二次封装) + 原生canvas。 目录1、看完能学到什么  2、前言  3、简单的自我介绍 + 什么是h5游戏 4、我负责了哪些h5游戏  5、王牌h5游戏线上链接  6、核心知识点简介  7、如何实现h5游戏  8、h5游戏开发规范  9、创建该项目目的 10、总结 该项目的亮点有哪些?技术栈为原生JS(es5) + create.js(二次封装) + 原生canvas,体量小代码精简,提升了游戏页面加载速度。所有h5游戏,要么是用原生JS实现,要么是二次封装的create.js实现,也有原生canvas的精彩表现,或是两者、三者技术的结合,不存在类似jq等第三方库。h5游戏前端性能优化大全:https://github.com/WckY/Respo..., 将会告诉你h5游戏具体会如何提升性能。成功封装了自己的UI框架。将我司的移动端适配和create.js进行了深度结合、二次封装,不仅创建了公共create.base.js,还封装了公共UI框架。不仅实现了移动端的适配,还实现了横竖屏的适配,也就是移动端和PC端的双重适配,打破了h5游戏默认竖屏横屏却无兼容的尴尬模式。使用原生JS封装了公共工具类——base.js,在该js里注入了移动端适配的核心。成功监听到当手机静音键开启时,h5游戏的BGM也对应的pause。兼容了在弱网条件下,可能出现的白屏问题。更多的亮点,我会在开发规范中阐述。h5游戏前端性能优化大全https://github.com/WckY/Respo...,将会告诉你h5游戏具体如何提升性能。 更加详细的解析和已分好类的各大h5游戏文件,再加上本篇文章篇幅很长,各位也可直接移步至我的github:https://github.com/WckY/Respo...。喜欢的希望大家点个 star,鼓励一下,谢谢哈!!!那么正文开始,开启奇妙的h5游戏之旅吧。 1、看完能学到什么?Q: 什么是h5游戏? 我将解释清楚。 Q: 实现h5游戏的过程中,需要注意哪些事项? 我会分享我司前端游戏小组约定俗成的开发规范。 h5游戏编程中,会涉及大量知识点、技术难点、解决方案,及时避坑。 Q: 对提高业务能力有帮助吗? 答案是肯定的,毫不夸张地说,有利于快速提高你的产品思维、设计美感,而不仅仅是撸码。 2、前言大家好,我是来自掌游天下的WckY,自从去年年底从驾考宝典离职来到掌游天下探索、编写响应式h5游戏,不知不觉已经过了十个月了,时间过的真快啊。可能大部分前端工程师处理的都是数据型业务,h5内嵌App、混合开发,用element等做后管理后台,很少听过h5游戏。那么接下来我将为大家全面地介绍h5游戏,什么是h5游戏,如何实现h5游戏,h5游戏从零到一上线需要哪些人员配合等问题,我将一一为大家讲述。友情提示,此篇文章篇幅很长,作为一篇专业介绍h5游戏开发实战的文章,里面首先会介绍、分类我公司目前上线的所有游戏,我会将代码当中涉及到的知识点、技术难点,一一罗列。对h5游戏感兴趣的同学更要有耐心和用心了,因为h5游戏对原生JS的要求很高,游戏引擎和原生canvas的使用其次。当然了,专业的flash开发转h5游戏开发大佬还请高抬贵手勿喷,此篇文章仅作为科普贴和小白分享帖,向更多的前端同学分享一个全新的前端世界。更多精彩内容,各位也可移步我的github地址,我在我的github里建立了一个Responsive-h5game-dictionary项目: https://github.com/WckY/Responsive-h5-game-dictionary ,项目里有所有线上h5游戏链接和对应的详解,将会介绍的更加详细。好了废话也不多说,我先抛砖引玉一个我司的王牌游戏——Popstar消灭星星(消除类游戏),已经十周年了,这是我实现的国庆大阅兵主题: https://static.zplay.cn/wap/ad_canPlay/popstar/20/plat/popstar_nation_WCKY_adwords_cn.html 。 那么接下来进入正题。 3、简单的自我介绍 + 什么是h5游戏我在进入掌游天下游戏公司前(我司主要是发行、代理和自主研发游戏),在驾考宝典从事常规的业务开发一年多。和大家一样,每天都是和服务端、客户端打交道,做运营、产品的移动端需求,做完对外项目,就做对内后台管理项目。从驾考宝典离职后,我也没想过自己会来游戏公司,负责全新的领域。坦白讲,h5游戏对前端来说是个巨大的挑战,而我,即负责h5端游戏。什么是h5游戏?区别于小程序里的游戏——在高度还原App端游戏玩法、主题、操作同时,不断推陈出新其他idea,然后可以在所有浏览里打开正常操作的一个线上链接,包括微信、QQ、钉钉等。说白了,就是引流、创意营销。而我在公司一人身兼至少三个角色,游戏策划、代码的编写、自测。因为公司并没有招对应的游戏策划,也就是我们理解的产品经理这一专业人才。因此每个App游戏、每个新玩法h5上线,都是自己绞尽脑汁想出的idea,而且每周至少要新出一个idea,这是一件十分痛苦的事,没有人会告诉你该怎么做(我公司当然有产品经理,但只负责App端,h5端无)。紧接着是设计稿,从我加入掌游天下至今,是没有设计稿的。响应式h5游戏,需要兼容横竖屏,包括不同的样式布局、和对PC端移动端的事件监听。说到这希望各位朋友不要误会,以为可以随心所欲设计了,前端游戏小组还是有前端老大也就是我leader坐镇的,创意的审核、设计稿的自行设计还是要经过leader同意方可开始,虽然他也是从数据型前端开发转型过来。因此,有一定的设计感、美感是必须的,即使没有,也要在最短时间内培养出来,否则最终导致的后果就是下载量惨不忍睹,转换率过低,大家都很尴尬。总之,对h5感兴趣甚至想尝试这个领域的朋友一定要做好心理准备,h5游戏开发太难了,难的不是写代码,写代码也比处理数据的代码难很多。当没有游戏策划同事时,所有的一切就要靠自己了。就比如大家都爱玩王者荣耀,那如果让各位设计一款30S以内吸引新玩家的王者荣耀h5游戏,该如何下手呢?并成功转化为让商务经理、老板高兴的可观的下载量数据。这就是h5游戏的最大使命! 4、我负责了哪些h5游戏在介绍具体如何实现h5游戏前,我想先和大家分享下我目前负责了哪些游戏。从数量上计算总共有11款App,每款App里有若干玩法、不同版本的h5,少则2款,多则像我司的王牌游戏——Popstar消灭星星,30+个创意,而且在持续增加。从游戏大种类上区分,分别是消除类游戏《Popstar消灭星星》、竞技绘画游戏《猜画小歌2》(英文名字《Draw It》)、割草休闲游戏《Idle Grass Cutter》、闯关冒险游戏《Will hero》(中文名《王牌大作战》)、纸飞机游戏《PaperPlanePlanet》、电音类游戏《球球你跳一跳》、拼图类游戏《Hexa Drawn》、解压破坏类游戏《Idle Press》、涂鸦休闲游戏《Kolor It》、舞蹈类游戏《madForDance》。我也将在之后的篇幅及github中,为大家分享我同事实现的更有趣、更有难度的h5游戏。而之所以先告诉各位游戏的种类,目的就是不想浪费大家的时间,希望能方便你们自行搜索、阅览、尝试、编程。甚至在以后的工作当中如果能借鉴到我今天的分享,我的工作就没白费。那么在大种类里还细分了更多的尝试,比如分屏玩法,程序的自动开始和玩家的手动操作竞技,这样趣味性是不是更足呢,期待大家的反馈。 5、部分王牌h5游戏线上链接Popstar https://static.zplay.cn/wap/ad_canPlay/popstar/1/plat/popstar_appLovin_en.html 引擎为pixi.js,难点在于无限递归,我leader亲自写的第一版。 static.zplay.cn/wap/ad_canP…  引擎为create.js。 static.zplay.cn/wap/ad_canP…  同上,难点在于气泡的渲染,使用算法实现,以及监听mouseover事件,最后removeEventListener。 static.zplay.cn/wap/ad_canP…  原生JS实现,创意来自网上,难点在于单次点击和点击以后的判断等。 static.zplay.cn/wap/ad_canP…  同上。 static.zplay.cn/wap/ad_canP…  引擎为create.js。 static.zplay.cn/wap/ad_canP…  ...

October 16, 2019 · 2 min · jiezi

基于-HTML5-WebGL-智能城市的模拟运行

前言智能城市是一个系统。也称为网络城市、数字化城市、信息城市。 智能城市建设是一个系统工程:首先实现的是城市管理智能化,由智能城市管理系统辅助管理城市,通过管理系统人们可以监视城市的运行,了解城市每天中发生的变化,以及及时的根据这些变化做出相应的管理;其次是包括智能交通、智能电力、智能安全等基础设施的智能化,交通是一个城市的驱动,交通的畅通加速了城市的发展,通过 Web 可视化的交通管理,可以更及时的了解交通情况,做出处理;智能城市也包括智能医疗、智能家庭、智能教育等社会智能化和智能企业、智能银行、智能商店的生产智能化,从而全面提升城市生产、管理、运行的现代化水平。 本 demo 使用 HT for Web 产品轻量化 HTML5/WebGL 建模的方案,构建了城市建筑群场景,添加了城市道路,实现了智能城市 Web 可视化,还通过动画模拟了城市的运行。 demo 地址:http://www.hightopo.com/demo/intelligent-city/entry/dest/index.html 预览图: 代码实现加载场景 首先新建一个场景,并将场景添加到页面中。 let dm = this.dm = new ht.DataModel();let entryG3d = this.entryG3d = new ht.graph3d.Graph3dView(dm);entryG3d.addToDOM(); // 将场景添加到页面中 HT 的组件一般都会嵌入 BorderPane、SplitView 和 TabView 等容器中使用,而最外层的 HT 组件则需要用户手工将 getView() 返回的底层 div 元素添加到页面的 DOM 元素中,这里需要注意的是,当父容器大小变化时,如果父容器是 BorderPane 和 SplitView 等这些 HT 预定义的容器组件,则 HT 的容器会自动递归调用孩子组件 invalidate 函数通知更新。但如果父容器是原生的 html 元素, 则 HT 组件无法获知需要更新,因此最外层的 HT 组件一般需要监听 window的窗口大小变化事件,调用最外层组件 invalidate 函数进行更新。 ...

October 16, 2019 · 4 min · jiezi

简单的鼠标移动元素近大远小效果

效果: 前置知识:CSS position,js map函数实现原理:视觉原理:远处的物体移动慢,近处的物体移动快实现原理:在鼠标移动的时候,在原 div 的原有位置上+鼠标移动的距离和z-index的乘积*Q:为什么要乘z-index?A:在初始div的时候要给每个都设置z-index,越大(离你越近)的物体z-index越高or大* 步骤:①获取每个div②获取每个div当前的left和top③鼠标移动时给每个元素加上鼠标移动距离*z-index; 代码实现:HTML代码: <div style="width:50px;height:50px;left:210px;top:50px;position: absolute;z-index: 1;background: blueviolet"></div><div style="width:100px;height:100px;left:50px;top:130px;position: absolute;z-index: 2;background: rgb(223, 66, 139)"></div><div style="width:150px;height:150px;left:300px;top:150px;position: absolute;z-index: 3;background: rgb(65, 163, 139)"></div><div style="width:200px;height:200px;left:50px;top:400px;position: absolute;z-index: 4;background: rgb(226, 197, 35)"></div>①获取每个div: let aDiv=document.getElementsByTagName('div');②获取每个div当前的left和top: let oldPos=Array.from(aDiv).map(div=>{ return { left:div.offsetLeft, top:div.offsetTop } });③鼠标移动时给每个元素加上鼠标移动距离*z-index; document.onmousemove=function(ev){ let event=ev||window.event; Array.from(aDiv).forEach((div,index)=>{ div.style.left=oldPos[index].left+event.clientX*div.style.zIndex/100+'px'; //除100是为了div移动的不要太快 div.style.top=oldPos[index].top+event.clientY*div.style.zIndex/100+'px';//同理 }) }完整代码:<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <script> window.onload=function(){ let aDiv=document.getElementsByTagName('div'); let oldPos=Array.from(aDiv).map(div=>{ return { left:div.offsetLeft, top:div.offsetTop } }); document.onmousemove=function(ev){ let event=ev||window.event; Array.from(aDiv).forEach((div,index)=>{ div.style.left=oldPos[index].left+event.clientX*div.style.zIndex/100+'px'; div.style.top=oldPos[index].top+event.clientY*div.style.zIndex/100+'px'; }) } } </script></head><body> <div style="width:50px;height:50px;left:210px;top:50px;position: absolute;z-index: 1;background: blueviolet"></div> <div style="width:100px;height:100px;left:50px;top:130px;position: absolute;z-index: 2;background: rgb(223, 66, 139)"></div> <div style="width:150px;height:150px;left:300px;top:150px;position: absolute;z-index: 3;background: rgb(65, 163, 139)"></div> <div style="width:200px;height:200px;left:50px;top:400px;position: absolute;z-index: 4;background: rgb(226, 197, 35)"></div></body></html>

October 16, 2019 · 1 min · jiezi

关于前端面试每日31

前端面试每日3+1简介有些是聚合平台,大家一起来成就它,而我的使命是要去成就别人,我觉得自己做的事情很伟大,所以我在坚持!就算最后一个人都没有,那我还是要坚持,因为我很固执为自己而活!近些日子,很多人私聊我很多问题,我把这些问题归类整理了下,便形成了“前端面试每日3+1”的介绍。语录整理问:3+1指的是什么? 答:指的是前端的3个必会技能html/css/javascript和一个工作中相关的软技能。问:为什么是3+1? 答:在这千变万化,类库层出不穷的前端,要知道html、css、javascript才是基石!有的时候我们舍近而求远,容易被各种框架所迷惑,要做到不忘初心才能方得始终,+1是加了个技能题,扩展我们的视野(广度)。问:你提到的“每日三问”,指的是哪三问呢? 答:出自于《论语》,曾子曰:“吾日三省吾身”。今天我做计划了吗?今天我学习了吗?今天我思考了吗?问:你为什么要做这个事?你的初衷是什么? 答:好多人都问过我,为什么要做这个事情呢?故事起源于离职同事发来的一道求助面试题,然后在部门企业微信群里炸开了,答题完后大家觉得如果要是每天来一题,是不是会更爽呢?以面代练,突发其想说干就干,所以就有了这个开源仓库,只为利他利己!当时的一股劲,说做就做,没想这么多。现在好好想下,其实不为别的,就算是为了自己吧,坚持去做一件事,哪怕就只有我一个人。问:为什么没有答案? 答:这个问题已经有不下百人问过我,在这我一直都在强调三点: 1.独立思考(勤思考);2.动手去做(多动手);3.坚持学习(能坚持)答案网上一大把,就算是我一下子把上千道题目和答案放在你面前,你未必看得下去,学习是一个思考与积累的过程。我宁愿自己花点时间深入弄懂一个知识点,也不愿意仅仅只是把这几千道题收藏起来!问:有没有人让你提供过答案? 答:有,非常多!有不少朋友上来就是要答案,我都会说没有!问:面试题这么多,网上搜索出来有很多,为何还要一天天发呢? 答:如果我一下子把所有题列出来了,你觉得你还会看吗?就好比一下给你几十G的视频,你觉得会有效果吗?问:你去哪弄的这么多面试题? 答:很多都是工作中遇到的,然后拿出来分享下,当然还有更多是来自广大朋友的力量。所以说开源是大家的,不是我一个人的,取之于民用之于民。问:题目有没有可能出完的一天?出完了怎么办? 答:会,但学习的过程是无止境的。问:你觉得出的题偏难还是简单? 答:我觉得没必要去划分简单和难的界线,只有学与不学。问:看到你的平时提交记录,都是在还没到5点的时候,你究竟是几点起的? 答:4:30问:你不困吗?答:不困问:有没有人质疑过你?答:有啊,有几次我一刚发完题,网友们就在微信上私聊我假装跟我聊天,看我是机器发的还是人工发的,刚开始几次我还好就回复了,但后来我就不回复了,等上班在地铁上时再回复下,因为我不想占用他们的早上的宝贵时间。问:你是如何来得动力? 答:做就要做好,这是一种个性吧。问:你怎么会有这么多时间? 答:早上的时间完完全全属于自己的,那时没有微信、没有电话、没有饭局等的打扰。问:这开源项目未来还要添加什么功能吗? 答:可能会做个网站展示吧,具体怎么做暂时还未考虑这么多。问:你是怎么做推广的? 答:刚开始的时候,我天天在掘金上发,后面被喷了很多次,但我就是这么厚脸皮,既然请不了大v,那就只能天天坚持厚脸皮啰^_^!问:在开源过程中会有反对你的人吗? 答:好多,非常感谢!问:你能自我评价下自己是个什么样的人? 答:非常靠谱问:有和你做类似的事情吗?或者说是竞争对手? 答:这不存在竞争对手一说。但做的过程中发现类似的朋友还是挺多的,都是爱学习的朋友!希望更多的朋友参与进来!像木易杨、刘小夕他们也在为社区贡献,质量都非常高,欢迎大家也关注下(呵呵,我得去收他们的广告费才行,1分也是爱)。问:你这个项目主要针对的是哪些人群呢? 答:web开发的朋友们。问:对于喜欢学习的朋友你有什么建议吗? 答:只要你真的感兴趣,剩下的就只有坚持了。问:听说你非常喜欢打羽毛球 答:这不用听说的,认识我的人都知道这个事情!问:前端里面你觉得公众号做得最好的是哪个? 答:情大的《前端早读课》,他几年前发第一篇的时候我刚好在地铁上,在这几年的时间里,我每天都会看。问:你说你的事业是父亲,怎么说呢? 答:其实生活和工作是息息相通的,作为父亲,是一种责任,对孩子的负责也是对自己的负责。问:对于前端的发展,你怎么看? 答:静下心来学习,以不变应万变。问:你做这个开源项目的目的是什么? 答:没有想过,单纯地想坚持做件事吧。其实这是为了什么呢?挣钱?挣名利?我只觉得别人能做到的,我一定也可以做得到,就是那么要强!问:在开源过程中你学到了什么? 答:学会了包容和取舍。问:在开源过程中,你觉得遇到最印象深刻的是什么? 答:有个网友加我说他通过3+1的深入学习,自己掌握了很多以前不会也没有去想过的知识点,同时也给自己找到了份好工作,最重要的是学会了主动学习。这点令我非常感动,至少有认可的,知足!问:在开源过程中,有没有发生过什么问题? 答:题目有时候会出现类似的(已经尽量避免了,后期准备做个题库管理的工具,加上点人工智能分词,就能分析出题目是否类似了)问:在开源过程中遇到最大的困难是什么? 答:是自己的坚持!刚开始时,会有各种好心的朋友提建议,随着时间的增长也会暴露出问题,比如说端午节去玩时,由于忘带电脑,就只发了issue,没有更新README,朋友们一眼就看出来了。问:为何要纯手工发布而不写个工具做自动化发布呢? 答:怕变成自动化后,我就很少关注这事了。但我后期我会写些工具来辅助,比如说题目的管理等。问:会坚持多久? 答:很久问:如果硬要加个期限呢?答:5年问:别人做的面试题都标有大厂的标签,为何你不标下 答:很多时候,我们都是小人物,也有很多人都跟我一样,并非人人都是BAT出身,每个人都是从新手一步步过来的。问:别人做的面试题都标高级、进阶之类的,为何你不标下 答:标了高级、进阶只是看着好看而已,只有自己学到了才是真货。问:宗旨是什么 答:勤思考,多动手,善总结,能坚持问:给前端人员有什么建议吗? 答:学习方法:集中学习法,分散学习法。学习是个积累的过程,希望大家能每天保持学习,平时的积累,是要深度的,不是只看下题就会了!学习本该孤独的。问:你写的死磕自己,愉悦大家是怎么理解呢? 答:推荐大家去看看罗振宇《罗辑思维》,每天早上6点发布60s语音,这年头敢死磕自己的太少了!

October 16, 2019 · 1 min · jiezi

Iframe实现单页面多tab切换界面无刷新

项目需求:需要在原MVC项目上实现单页面多tab切换,局部刷新功能。痛点:原MVC项目菜单栏使用的是a标签,利用a标签的hare属性跳转到对应界面,所以导致每个界面都得重新加载一遍;项目早已上线 正常运转,大改框架代价比较大,只得另辟蹊径。思路:通过点击菜单,动态增加Iframe,利用Iframe的src属性,将子页面与母板页结合,再通过控制Iframe的显隐,实现界面的切换,另外利用history增加路由管理功能。原MVC项目上效果实现后,自己花时间整理了一版Html+Jq实现的例子,并整理出有关Iframe和history路由的有关知识点,还有一些实现过程中遇到的小坑,供大家参考!废话少说,先上效果图源码连接(有详细注释,可根据实际需求修改,万变不离其中):https://github.com/xuqiaoba/Iframe-tab-router 关于history方法,网上已经有很多解释了,本文Demo中主要使用了window.history.pushState(state, title, url); state:一个与指定网址相关的状态对象,popstate事件触发时,该对象会传入回调函数。如果不需要这个对象,此处可以填null。可用它来传一些数据title:新页面的标题,但是所有浏览器目前都忽略这个值,因此这里可以填null。url:新的网址,必须与当前页面处在同一个域。浏览器的地址栏将显示这个网址。//监听浏览器前进后退事件window.addEventListener("popstate", function (e) { console.log(e)});浏览器的前进后退功能实现后,当时就试着全局刷新了一下,结果。。。 这很正常,浏览器地址栏里面不就是指向的这个子界面嘛。所以我就想到了监听“浏览器重新加载”事件 //监听重新加载界面事件window.onload = function (e) { window.history.pushState({ id: 1, url: './Home.html', menuname: '主界面' }, "title", './Home.html'); window.location.reload()}最初我将监听“浏览器重新加载”事件写在了母板页中,本来想着是,刷新界面,让他回到“最初的摸样”,先改变浏览器当前路由为“Home.html”,让后刷新当前界面,结果,路由有那么一瞬间是改变了,但紧接着又变回子界面路由地址了,且界面显示的还是子界面。当时有点懵了,不知道咋回事,百度一番,发现父界面刷新,其子界面也会被刷新,也就是说路由变的一瞬间是父级界面刷新了,但其子界面紧接着也跟着刷新了,所以路由马上就改变成了Iframe里面的src地址。这是我就想着将“监听重新加载界面事件”写到每个子界面中去,这下思路应该正确了吧。结果。。。被“无限嵌套”了。这也正常,既然 子界面的src被重定向成“Home.html” 了,自然每个子界面都跟母板页长得一样了呀。再冷静分析一波,需要判断当前刷新的界面是母板页还是子界面,如果是母板页,则执行 window.history.pushState({ id: 1, url:'./Home.html', menuname: '主界面' }, "title", './Home.html'); window.location.reload(),如果是子界面,则直接跳过。这里就用到了window.parent.father()方法,通过window.parent可以调用到父级界面定义的方法"father()",如果在父级界面调用window.parent.father()则会抛出异常。这里就巧妙的运用 try...catch...,完美解决这个问题。 //监听重新加载界面事件(点击浏览器按钮刷新,会进catch,点击菜单刷新,正常调用fj())window.onload = function (e) { try { window.parent.father() } catch (e) { window.history.pushState({ id: 1, url: './Home.html', menuname: '主界面' }, "title", './Home.html'); window.location.reload() }}欢迎交流,欢迎 Star (^_^)经验总结,代码加工厂! ...

October 16, 2019 · 1 min · jiezi

Zepto源代码学习一

最近开始学习Zepto源代码,分享出来,共同学习。前端新人,技术欠佳,多多见谅参考的gitbook地址感谢作者奉献 代码主体机构: 定义Zepto——核心自执行函数 函数里面的变量都为私有变量,防止污染全局var zepto = (function (){})(); 自执行函数 定义全局Zepto 核心函数 函数常用示例 $('div'); init函数: zepto.init = function (selector, context) { var dom // If nothing given, return an empty Zepto collection if (!selector) return zepto.Z() // Optimize for string selectors else if (typeof selector == 'string') { selector = selector.trim() // If it's a html fragment, create nodes from it // Note: In both Chrome 21 and Firefox 15, DOM error 12 // is thrown if the fragment doesn't begin with < if (selector[0] == '<' && fragmentRE.test(selector)) dom = zepto.fragment(selector, RegExp.$1, context), selector = null // If there's a context, create a collection on that context first, and select // nodes from there else if (context !== undefined) return $(context).find(selector) // If it's a CSS selector, use it to select nodes. else dom = zepto.qsa(document, selector) } // If a function is given, call it when the DOM is ready else if (isFunction(selector)) return $(document).ready(selector) // If a Zepto collection is given, just return it else if (zepto.isZ(selector)) return selector else { // normalize array if an array of nodes is given if (isArray(selector)) dom = compact(selector) // Wrap DOM nodes. else if (isObject(selector)) dom = [selector], selector = null // If it's a html fragment, create nodes from it else if (fragmentRE.test(selector)) dom = zepto.fragment(selector.trim(), RegExp.$1, context), selector = null // If there's a context, create a collection on that context first, and select // nodes from there else if (context !== undefined) return $(context).find(selector) // And last but no least, if it's a CSS selector, use it to select nodes. else dom = zepto.qsa(document, selector) } // create a new Zepto collection from the nodes found return zepto.Z(dom, selector) }如果传递的第一个参数为string——首字母为< 并且时html标签 创建新的DOM否则如果为正常的字符串直接获取DOM如果有第二项参数 递归调用只有单参数本方法 并且执行find方法如果传递的参数为函数——作为ready的回调传递如果已经时zepto对象 直接返回如果是DOM数组 如果是单个DOM如果是html片段 ...

October 15, 2019 · 2 min · jiezi

BS-工业互联网-地铁行业

前言近几年,互联网与交通运输的融合,改变了交易模式,影响着运输组织和经营方式,改变了运输主体的市场结构、模糊了运营与非营运的界限,也更好的实现了交通资源的集约共享,同时使得更多依靠外力和企业推动交通信息化成为可能。互联网交通具有巨大的潜力、发展迅速、生态浩大,需要政府顺势而为,紧跟发展态势,加强引导、转变职能、创新政府管理与市场监管的模式。而城市轨道交通的投资体量巨大,一条线路动辄上百亿元,如何保证投资效益、提升投资管理工作的精确性和可控性是当务之急。应引入“互联网+”思维,研发基于“互联网+”的城市轨道交通系统。在分析现有投资管理存在问题基础上,这里对该系统的应用特点及主要功能进行了深入阐述,旨在完善提高系统的功能分布和用户体验。 http://www.hightopo.com/demo/... 代码实现场景搭建我们先来搭建基础场景,因为这个场景是在 2D 的基础上实现的,因此我们需要用拓扑组件 ht.graph.GraphView 来搭建基础场景: dataModel = new ht.DataModel();// 数据容器,用来存储数据节点graphView = new ht.graph.GraphView(dataModel);// 拓扑组件graphView.addToDOM();// 将拓扑组件添加到 body 体中上面代码中出现的 addToDOM 方法将组建添加到 DOM 的 body 中,HT(https://hightopo.com)的组件一般都会嵌入 BorderPane、SplitView 和 TabView 等(均为 HT 的组件)容器中使用,而最外层的 HT 组件则需要用户手工将 getView() 返回的底层 div 元素添加到页面的 DOM 元素中,这里需要注意的是,当父容器大小变化时,如果父容器是 BorderPane 和 SplitView 等这些 HT 预定义的容器组件,则 HT 的容器会自动递归调用孩子组件 invalidate 函数通知更新。但如果父容器是原生的 html 元素, 则 HT 组件无法获知需要更新,因此最外层的 HT 组件一般需要监听 window 的窗口大小变化事件,调用最外层组件 invalidate 函数进行更新。 为了最外层组件加载填充满窗口的方便性,HT 的所有组件都有 addToDOM 函数,其实现逻辑如下,其中 iv 是 invalidate 的简写: ...

October 15, 2019 · 3 min · jiezi

defer和async的区别

当浏览器碰到script脚本的时候: <script src="script.js"></script>没有defer或async,浏览器会立即加载并执行指定的脚本,“立即”指的是在渲染该script标签之下的文档元素之前,也就是说不等待后续载入的文档元素,读到就加载并执行。 <script async src="script.js"></script>有async,加载和渲染后续文档元素的过程将和script.js的加载与执行并行进行(异步)。 <script defer src="myscript.js"></script>有defer,加载后续文档元素的过程将和script.js的加载并行进行(异步),但是script.js的执行要在所有元素解析完成之后,DOMContentLoaded事件触发之前完成。 蓝色线代表网络读取,红色线代表执行时间,这俩都是针对脚本的;绿色线代表 HTML 解析。 此图告诉我们以下几个要点: _defer_和_async_在网络读取(下载)这块儿是一样的,都是异步的(相较于 HTML 解析)它俩的差别在于脚本下载完之后何时执行,显然_defer_是最接近我们对于应用脚本加载和执行的要求的关于_defer_,此图未尽之处在于它是按照加载顺序执行脚本的,这一点要善加利用_async_则是一个乱序执行的主,反正对它来说脚本的加载和执行是紧紧挨着的,所以不管你声明的顺序如何,只要它加载完了就会立刻执行仔细想想,_async_对于应用脚本的用处不大,因为它完全不考虑依赖(哪怕是最低级的顺序执行),不过它对于那些可以不依赖任何脚本或不被任何脚本依赖的脚本来说却是非常合适的,最典型的例子:Google Analytics

October 15, 2019 · 1 min · jiezi

css-计算器中显示的数字字体

地址 使用: 1.网络上下载需要的 .ttf 格式的语言包,在css导入: @font-face { font-family: mFont; src: url('/fonts/font-chenjishi.ttf'); } 2.需要的字体引用: span{ font: bold 30px mFont; //简写,原font-family: mFont; }

October 15, 2019 · 1 min · jiezi

第六篇-仿写Vue生态系列模板loader与计算属性

( 第六篇 )仿写'Vue生态'系列___"模板loader与计算属性"本次任务 编写'cc-loader', 使我们可以使用'xxx.cc'文件来运行我的框架代码.为'cc_vue'添加生命周期函数.新增'计算属性'.新增'观察属性'.一.'cc-loader'的定义与编写本次只是编写一个最基础的版本, 后续完善组件化功能的时候, 会对它有所改动.使'webpack'可以解析后缀为'cc'的文件.必须做到非常的轻量.让我们一步一步来做出这样一个'loader', 首先我先介绍一下文件结构, 在'src'文件夹平级建立'loader'文件夹, 里面可以存放以后我做的所有'loader'. 不可或缺的步骤就是定义'loader'的路径.cc_vue/config/common.js新增resolveLoader项 resolveLoader: { // 方式1: // 如果我书写 require('ccloader'); // 那么就会去 path.resolve(__dirname, '../loader')寻找这个引入. alias: { ccloader: path.resolve(__dirname, '../loader') }, // 方式2: 当存在require('xxx');这种写法时, 先去'node_modules'找寻, 找不到再去path.resolve(__dirname,'../loader')找找看. modules:[ 'node_modules', path.resolve(__dirname,'../loader') ] },'loader'文件的配置写完了, 那么可以开始正式写这个'loader'了.cc_vue/loader/cc-loader.js // 1: 'source'就是你读取到的文件的代码, 他是'string'类型.function loader(source) { // ..具体处理函数 // 2: 处理完了一定要把它返回出去, 因为可能还有其他'loader'要处理它, 或者是直接执行处理好的代码. return source;}module.exports = loader;模板的定义 本次暂不处理title, 因为没啥技术含量暂时也没必要.'#--style-->' 会被替换为css的内容.'#--template-->' 会被替换为模板的内容.<!DOCTYPE html><html lang='en'> <head> <meta charset='UTF-8' /> <meta name='viewport' content='width=device-width, initial-scale=1.0' /> <meta http-equiv='X-UA-Compatible' content='ie=edge' /> <title>编译模板</title> #--style--> </head> <body> <div id="app"> #--template--> </div> </body></html>最终要达到的'.cc'文件的书写方式 ...

October 15, 2019 · 3 min · jiezi

魅族官网基于-nextjs-重构实践总结与分享

项目背景俗话说,脱离业务谈代码的都是耍流氓。在此我先简单介绍下重构项目的背景。 截图镇楼:魅族官网首页 在 2015 年,公司前端大佬猫哥基于 FIS3 深度定制开发了一套前端工程体系 mz-fis,该框架经历3年来的网站改版升级需求,都很好的完成了需求任务。 但随着项目越来越大,以及前端技术快速迭代。老项目的痛点越发明显。 此次重构解决了那些痛点1.随着项目越来越大,前端编译打包流程巨慢。(算上图片视频等资源,仓库有3.9G大小)2.运营需要经常改动网站内容,由于需要SEO,哪怕改几个字也需要前端打包发布。3.旧框架的核心还是Jquery,虽然结果3年开发积累了很多组件,但在数据维护、模块化以及开发体验上已经落后了。 以上痛点想必手上有老项目的,都感同身受。改起来伤筋动骨,但不改吧工作效率太低了。 此次重构需要满足哪些要求再说说重构的基本要求,咱得渐进增强而不是优雅降级。:D 1.支持SEO,也就是说需要服务端渲染。2.解放前端、测试劳动力,让运营在网站内容管理平台编辑数据后发布,官网及时生效。(不同于传统AJAX,这里数据需要SEO)。3.支持多国语言。4.需要新旧框架同存,同域名下无缝对接,要求两套工作流都可以正常工作。(一些不频繁改动的页面,可以不改,减少重构成本)。5.更快的页面性能、更畅快的开发体验和更好可维护性。 此次重构技术选型首先,服务端渲染 SSR 是没跑了,它可以更快渲染首屏,同时对 SEO 更友好。 于是我在带着鸭梨与小兴奋寻遍各大SSR方案后,最终选择了 Next.jsNext.js 是一个轻量级的 React 服务端渲染应用框架。目前在 github 已获得 4W+ 的 star。 之所以火爆,是因为它有以下优点:1.默认服务端渲染模式,以文件系统为基础的客户端路由2.代码自动分隔使页面加载更快3.简洁的客户端路由(以页面为基础的)4.以webpack的热替换为基础的开发环境5.使用React的JSX和ES6的module,模块化和维护更方便6.可以运行在其他Node.js的HTTP 服务器上7.可以定制化专属的babel和webpack配置 这里不做过多讲解了,大家可以访问 next.js中文网、github地址了解更多。 重构过程中遇到的问题以及解决方案问题一:网站采用 next.js 的 start 模式服务,还是 export 出静态化文件让 ngxin 做web服务两种方案都可行,但各有优缺点。 考虑到运营并不在乎那点等待时间,相比之下项目稳定性更重要。于是选择方案二:「export 出静态化文件让 ngxin 做web服务」。 ok~ 选定后要做的就是静态化了。 问题二:如何静态化如何做呢? 恩... 最简单的就是 cd 到项目目录下 npm run build && npm run export 下,打包出文件到./out文件夹,然后打个zip包扔服务器上。当然,为了运营数据及时更新,你得24小时不停重复以上步奏,还不能手抖出错。 为了不被同事打死,我设计了一套开发流程,在项目中写一个shell脚本: #!/bin/bashecho node版本:$(node -v)BASEDIR=$(dirname $0)cd ${BASEDIR}/../sudo npm run buildwhile true;do whoami && pwd sudo npm run export >/dev/null 2>&1 || continue sudo chown -R {服务器用户名} ./out || echo 'chown Err' sudo cp -ar ./out/* ./www || echo 'cp Err' sudo chown -R {服务器用户名} ./www || echo 'chown Err' echo '静态化并复制完毕' sleep 15done好了,只要执行这段 shell,你的服务器就会cd到项目目录,先build构建项目,然后每间隔15秒构建一次。并输出当前环境和相关信息。 ...

October 14, 2019 · 5 min · jiezi

利用Python进行数据分析12-pandas基础-数据合并

https://mp.weixin.qq.com/s?__biz=MzU2NTc1MTc5MQ==&mid=2247484379&idx=1&sn=c1b76fd6dea196085924b095f9532542&chksm=fcb7b95bcbc0304d512fdf7c2737efe68a0c88282101f5e6a902d43878690839e3d4912c2c2c&token=167148415&lang=zh_CN#rd

October 14, 2019 · 1 min · jiezi

基于阿里egg框架搭建博客5置顶导航条

相关文章基于阿里egg框架搭建博客(1)——开发准备基于阿里egg框架搭建博客(2)——Hello World基于阿里egg框架搭建博客(3)——注册与登录基于阿里egg框架搭建博客(4)——权限控制基于阿里egg框架搭建博客(5)——置顶导航条基于阿里egg框架搭建博客(6)——浏览、发表文章基于阿里egg框架搭建博客(7)——编辑文章 githttps://github.com/ZzzSimon/e...喜欢就点个赞吧! 正文模板继承导航条是博客不可或缺的一部分,几乎每一个页面都有置顶导航条。我们不可能在每个页面都复制一份相同的代码,因为这样代码变得冗余,而且当需要修改导航条时,改动量会非常之大。所幸的是,我们使用了nunjucks作为view模板,其提供的模板继承功能可以解决这个问题。 官方文档:https://nunjucks.bootcss.com/...页面设计 功能设计如页面设计图中所示,导航条共有6块功能: 站点名称,点击后可以回到首页文章按钮,点击后可以查看文章列表搜索框,可以按文章名称搜索文章发表文章按钮,顾名思义,可以发表博文用户头像下拉按钮,我的文章可以查看自己的文章或重新编辑设置,可以修改个人信息注销,注销用户,删除session,返回登录父模板parent.tpl代码(包含导航条)我们创建/app/view/parent.tpl文件: <!DOCTYPE html><html><head> <link rel="stylesheet" href="/public/bootstrap/css/bootstrap.css"> <script type="text/javascript" src="/public/js/jquery.min.js"></script> <script type="text/javascript" src="/public/bootstrap/js/bootstrap.min.js"></script> {% block head %}{% endblock %}</head><body><div id="nav"> <nav class="navbar navbar-default navbar-fixed-top"> <div class="container-fluid"> <div class="navbar-header"> <a class="navbar-brand" href="/">妖云小离</a> </div> <div class="collapse navbar-collapse"> <ul class="nav navbar-nav"> <li><a href="/articleList.htm">文章</a></li> <li class="dropdown"> <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">预留 <span class="caret"></span></a> <ul class="dropdown-menu"> <li><a href="#">Action</a></li> <li><a href="#">Another action</a></li> <li><a href="#">Something else here</a></li> <li role="separator" class="divider"></li> <li><a href="#">Separated link</a></li> <li role="separator" class="divider"></li> <li><a href="#">One more separated link</a></li> </ul> </li> </ul> <form class="navbar-form navbar-left" action="/search?_csrf={{ ctx.csrf | safe }}"> <div class="input-group"> <input type="text" class="form-control" placeholder="搜索" name="keyword"> <span class="input-group-btn"> <button class="btn btn-default" type="submit"> <span class="glyphicon glyphicon-search " aria-hidden="true"></span> </button> </span> </div> </form> <ul class="nav navbar-nav navbar-right"> <li><a href="/edit.htm"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span> 发表文章</a> </li> <li class="dropdown"> <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"> <img src="" id="avatarNav" class="img-circle" style="width: 26px; margin-top: -6px"> <span class="caret"></span></a> <ul class="dropdown-menu"> <li><a href="/myarticle.htm">我的文章</a></li> <li><a href="/myInfo.htm">设置</a></li> <li role="separator" class="divider"></li> <li><a href="/user/logout">注销</a></li> </ul> </li> </ul> </div> </div> </nav></div><div id="top" class="row" style="margin-top: 10%"></div><div class="container"> {% block content %}{% endblock %}</div><script type="text/javascript"> function getCookie(c_name) { if (document.cookie.length > 0) { c_start = document.cookie.indexOf(c_name + "=") if (c_start != -1) { c_start = c_start + c_name.length + 1 c_end = document.cookie.indexOf(";", c_start) if (c_end == -1) c_end = document.cookie.length return unescape(document.cookie.substring(c_start, c_end)) } } return "" } $('#avatarNav').attr('src', getCookie('avatarUrl'));</script>{% block script %}{% endblock %}</body></html>父模板中可以继承重写的地方有3处: ...

October 14, 2019 · 2 min · jiezi

基于阿里egg框架搭建博客3注册与登录

相关文章基于阿里egg框架搭建博客(1)——开发准备基于阿里egg框架搭建博客(2)——Hello World基于阿里egg框架搭建博客(3)——注册与登录基于阿里egg框架搭建博客(4)——权限控制基于阿里egg框架搭建博客(5)——置顶导航条基于阿里egg框架搭建博客(6)——浏览、发表文章基于阿里egg框架搭建博客(7)——编辑文章 githttps://github.com/ZzzSimon/e...喜欢就点个赞吧! 正文俗话说万事开头难,此章节涉及大量的知识点,在每个代码后面都有解释,需要大家查看官方文档。 user表设计简单来说,注册与登录就是对user表的读写。所以我们首先对user表进行设计: 字段说明字段解释iduuidusername用户名password密码phone手机号create_time创建时间update_time更新时间avatar_url头像urlsql脚本DROP TABLE IF EXISTS `user`;CREATE TABLE `user` ( `id` varchar(20) NOT NULL, `username` varchar(18) NOT NULL, `password` varchar(20) NOT NULL, `phone` varchar(11) DEFAULT NULL, `create_time` datetime NOT NULL, `update_time` datetime NOT NULL, `avatar_url` varchar(255) DEFAULT NULL, PRIMARY KEY (`username`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;注册页面设计页面设计如上图所示,需要用户输入用户名,密码,手机号,还可以上传自己的头像。 前端代码官方文档推荐我们使用nunjucks作为模板。 使用方法:https://eggjs.org/zh-cn/intro...我们在app\view\home目录下创建register.tpl文件: <html><head> <title>注册</title> <link rel="stylesheet" href="/public/bootstrap/css/bootstrap.css"> <script type="text/javascript" src="/public/js/jquery.min.js"></script> <script type="text/javascript" src="/public/bootstrap/js/bootstrap.min.js"></script></head><body><div class="container "> <form class="center-block" style="width: 50%;margin-top: 10%" method="POST" action="/user/register?_csrf={{ ctx.csrf | safe }}" enctype="multipart/form-data"> <div class="form-group "> <img src="/public/avatar/default.jpg" id="avatarPic" class="img-circle center-block" style="width: 64px;"> <input type="file" id="avatarBtn" name="file" style="visibility: hidden"> <p class="text-center help-block">点击头像更改,只支持jpg,png格式,大小≤ 200 kb</p> </div> <div class="form-group"> <label for="username">账号</label> <input type="text" class="form-control" id="username" placeholder="用户名" name="username"> </div> <div class="form-group"> <label for="password">密码</label> <input type="password" class="form-control" id="password" placeholder="密码" name="password"> </div> <div class="form-group"> <label for="phone">手机号</label> <input type="text" class="form-control" id="phone" placeholder="手机号" name="phone"> </div> <div class="form-group"> <button type="submit" class="btn btn-info pull-right">注册</button> </div> </form></div><script> $('#avatarPic').bind('click', function () { $('#avatarBtn').click(); }); $('#avatarBtn').bind('change',function (e) { if (window.FileReader) { var reader = new FileReader(); reader.readAsDataURL(e.target.files[0]); //监听文件读取结束后事件 reader.onloadend = function (e) { $('#avatarPic').attr("src",e.target.result); //e.target.result就是最后的路径地址 }; } });</script></body></html>有3点需要注意: ...

October 14, 2019 · 4 min · jiezi

基于阿里egg框架搭建博客4权限控制

相关文章基于阿里egg框架搭建博客(1)——开发准备基于阿里egg框架搭建博客(2)——Hello World基于阿里egg框架搭建博客(3)——注册与登录基于阿里egg框架搭建博客(4)——权限控制基于阿里egg框架搭建博客(5)——置顶导航条基于阿里egg框架搭建博客(6)——浏览、发表文章基于阿里egg框架搭建博客(7)——编辑文章 githttps://github.com/ZzzSimon/e...喜欢就点个赞吧! 正文上一篇文章我们实现了用户的注册与登录,接下来就需要对用户权限进行控制了,比如:普通用户只能评论,管理员可以发表文章,最高管理员可以修改用户权限等等。由于权限控制是一个通用的功能,我们把这块功能做成中间件。关于中间件: 官方文档:https://eggjs.org/zh-cn/basic...功能设计一个用户对应1个角色可以通过配置文件配置,某一个角色无权限使用的页面与接口可以配置无需验证用户与权限的path。比如:登录与注册的相关页面与接口只有登录过才能访问的path,否则跳转登录页。User表,增加role(角色)字段 配置文件我们在config/config.default.js中加入以下内容: auth : { noAuth:['/login.htm','/user/login','/register.htm','/user/register'], noPermission:{ admin:[], manager:['/admin.htm'], user:['/admin.htm','/edit.htm'] } }其中:noAuth节点配置的是无需验权就能访问的pathnoPermission节点配置的是各个角色无权限访问的path auth.js中间件代码我们创建app/middleware/auth.js文件: module.exports = (options, app) => { return async function auth(ctx, next) { //如果用户session没失效 if (typeof (ctx.session.user) !== 'undefined') { const username = ctx.session.user.username; //这里有两种做法,第一种每次都查库校验角色,优点:实时,角色变更对用户无感。缺点:查库效率低,可考虑用redis //第二种,把角色信息放进session,优点:无需查库,效率高。缺点:角色变更时需额外逻辑来处理老的session,否则客户端的用户角色无法实时更新 const role = await ctx.service.user.getRoleByUsername(username); const noPerList = options.noPermission[role]; if (noPerList && !noPerList.includes(ctx.path)) { await next(); } else { ctx.body = '无权限,请联系网站管理员!'; } //登录注册页面不需要权限 } else if (options.noAuth.includes(ctx.path)) { await next(); //如果session失效后则重定向到登录页 } else { ctx.redirect('/login.htm') } }};效果我们创建一个用户,并给与他user角色,由配置文件可以看出,user角色无权限访问/edit.htm路径。如图: ...

October 14, 2019 · 1 min · jiezi

前端工程师学Docker-看这篇就够了-原创精读

前端工程师,为什么要学习Docker ?传统的虚拟机,非常耗费性能 Docker可以看成一个高性能的虚拟机,并且不会浪费资源,主要用于Linux环境的虚拟化,类似VBox这种虚拟机,不同的是Docker专门为了服务器虚拟化,并支持镜像分享等功能。前端工程师也可以用于构建代码等等目前看,Dokcer不仅带火了GO语言,还会持续火下去 首先,我们看看传统的虚拟机和Docker的区别传统的虚拟机: Docker: 可以看到,传统的虚拟机是每开一个虚拟机,相当于运行一个系统,这种是非常占用系统资源的,但是Docker就不会。但是也做到了隔离的效果 Docker容器虚拟化的优点:环境隔离Docker实现了资源隔离,实现一台机器运行多个容器互不影响。 更快速的交付部署使用Docker,开发人员可以利用镜像快速构建一套标准的研发环境,开发完成后,测试和运维人员可以直接通过使用相同的环境来部署代码。 更高效的资源利用Docker容器的运行不需要额外的虚拟化管理程序的支持,它是内核级的虚拟化,可以实现更高的性能,同时对资源的额外需求很低。 更易迁移扩展Docker容器几乎可以在任意的平台上运行,包括乌力吉、虚拟机、公有云、私有云、个人电脑、服务器等,这种兼容性让用户可以在不同平台之间轻松的迁移应用。 更简单的更新管理使用Dockerfile,只需要小小的配置修改,就可以替代以往的大量的更新工作。并且所有修改都是以增量的方式进行分发和更新,从而实现自动化和高效的容器管理。 正式开始本文撰写于2019年10月13日 电脑系统:Mac OS 使用最新版官网下载的Docker 以下代码均手写,可运行 下载官网的Docker安装包,然后直接安装 https://www.docker.com/ Docker官网下载地址安装后直接打开 打开终端命令行,输入docker,会出现以下信息,那么说明安装成功 下载安装成功后,首先学习下Docker的两个核心知识点 container(容器)和image(镜像) Docker的整个生命周期由三部分组成:镜像(image)+容器(container)+仓库(repository) 思维导图如下: 该如何理解呢?每台宿主机(电脑),他下载好了Docker后,可以生成多个镜像,每个镜像,可以创建多个容器。发布到仓库时,以镜像为单位。可以理解成:一个容器就是一个独立的虚拟操作系统,互不影响,而镜像就是这个操作系统的安装包。想要生成一个容器,就用安装包(镜像)生成一次 上面就是Docker的核心概念,下面开始正式操作 补充一点:如果想深入Docker , 还是要去认真学习下原理,今天我们主要讲应用层面的 首先,我们回到终端命令行操作 输入: docker images如果你的电脑上之前有创建过的镜像,会得到如下: 如果没有的话就是空~ 我们首先创建一个自己的镜像 先编写一个Node.js服务 创建index.js // index.jsconst Koa = require('koa');const app = new Koa();app.use(async ctx => { ctx.body = 'Hello docker';});app.listen(3000);然后配置package.json文件 { "name": "app", "version": "1.0.0", "private": true, "scripts": { "start": "node server.js" }, "dependencies": { "koa": "^2.5.0" } } 正常情况下 使用npm start 或 node index.js 就可以启动服务可是我们这里需要打包进Docker中,这里就需要写一个配置文件dockerfile ...

October 14, 2019 · 2 min · jiezi

基于阿里egg框架搭建博客2HelloWorld

相关文章基于阿里egg框架搭建博客(1)——开发准备基于阿里egg框架搭建博客(2)——Hello World基于阿里egg框架搭建博客(3)——注册与登录基于阿里egg框架搭建博客(4)——权限控制基于阿里egg框架搭建博客(5)——置顶导航条基于阿里egg框架搭建博客(6)——浏览、发表文章基于阿里egg框架搭建博客(7)——编辑文章 githttps://github.com/ZzzSimon/e...喜欢就点个赞吧! 正文这是必备的Hello World章节,本章节将不使用脚手架,逐步创建一个hello world web应用。 初始化项目先来初始化下目录结构: $ mkdir egg-hello-world$ cd egg-hello-world$ npm init$ npm i egg --save$ npm i egg-bin --save-dev执行完成后如下图所示:除了下载的node模块以外什么都没有,不要着急,我们接下来会一点点创建。 添加 npm scripts 到 package.json: { "name": "egg-example", "scripts": { "dev": "egg-bin dev" }}编写Controller上一节我们知道,controller是需要放在app/controller/目录下的,所以我创建helloWorld.js文件: // app/controller/home.jsconst Controller = require('egg').Controller;class HelloWorldController extends Controller { async index() { this.ctx.body = 'Hello World'; }}module.exports = HelloWorldController;编写路由规则egg将路由交由app/router.js管理,于是我们在app/目录下创建router.js文件: // app/router.jsmodule.exports = app => { const { router, controller } = app; router.get('/', controller.helloWorld.index);};配置文件最后加上一个配置config/config.default.js文件:注意:config与app为同级目录! ...

October 14, 2019 · 1 min · jiezi

从零到一实现微信H5视频行内autoplay

写在前面不知不觉又到了2019年的深秋,想不到上一篇文章孩子还没出生,这一篇就已经半岁了。创业加上带孩子,时间会过得飞快。在这里劝大家还是不要过早创业(gank),多多学习(发育)才实际。打工虽不自由,起码安稳,面对任务和书本,胜于面对盈利还是亏本。 废话不多说,以下正文。 通常会出现的需求微信进入H5后,自动播放视频在流行终端上体验尽量一致可在视频上叠加UI转化为技术需求视频需要自动播放如何兼容iOS和安卓视频需要行内播放PS:要叠加UI,就得是行内播放而非全屏,iOS倒好,安卓的微信用的X5内核,一言难尽,卡住不少人,网上求助相关问题的不在少数。 来个简单的demo 查看demo仓库地址PS:在微信中打开才能自动播放哦。 关键代码块<div class="container"> <!-- For iOS --> <video src="https://static.shikehuyu.com/vincent/wx-video-demo/movie.mp4" playsinline webkit-playsinline loop> </video> <!-- For Android --> <canvas></canvas> <!-- 示例弹幕 --> <div class="danmu">示例弹幕,表示你可以放任意UI在视频上面</div></div><style>video { width: 80vw; height: 80vw; object-fit: contain; object-position: center; display: none;}canvas { display: none;}</style>function initVideo() { var isAndroid = window.navigator.userAgent.match(/android/ig) if (isAndroid) { // 安卓 var src = "https://static.shikehuyu.com/vincent/wx-video-demo/movie.ts" player = new JSMpeg.Player(src, { canvas: canvas, autoplay: true, progressive: false, loop: true, onVideoDecode: function() { canvas.style.display = 'block' canvas.style.height = 80 / (canvas.width / canvas.height) + "vw" } }) } else { // iOS player = video video.style.display = 'block' }}window.onload = function() { initVideo() // 自动播放 document.addEventListener('WeixinJSBridgeReady', () => { player.play() })}实现要点区分开iOS和安卓,iOS用原生video标签,安卓用JSMpeg,绘制画面到canvas上。iOS用mp4或者其他原生video标签支持的视频格式,安卓用ts格式。(其中ts格式需要用ffmpeg来转一下,下文会提及)监听WeixinJSBridgeReady事件,调用视频播放方法,实现自动播放。什么是ts文件来自百度百科ts即"Transport Stream"的缩写。MPEG2-TS格式的特点就是要求从视频流的任一片段开始都是可以独立解码的。简单地说就是视频数据流,将mp4等格式视频转换成ts后,就可以一段段进行解析,可用于视频直播。JSMpeg就是通过解析视频数据,然后绘制在canvas上,来实现视频播放的。 ...

October 14, 2019 · 1 min · jiezi

移动端布局基础概念指南

前言这篇文章主要讨论了移动端页面渲染与布局的一些基本概念例如 viewport 和 css 像素, 这些内容是了解移动端页面适配的基本前提. 在这篇文章中记录了这些基本的概念, 因为我并不从事移动端开发, 文章有误, 欢迎指正. 移动端渲染表现为了简单起见, 我们不从概念讲起, 我们先来看看一个固定宽度的元素被放置到移动端浏览器中会发生什么. 有如下代码: <!DOCTYPE html><html><head> <meta charset="UTF-8"> <title>Document</title> <style> .example{ width: 900px; background-color: aqua; } </style></head><body> <div class="example"> 我的宽度是 900px </div></body></html>当然桌面浏览器渲染效果肯定在我们意料之中啦✨: 图片: 1920px下chrome渲染的效果: 而下面展示了图片展示了几个移动端浏览器渲染的结果: 图片: 移动端浏览器渲染效果: 这里我们简单的介绍一下图片中浏览器的版本, 这些浏览器在后文的截图中版本都是不会发生变化的. 浏览器版本平台chrome75windows10chrome75android9edge42android9Samsung9.3android9仔细观察我们发现:900px 宽的 div 没有占满屏幕, 也就是说屏幕的宽度比 900px 还要大. 那么屏幕宽度到底是多大呢, 我们插入一行代码来获取HTML元素的宽度: <script> document.write(`html元素的宽度是${document.documentElement.clientWidth}`);</script>不同浏览器的显示结果为: 他们都输出了同样的数据那就是 980 在某种程度上我们知道了页面的宽度, 原来页面是 980px 的宽度所以 900px 的div无法铺满一行. 对于移动浏览器它感知到自己的视口的宽度是 980px, 此时它渲染的比例就和一个 横向分辨率为 980px 的桌面显示器渲染的一样. 只不过移动终端的屏幕是一个小号的显示器而已.在没有更改页面的设置的情况下或者说默认的情况下, 移动终端的浏览器会按照 980px 的宽度来渲染页面, 然后再将页面缩放到适合屏幕的大小. ...

October 13, 2019 · 4 min · jiezi

React-源码阅读7038

React 源码阅读-7memoReact.memo 为高阶组件。它与 React.PureComponent 非常相似,但它适用于函数组件,但不适用于 class组件。 const MyComponent = React.memo(function MyComponent(props) { /* 使用 props 渲染 */});如果你的函数组件在给定相同 props 的情况下渲染相同的结果,那么你可以通过将其包装在 React.memo 中调用,以此通过记忆组件渲染结果的方式来提高组件的性能表现。这意味着在这种情况下,React 将跳过渲染组件的操作并直接复用最近一次渲染的结果。 此方法仅作为性能优化的方式而存在。但请不要依赖它来“阻止”渲染,因为这会产生 bug。 默认情况下其只会对复杂对象做浅层对比,如果你想要控制对比过程,那么请将自定义的比较函数通过第二个参数传入来实现 function MyComponent(props) { /* 使用 props 渲染 */}function areEqual(prevProps, nextProps) { /* 如果把 nextProps 传入 render 方法的返回结果与 将 prevProps 传入 render 方法的返回结果一致则返回 true, 否则返回 false */}export default React.memo(MyComponent, areEqual);何时使用React.memo()组件经常重新渲染,又是差不多的内容.纯展示组件,渲染相同的props,比如只是数字的更新,其他无变化. // Initial render<MovieViewsRealtime views={0} title="Forrest Gump" releaseDate="June 23, 1994"/>// After 1 second, views is 10<MovieViewsRealtime views={10} title="Forrest Gump" releaseDate="June 23, 1994"/>// After 2 seconds, views is 25<MovieViewsRealtime views={25} title="Forrest Gump" releaseDate="June 23, 1994"/>function MovieViewsRealtime({ title, releaseDate, views }) { return ( <div> <MemoizedMovie title={title} releaseDate={releaseDate} /> Movie views: {views} </div> )}// etcReact.memo() and callback functions这里的 callback 指的是usecallbackreact新增的api.还没看到那一部分,暂时先 mark 一下 ...

October 13, 2019 · 1 min · jiezi

高清屏下canvas重置尺寸引发的问题

我们知道,清空canvas画布内容有以下两个方法。第一种方法是cearRect函数: context.cearRect(0,0,canvas.width,canvas.height)第二种方法就是用原值重新设置一下canvas的宽(或者高) canvas.width = canvas.width// or canvas.height = canvas.height第二种方法可以起作用,是因为canvas的一个特点: 每当画布的高度或宽度被重设时,画布内容就会被清空。相关内容可以参考https://www.w3school.com.cn/html5/att_canvas_width.asp在一个可视化项目中,我们发现在一些电脑上面总是会出现效果错乱的情况。经过调试,我们发现,原来是“canvas.width = canvas.width”惹的祸。普通屏幕下面下不会有问题,但是如果屏幕是高清屏,就会出现问题。这是因为,高清屏下,我们为了处理绘制图形模糊的问题,通常会做如下处理: function setupCanvas(canvas) { let width = canvas.width, height = canvas.height, dpr = window.devicePixelRatio || 1.0; if (dpr != 1.0 ) { canvas.style.width = width + "px"; canvas.style.height = height + "px"; canvas.height = height * dpr; canvas.width = width * dpr; ctx.scale(dpr, dpr); } }我们知道,高清屏下window.devicePixelRatio都大于1。所以在绘图之前画笔会被缩放: ctx.scale(dpr, dpr);我们知道cavnas是基于状态的绘图组件。 其中缩放比例值也在状态管理之中。 当我们重新设置canvas的宽(高也一样)的时候,不仅会清空canvas的画布内容,同时还会把绘图状态重置到最原始的状态,原始状态下画笔的缩放比例是1,缩放比例值会被重置为1,因而导致绘制效果错乱。 如果读者不清楚“高清屏下canvas处理绘制图形模糊及处理方式”和“canvas的绘制状态”等知识点不清楚,建议学习相关知识,也推荐有兴趣读者,订阅我的专栏:Canvas高级进阶 https://xiaozhuanlan.com/canvas,相关知识会在本文也是摘录自专栏的部分内容并改编而成的。欢迎关注公众号“ITman彪叔”。彪叔,拥有10多年开发经验,现任公司系统架构师、技术总监、技术培训师、职业规划师。在计算机图形学、WebGL、前端可视化方面有深入研究。对程序员思维能力训练和培训、程序员职业规划有浓厚兴趣。

October 13, 2019 · 1 min · jiezi

React-源码阅读6037

React 源码阅读-6lazyReact.lazy 函数能让你像渲染常规组件一样处理动态引入(的组件)。 React.lazy 接受一个函数,这个函数需要动态调用 import()。它必须返回一个 Promise,该 Promise 需要 resolve 一个 defalut export 的 React 组件。 React.lazy并不适合SSR import type {LazyComponent, Thenable} from 'shared/ReactLazyComponent';import {REACT_LAZY_TYPE} from 'shared/ReactSymbols';import warning from 'shared/warning';export function lazy<T, R>(ctor: () => Thenable<T, R>): LazyComponent<T> { let lazyType = { $$typeof: REACT_LAZY_TYPE, _ctor: ctor, // React uses these fields to store the result. _status: -1, _result: null, }; if (__DEV__) { // In production, this would just set it on the object. let defaultProps; let propTypes; Object.defineProperties(lazyType, { defaultProps: { configurable: true, get() { return defaultProps; }, set(newDefaultProps) { warning( false, 'React.lazy(...): It is not supported to assign `defaultProps` to ' + 'a lazy component import. Either specify them where the component ' + 'is defined, or create a wrapping component around it.', ); defaultProps = newDefaultProps; // Match production behavior more closely: Object.defineProperty(lazyType, 'defaultProps', { enumerable: true, }); }, }, propTypes: { configurable: true, get() { return propTypes; }, set(newPropTypes) { warning( false, 'React.lazy(...): It is not supported to assign `propTypes` to ' + 'a lazy component import. Either specify them where the component ' + 'is defined, or create a wrapping component around it.', ); propTypes = newPropTypes; // Match production behavior more closely: Object.defineProperty(lazyType, 'propTypes', { enumerable: true, }); }, }, }); } return lazyType;}使用前 ...

October 13, 2019 · 2 min · jiezi

H5唤醒App快速直达App核心页面

在这个流量为王的互联网背景下,移动端的H5页面显然在导流上承担着重要作用,在H5页面上,我们对引流的需求有两种: 一是引导已下载用户从H5页面唤醒App并直达指定场景二是引导未下载用户从H5页面下载App,首次打开App时直达指定场景从运营角度来看,引导已下载用户打开App,能提高用户粘性和活跃度,而用户在App内的产品体验自然也比H5页面要好;引导未下载用户下载App并进入指定页面,显然能给用户更好的产品初体验。 这里其实就解释了我们做H5唤醒App并直达指定页面的必要性。 涉及哪些要素?唤醒App这件事,在不同平台要采用不同的方法,主要是这三个: URL SchemeUniversal LinkAndroid App Links1、URL Scheme URL Scheme是iOS、Android都兼容的机制,只需要原生App开发时注册Scheme即可,用户点击此类链接时,会自动唤醒App,并借助URL Router机制跳转到指定页面。 <scheme name> : <hierarchical part> [ ? <query> ] [ # <fragment> ]<scheme name>:是scheme的名称,代表着协议名称。<hierarchical part>:它包含 authority 和 path。<query>:可选项目,隔开或&隔开的键值对<key>=<value><fragmentg> :可选项目包,其它额外的标识信息 尽管URL Scheme兼容性高,但却存在许多限制,比如: 国内各个厂商浏览器差异很大,当要被唤醒的目标App未安装时,这个链接很容易出错。当注册有多个Scheme相同的时候,目前是没有办法区分的。不支持从其他App中的UIWebView中跳转到目标App。被部分主流平台禁止,微信、微博、QQ浏览器、手机百度中都已经被禁止使用。正是由于这些限制的存在,苹果和安卓都不约而同发布了自己的第二套方案:iOS的Universal Link、Android的App Links。 2、Universal Link Universal Link是iOS9后苹果推出的通用链接技术,能够方便的通过一个https链接来打开App指定页面,不需要额外的判断,如果没有安装App,可以跳转到自定义地址。 相对Scheme的优势在于,Universal Link是一个Web Link,因此少了很多麻烦: 当用户已安装该App时,不需要加载任何页面,能够立即唤醒App,用户未安装App,则跳去对应的web link(自定义页面)。Universal Links支持从其他App中的UIWebView中跳转到目标app。提供Universal Link给别的App进行App间的交流,然而对方并不能够用这个方法去检测你的App是否被安装,具有比较好的隐私性。绝大多数平台都支持Universal Link,微信7.0.5版本也解除了对Universal Link的限制,同时也能被搜索引擎索引。 3、App Links Android M以上版本可以通过App Links,让用户在点击一个链接时跳转到App的指定页面,前提是这个App已经安装并经过验证。App Links的最大的作用,就是可以避免从页面唤醒App时出现的选择浏览器选项框,前提是必须注册相应的Scheme,就可以实现直接打开关联的App。 实际上App Links和Universal Links差异不大,但相对来说有不同的限制: App links在国内的支持还不够,部分安卓浏览器并不支持跳转至App,而是直接在浏览器上打开对应页面。系统询问是否打开对应App时,假如用户选择“取消”并且选中了“记住此操作”,那么用户以后就无法再跳转App。几个方案的缺陷这几种方式无论哪种都无法解决这几个问题: 当用户未安装目标App时,无法保留用户停留的上下文,也就是说,用户下载完App后,无法在首次打开App时还原指定页面。Web目前无法监听App是否已安装,因此这几个方案都需要一些其他方法兼容唤醒App,或者跳转下载页面。那么怎样实现用户安装App后进入指定页面呢? 众所周知,苹果出于用户隐私的保护,设置了名为沙盒的机制:应用只能访问它声明可以访问的资源,但沙盒也阻碍了应用间合理的信息共享。 但也不是完全没办法,比如使用模糊匹配,尽可能收集设备的特征,将Web和App上的信息点配合算法做一个匹配是可以做到的,但准确率和成功率就取决于算法本身。如果App本身业务需求不高,那么低精度的方案也可以满足,但如果业务上需要一个能做到一对一精准匹配的方案,那么精准度不够高显然会影响业务的开展。 第三方服务如果嫌精准度不够高或者实现难度太大的话,可以交给专业的第三方去做,毕竟这几项技术是基于系统平台的,Android 及 iOS 每个系统版本的迭代后,配置方式都会有新的变化,且安卓机型众多,浏览器众多等也会导致出现兼容问题,开发者自行研发的话,资源配置以及系统更新后的维护成本是比较高的,还要考虑各种各样的跳转场景问题。 ...

October 9, 2019 · 1 min · jiezi

前端HTMLCSS笔试题面试题

前言前端的面试和学习都是不可或缺的事情,在这里收集一些高频面试题,供自己现在和以后查阅和查缺补漏的同时,也希望对小伙伴有所帮助。 HTML1、HTML语义化的理解1、用正确的标签做正确的事情!2、HTML语义化就是让页面的内容结构化,便于对浏览器、搜索引擎解析;3、在没有样式CSS情况下也以一种文档格式显示,并且是容易阅读的。4、搜索引擎的爬虫依赖于标记来确定上下文和各个关键字的权重,利于 SEO。5、使阅读源代码的人对网站更容易将网站分块,便于阅读维护理解 2、HTML5有哪些新特性、移除了那些元素?<font color='red'>HTML5</font> 现在已经不是 <font color='red'>SGML</font> 的子集,主要是关于图像,位置,存储,多任务等功能的增加 绘画 canvas用于媒介回放的 <font color='red'>video</font> 和 <font color='red'>audio</font> 元素本地离线存储 <font color='red'>localStorage</font> 长期存储数据,浏览器关闭后数据不丢失<font color='red'>sessionStorage</font> 的数据在浏览器关闭后自动删除语意化更好的内容元素,比如<font color='red'>article、footer、header、nav、section</font>表单控件,<font color='red'>calendar、date、time、email、url、search</font>新的技术<font color='red'>webworker、 websocket、 Geolocation</font>移除的元素: 纯表现的元素:<font color='red'>basefont、big、center、font、 s、strike、tt、u</font>对可用性产生负面影响的元素:<font color='red'>frame、frameset、noframes</font>支持HTML5新标签: <font color='red'>IE8/IE7/IE6</font>支持通过<font color='red'>document.createElement</font>方法产生的标签可以利用这一特性让这些浏览器支持<font color='red'>HTML5</font>新标签浏览器支持新标签后,还需要添加标签默认的样式当然也可以直接使用成熟的框架、比如<font color='red'>html5shim</font>3、<img>的title和alt有什么区别alt 是图片加载失败时,显示在网页上的替代文字;title 是鼠标放上面时显示的文字。alt是img必要的属性,而title不是。4、从浏览器地址栏输入url到显示页面的步骤浏览器根据请求的URL交给DNS域名解析,找到真实IP,向服务器发起请求;服务器交给后台处理完成后返回数据,浏览器接收文件(HTML、JS、CSS、图象等);浏览器对加载到的资源(HTML、JS、CSS等)进行语法解析,建立相应的内部数据结构(如HTML的DOM);载入解析到的资源文件,渲染页面,完成。5、HTML全局属性(global attribute)有哪些class:为元素设置类标识data-*: 为元素增加自定义属性draggable: 设置元素是否可拖拽id: 元素id,文档内唯一lang: 元素内容的的语言style: 行内css样式title: 元素相关的建议信息6、介绍一下你对浏览器内核的理解?主要分成两部分:渲染引擎(layout engineer或Rendering Engine)和JS引擎 渲染引擎:负责取得网页的内容(HTML、XML、图像等等)、整理讯息(例如加入CSS等),以及计算网页的显示方式,然后会输出至显示器或打印机。浏览器的内核的不同对于网页的语法解释会有不同,所以渲染的效果也不相同。所有网页浏览器、电子邮件客户端以及其它需要编辑、显示网络内容的应用程序都需要内核 JS引擎则:解析和执行javascript来实现网页的动态效果 最开始渲染引擎和JS引擎并没有区分的很明确,后来JS引擎越来越独立,内核就倾向于只指渲染引擎 7、请描述一下 cookies,sessionStorage 和 localStorage 的区别?cookie是网站为了标示用户身份而储存在用户本地终端(Client Side)上的数据(通常经过加密) cookie数据始终在同源的http请求中携带(即使不需要),记会在浏览器和服务器间来回传递 sessionStorage和localStorage不会自动把数据发给服务器,仅在本地保存 存储大小: cookie数据大小不能超过4ksessionStorage和localStorage虽然也有存储大小的限制,但比cookie大得多,可以达到5M或更大有期时间: localStorage 存储持久数据,浏览器关闭后数据不丢失除非主动删除数据sessionStorage 数据在当前浏览器窗口关闭后自动删除cookie 设置的cookie过期时间之前一直有效,即使窗口或浏览器关闭 8、行内元素有哪些?块级元素有哪些?空(void)元素有那些?行内元素和块级元素有什么区别?行内元素有:a b span img input select strong块级元素有:div ul ol li dl dt dd h1 h2 h3 h4… p空元素:<br> <hr> <img> <input> <link> <meta>行内元素不可以设置宽高,不独占一行块级元素可以设置宽高,独占一行9、如何在页面上实现一个圆形的可点击区域?svgborder-radius纯js实现 需要求一个点在不在圆上简单算法、获取鼠标坐标等等10、HTTP状态码及其含义1XX:信息状态码2XX:成功状态码3XX:重定向4XX:客户端错误5XX: 服务器错误11、你能描述一下渐进增强和优雅降级之间的不同吗渐进增强:针对低版本浏览器进行构建页面,保证最基本的功能,然后再针对高级浏览器进行效果、交互等改进和追加功能达到更好的用户体验。 ...

October 9, 2019 · 1 min · jiezi

react整合原生redux二

react整合原生redux(二)前言在react整合原生redux(一)已经完成了一个基本的应用框架,但是在分发action的时候,并不能在action里写逻辑,换言之action始终只是json对象,不能是一个函数,虽然可以在视图生命周期内写逻辑方法改变state的数值,但是长此以往,会造成项目臃肿,维护困难,所以react-thunk中间件由此而生项目创建参考 react整合原生redux(一) 增加依赖包yarn add redux-thunk -s src文件目录|-app.js|-store.js|-index.js|-actions.js 多了一个actions.js文件,里面存放带逻辑的action action.js内容// actions.js/** * redux-thunk action格式为一个函数,返回值是使用了dispatch的函数 * 基本格式 * function () { * return function (dispatch) { * dispatch(...) * } * } */export const fetchListAction = param => { return dispatch => { // 模拟异步请求请求数据(fetch,axios等) new Promise(resolve => { setTimeout(() => { const data = { code: 0, msg: "ok", data: { list: ["hello", "thunk"], param } }; resolve(data); }, 2000); }).then(result => { dispatch({ type: "SAVE", payload: result.data }); }); };};store改动引入redux-thunk ...

October 9, 2019 · 2 min · jiezi

CSS-计数器counter

带计数器的自动编号CSS计数器就像“变量”。变量值可以通过CSS规则递增(它将跟踪它们被使用的次数)。要使用CSS计数器,我们将使用以下属性:counter-reset - 创建或重置计数器counter-increment - 增加计数器值content - 插入生成的内容counter()或counters()函数 - 将计数器的值添加到元素要使用CSS计数器,必须首先使用counter-reset创建。 下面的示例为页面创建一个计数器(在body选择器中),然后递增每个<h2>元素的计数器值,并将“选项 < 计数器的值 >:”添加到每个<h2>元素的开头: <!DOCTYPE html><html><head> <meta charset="utf-8"> <title>教程(jc2182.com)</title> <style> body { counter-reset: section; } h2::before { counter-increment: section; content: "选项 " counter(section) ": "; } </style></head><body><h1>使用CSS计数器:</h1><h2>HTML教程</h2><h2>CSS教程</h2><h2>JavaScript教程</h2><p><b>注意:</b> 只有在指定了!DOCTYPE时,IE8才支持这些属性。</p></body></html>嵌套计数器以下示例为页面(节)创建一个计数器,为每个<h1>元素(子节)创建一个计数器。对于每个<h1>元素,“section”计数器将计为“Section < 值的分区计数器 >。”,并且“subsection”计数器将计入每个<h2>元素,记入“<分区计数器的值 >==< 分段计数器的值 >“: <!DOCTYPE html><html><head> <meta charset="utf-8"> <title>教程(jc2182.com)</title> <style> body { counter-reset: section; } h1 { counter-reset: subsection; } h1::before { counter-increment: section; content: "分区计数器的值 " counter(section) ". "; } h2::before { counter-increment: subsection; content: counter(section) "." counter(subsection) " "; } </style></head><body><h1>HTML教程:</h1><h2>HTML教程</h2><h2>CSS教程</h2><h1>Scripting教程:</h1><h2>JavaScript</h2><h2>VBScript</h2><h1>XML教程:</h1><h2>XML</h2><h2>XSL</h2><p><b>注意:</b>只有在指定了!DOCTYPE时,IE8才支持这些属性。</p></body></html>属性描述content与::before和::after伪元素一起使用,插入生成的内容counter-increment递增一个或多个计数器值counter-reset创建或重置一个或多个计数器

October 9, 2019 · 1 min · jiezi

前端面试每日-31-第176天

今天的知识点 (2019.10.09) —— 第176天[html] 做好的页面都有在哪些浏览器上测过[css] 你是怎样对css文件进行压缩合并的?[js] 请用js实现一个promise的方法[软技能] 在工作中,你觉得如何提高幸福指数呢?《论语》,曾子曰:“吾日三省吾身”(我每天多次反省自己)。 前端面试每日3+1题,以面试题来驱动学习,每天进步一点! 让努力成为一种习惯,让奋斗成为一种享受!相信 坚持 的力量!!!欢迎在 Issues 和朋友们一同讨论学习! 项目地址:前端面试每日3+1 【推荐】欢迎跟 jsliang 一起折腾前端,系统整理前端知识,目前正在折腾 LeetCode,打算打通算法与数据结构的任督二脉。GitHub 地址 微信公众号欢迎大家前来讨论,如果觉得对你的学习有一定的帮助,欢迎点个Star, 同时欢迎微信扫码关注 前端剑解 公众号,并加入 “前端学习每日3+1” 微信群相互交流(点击公众号的菜单:进群交流)。 学习不打烊,充电加油只为遇到更好的自己,365天无节假日,每天早上5点纯手工发布面试题(死磕自己,愉悦大家)。希望大家在这浮夸的前端圈里,保持冷静,坚持每天花20分钟来学习与思考。在这千变万化,类库层出不穷的前端,建议大家不要等到找工作时,才狂刷题,提倡每日学习!(不忘初心,html、css、javascript才是基石!)欢迎大家到Issues交流,鼓励PR,感谢Star,大家有啥好的建议可以加我微信一起交流讨论!希望大家每日去学习与思考,这才达到来这里的目的!!!(不要为了谁而来,要为自己而来!)交流讨论欢迎大家前来讨论,如果觉得对你的学习有一定的帮助,欢迎点个[Star] https://github.com/haizlin/fe...

October 9, 2019 · 1 min · jiezi

前端深入之css篇link和import到底有什么区别

写在前面在真正的前端开发中,我们很少去写行内样式和内嵌样式,通常都是去引用外部样式。 而在我们学习之初的外部样式表都是用link引入的,但是当后来我们学习的逐渐深入,发现@import也可以引入样式。那么同样是引入外部样式,这两者有什么区别呢,下面请跟随我来详细了解一下link和@import的区别吧! 区别<!DOCTYPE html><html lang="en"> <head> <link rel="stylesheet" rev="stylesheet" href="myCss.css" type="text/css" > <style type="text/css" > @import url("./myCss.css"); </style> </head></html>这就是两种引用方式的常见用法,可以很清晰的看出 1、从属关系:link是html的标签,不仅可以加载 CSS 文件,还可以定义 RSS、rel 连接属性等;而@import是css的语法,只有导入样式表的作用。2、加载顺序:页面被加载时,link会和html同时被加载而;@import引入的 CSS 将在页面加载完毕后被加载。3、兼容性:@import是 CSS2.1 才有的语法,所以只能在 IE5以上 才能识别;而link是 HTML 标签,所以不存在兼容性问题。4、DOM:javascript只能控制dom去改变link标签引入的样式,而@import的样式不是dom可以控制的。5、link方式的样式权重高于@import的权重。(如果对权重不是十分了解,可以看我之前的文章)@import最优写法@import 'style.css' //Windows IE4/ NS4, Mac OS X IE5, Macintosh IE4/IE5/NS4不识别@import "style.css" //Windows IE4/ NS4, Macintosh IE4/NS4不识别@import url(style.css) //Windows NS4, Macintosh NS4不识别@import url('style.css') //Windows NS4, Mac OS X IE5, Macintosh IE4/IE5/NS4不识别@import url("style.css") //Windows NS4, Macintosh NS4不识别由上分析知道,@import url(style.css) 和@import url("style.css")是最优的选择,兼容的浏览器最多。从字节优化的角度来看@import url(style.css)最值得推荐。 结论@import是依赖css的,存在一定的兼容问题,并且根据浏览器渲染机制来说,他在dom树渲染完成后才会渲染,并且不能被js动态修改。 ...

October 8, 2019 · 1 min · jiezi

程序员写技术博客选平台还是自己手动搭建

很多程序员也在积累到一定阶段之后,会开始写自己的博客,一方面可以帮助自己沉淀平时工作中的知识;另一方面可以分享知识给别人,帮助其他同行在遇到相同问题时提供思路。 有人会说,都什么年代了,还写博客,大家都在写公众号啦!其实博客有公众号代替不了的地方,就是可以通过搜素引擎搜索到,比如「如何在CentOS上安装SS?」这种问题是肯定不会在公众号上能搜到的。 很多朋友选择在哪里写博客犯了难?下面是我个人觉得是比较适合程序员写个人博客的8个选择:(排名不分先后) 阿里云云栖社区腾讯云+社区掘金SegmentFault博客园CSDN简书Github/Gitlab Pages 自己搭建静态网站云栖社区阿里云云栖社区是近年来内容逐渐丰富的平台,其中阿里的同学很多都会在上面发布内容,质量也比较的高。不过其中的内容更偏向于服务器运维,后端开发方面。 腾讯云+社区腾讯云+社区跟云栖社区基本上属于同一类型的,主要内容也是更多关于云方面的内容,很专业。 掘金掘金是近两年来比较火爆的社区,掘金上面的内容分类做的非常的好,知识面涵盖了几乎全部的行业,之前有朋友在掘金上写起了短篇小说,可以说掘金上的阅读体验非常的好。 优点用户粘性强支持 markdown 和富文本两种编辑器阅读体验好SegmentFaultSegmentFault 是前些年比较火爆的类似于 StackOverflow 的问答类网站,目前感觉已经有些不那么火了,但是网站的月活大约在 2000W左右,它的流量也几乎跟 StackOverflow 差不多,都是搜索流量。如果你的文章是解决方案之类的,那么 SegmentFalut 是非常适合的! 博客园博客园是很古老的博客平台,从它的主页,到博客页都能看出上古遗迹的感觉。不过他们的SEO也是做的非常的好。他们的编辑器对 markdown 支持不友好。 优点:SEO做的好阅读量有保证缺点:太旧了没有适配移动端CSDNCSDN也是一个很有历史的博客平台,CSDN 的 SEO 效果非常的好,但是CSDN不知道什么原因,它展示的广告内容太多了,我个人不太喜欢,而且CSDN上有太多相似的内容,内容质量不高。 优点:SEO非常好月活 2亿左右的用户,阅读量有保证缺点:广告太多内容质量不太高阅读体验不好简书简书是一个类似于 Medium 的博客平台,风格是十分简洁的,对 Markdown 支持非常的好,并且在手机上展示的效果也是非常的好。不过它的SEO 效果不是特别的好,而且无法进行分类等。 优点:页面风格简洁markdown 友好缺点:平台内容太杂,技术博客较少自己搭建自己搭建,这种方式比较复杂,适合想自己动手,不愿意受限制于平台,致力于打造个人名片的朋友。自己搭建的选择有很多种,选择付费产品?不存在的,作为一个程序员,怎么能花钱在这些上面! Github Pages 或者 Gitlab Pages 都是可以免费使用的。如果对 Jekyll 不感冒,可以选择 Gitlab Pages 进行搭建,因为 Gitlab 上支持很多种静态网站生成器,而 Github 只支持 Jekyll,Gitlab 支持比如 Jekyll,Hexo,Hugo,VuePress等等。Gitlab + Netlify 可以搭建一套完全自动编译自动发布的个人博客网站,参考:Gitlab Pages + Netlify 免费搭建自动化发布网站。 总结以上是现阶段比较好的博客平台,不代表以后也不代表以前。其实最终,最重要的是博客的内容,而不是载体,或许再过几年之后,又会有更新更时髦更好用的平台出来了。 最后,没有最好的平台,只有最好的博客内容。希望各位看完不需要再纠结选哪个平台了,而是开始写起自己的博客吧!

October 8, 2019 · 1 min · jiezi

结合React的Effect-Hook分析组件副作用的清除

一个订阅好友在线的组件我们在DidMount的时候通过ID订阅了好友的在线状态并且为了防止内存泄漏,我们需要在WillUnmount清除订阅 但是当组件已经显示在屏幕上时,friend prop 发生变化时会发生什么? 我们的组件将继续展示原来的好友状态。这是一个 bug。而且我们还会因为取消订阅时使用错误的好友 ID 导致内存泄露或崩溃的问题。 class FriendStatus extends React.Component { constructor(props) { super(props); this.state = { isOnline: null }; this.handleStatusChange = this.handleStatusChange.bind(this); } componentDidMount() { ChatAPI.subscribeToFriendStatus( this.props.friend.id, this.handleStatusChange ); } componentWillUnmount() { ChatAPI.unsubscribeFromFriendStatus( this.props.friend.id, this.handleStatusChange ); } handleStatusChange(status) { this.setState({ isOnline: status.isOnline }); } render() { if (this.state.isOnline === null) { return 'Loading...'; } return this.state.isOnline ? 'Online' : 'Offline'; }}优化订阅好友在线的组件为了解决props更新导致的BUG我们需要在DidUpdate中进行修改订阅 componentDidMount() { ChatAPI.subscribeToFriendStatus( this.props.friend.id, this.handleStatusChange ); } componentDidUpdate(prevProps) { // 取消订阅之前的 friend.id ChatAPI.unsubscribeFromFriendStatus( prevProps.friend.id, this.handleStatusChange ); // 订阅新的 friend.id ChatAPI.subscribeToFriendStatus( this.props.friend.id, this.handleStatusChange ); } componentWillUnmount() { ChatAPI.unsubscribeFromFriendStatus( this.props.friend.id, this.handleStatusChange ); }引入Hooks代码会变得十分简单Effect HookuseEffect() 可以让你在函数组件中执行副作用操作默认情况下,它在第一次渲染之后和每次更新之后都会执行。 ...

October 8, 2019 · 2 min · jiezi

实践实现纯前端下的音频剪辑处理

前言最近在做一个项目,需要对webRTC录制的音频进行处理,包括音频的裁剪、多音频合并,甚至要将某个音频的某一部分替换成另一个音频。 原本笔者打算将这件工作交给服务端去完成,但考虑,其实无论是前端还是后台,所做的工作是差不多的,而且交给服务端还需要再额外走一个上传、下载音频的流程,这不仅增添了服务端的压力,而且还有网络流量的开销,于是萌生出一个想法:为什么音频处理这件事不能让前端来做呢? 于是在笔者的半摸索半实践下,产生出了这篇文章。废话少说,先上仓库地址,这是一个开箱即用的前端音频剪辑sdk(点进去了不如就star一下吧) ffmpegffmpeg是实现前端音频处理的非常核心的模块,当然,不仅是前端,ffmpge作为一个提供了录制、转换以及流化音视频的业界成熟完整解决方案,它也应用在服务端、APP应用等多种场景下。关于ffmpeg的介绍,大家自行google即可,这里不说太多。 由于ffmpeg在处理过程中需要大量的计算,直接放在前端页面上去运行是不可能的,因为我们需要单独开个web worker,让它自己在worker里面运行,而不至于阻塞页面交互。 可喜的是,万能的github上已经有开发者提供了ffmpge.js,并且提供worker版本,可以拿来直接使用。 于是我们便有了大体的思路:当获取到音频文件后,将其解码后传送给worker,让其进行计算处理,并将处理结果以事件的方式返回,这样我们就可以对音频为所欲为了:) 开启美妙之旅前的必要工作需要提前声明的是,由于笔者的项目需求,是仅需对.mp3格式进行处理的,因此下面的代码示例以及仓库地址里面所涉及的代码,也主要是针对mp3,当然,其实不管是哪种格式,思路是类似的。 创建worker创建worker的方式非常简单,直接new之,注意的是,由于同源策略的限制,要使worker正常工作,则要与父页面同源,由于这不是重点,所以略过 function createWorker(workerPath: string) { const worker = new Worker(workerPath); return worker;}postMessage转promise仔细看ffmpeg.js文档的童鞋都会发现,它在处理音频的不同阶段都会发射事件给父页面,比如stdout,start和done等等,如果直接为这些事件添加回调函数,在回调函数里去区分、处理一个又一个音频的结果,是不大好维护的。个人更倾向于将其转成promise: function pmToPromise(worker, postInfo) { return new Promise((resolve, reject) => { // 成功回调 const successHandler = function(event) { switch (event.data.type) { case "stdout": console.log("worker stdout: ", event.data.data); break; case "start": console.log("worker receive your command and start to work:)"); break; case "done": worker.removeEventListener("message", successHandler); resolve(event); break; default: break; } }; // 异常捕获 const failHandler = function(error) { worker.removeEventListener("error", failHandler); reject(error); }; worker.addEventListener("message", successHandler); worker.addEventListener("error", failHandler); postInfo && worker.postMessage(postInfo); });}通过这层转换,我们就可以将一次postMessage请求,转换成了promise的方式来处理,更易于空间上的拓展 ...

October 8, 2019 · 3 min · jiezi

抖音抖一抖SVG和CSS视觉故障艺术小赏

故障艺术,英文名称叫glitch,在很多赛博朋克作品中经常看到,其实就是故意表现一种显示设备的小故障效果,抖音的图标其实就是这种的效果,我们看下这个图标 这个图标中的红色和蓝色的偏移其实就是一种故障艺术,看到这个,我就能想到早年我家还没有有线电视时,摇天线对电视信号的场景,信号一差就是对着电视一阵拳打脚踢,现在看到这种艺术效果颇为怀念。 某甲:为啥我没遇到过这种场景? 我:你把手里的平板扔地上就能看到了。 某甲:(土豪动作完成)我摔了,咋还没看到呢 我:我就打个比方,你何必当真... 某甲:我一定要看到! 我:要不你再跺几脚... ----------------------------------------我是打算开始的分割线------------------------------------------ 我们先来实现一个动态的抖音故障效果,首先我们要有一个干净的抖音图标,我是从阿里巴巴矢量图标库找的,因为它家支持SVG格式,得到的SVG代码是这样的。 <svg id="douyin" t="1570181112474" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2916" width="128" height="128"> <path d="M937.386667 423.850667a387.84 387.84 0 0 1-232.874667-77.824v352.341333C704.512 878.250667 565.930667 1024 394.922667 1024S85.333333 878.250667 85.333333 698.368c0-179.882667 138.581333-325.632 309.589334-325.632 17.066667 0 33.706667 1.450667 49.92 4.266667v186.624a131.754667 131.754667 0 0 0-48.64-9.216c-76.288 0-138.154667 65.024-138.154667 145.322666 0 80.213333 61.866667 145.322667 138.24 145.322667 76.202667 0 138.069333-65.109333 138.069333-145.322667V0h172.714667c0 134.485333 103.68 243.541333 231.594667 243.541333v180.309334h-1.28" p-id="2917"></path> </svg>看到的图形是这样子的 注意,在SVG的代码里面是没有设置颜色的,图片里面的黑色是为了让大家看清楚。我们先把白色,蓝色和红色的三层抖音图标先显示出来,代码如下: <use xlink:href="#douyin" x="0%" y="10%" class="douyin1" /><use xlink:href="#douyin" x="0%" y="10%" class="douyin2" /><use xlink:href="#douyin" x="0%" y="10%" class="douyin" />/ 白色 /.douyin { ...

October 7, 2019 · 3 min · jiezi

前端面试每日-31-第174天

今天的知识点 (2019.10.07) —— 第174天[html] img、input标签它们是行内元素还是块级元素?[css] css3和css2的区别是什么?[js] 你知道断点续传的原理吗?用js怎么实现?[软技能] 你想当技术总监吗?你觉得技术总监应具备什么样的技能?《论语》,曾子曰:“吾日三省吾身”(我每天多次反省自己)。 前端面试每日3+1题,以面试题来驱动学习,每天进步一点! 让努力成为一种习惯,让奋斗成为一种享受!相信 坚持 的力量!!!欢迎在 Issues 和朋友们一同讨论学习! 项目地址:前端面试每日3+1 【推荐】欢迎跟 jsliang 一起折腾前端,系统整理前端知识,目前正在折腾 LeetCode,打算打通算法与数据结构的任督二脉。GitHub 地址 微信公众号欢迎大家前来讨论,如果觉得对你的学习有一定的帮助,欢迎点个Star, 同时欢迎微信扫码关注 前端剑解 公众号,并加入 “前端学习每日3+1” 微信群相互交流(点击公众号的菜单:进群交流)。 学习不打烊,充电加油只为遇到更好的自己,365天无节假日,每天早上5点纯手工发布面试题(死磕自己,愉悦大家)。希望大家在这浮夸的前端圈里,保持冷静,坚持每天花20分钟来学习与思考。在这千变万化,类库层出不穷的前端,建议大家不要等到找工作时,才狂刷题,提倡每日学习!(不忘初心,html、css、javascript才是基石!)欢迎大家到Issues交流,鼓励PR,感谢Star,大家有啥好的建议可以加我微信一起交流讨论!希望大家每日去学习与思考,这才达到来这里的目的!!!(不要为了谁而来,要为自己而来!)交流讨论欢迎大家前来讨论,如果觉得对你的学习有一定的帮助,欢迎点个[Star] https://github.com/haizlin/fe...

October 7, 2019 · 1 min · jiezi

前端面试每日31周汇总20191006

《论语》,曾子曰:“吾日三省吾身”(我每天多次反省自己)。 前端面试每日3+1题,以面试题来驱动学习,每天进步一点! 让努力成为一种习惯,让奋斗成为一种享受!相信 坚持 的力量!!!学习不打烊,充电加油只为遇到更好的自己,365天无节假日,每天早上5点纯手工发布面试题(死磕自己,愉悦大家)。希望大家在这浮夸的前端圈里,保持冷静,坚持每天花20分钟来学习与思考。在这千变万化,类库层出不穷的前端,建议大家不要等到找工作时,才狂刷题,提倡每日学习!(不忘初心,html、css、javascript才是基石!)欢迎大家到Issues交流,鼓励PR,感谢Star,大家有啥好的建议可以加我微信一起交流讨论!希望大家每日去学习与思考,这才达到来这里的目的!!!(不要为了谁而来,要为自己而来!)【推荐】欢迎跟 jsliang 一起折腾前端,系统整理前端知识,目前正在折腾 LeetCode,打算打通算法与数据结构的任督二脉。GitHub 地址 htmlHTML的标签区分大小写吗?属性名区分大小写吗?HTML的注释有几种写法?有什么规范吗?怎样给radio分组呢?你知道HTML什么是单闭合标签和双闭合标签吗?为何要分为这两种呢?什么是Data URI?你知道有哪些常见的视频(音频)编码格式和视频(音频)格式吗?Shadow DOM和Virtual DOM有什么区别?css你有使用过字体图标吗?它有什么好处?你知道什么是流体排版吗?说说它的原理是什么?请说说你对vh、vw的理解以及它们的运用场景是什么?css怎么更改表单的单选框或下拉框的默认样式?你了解css3的currentColor吗?举例说明它的作用是什么?怎么去掉点击a链接或者图片出现的边框?css的linear-gradient有什么作用呢?js清空一个数组的方式有哪些?它们有什么区别?ES5和ES6、ES7有什么区别?写一个根据xpath获取元素的方法用js实现一个复制粘贴的功能说说你对ArrayBuffer的理解!它和Array有什么区别?如何解决在手机上长时间点击会选中图片?你了解什么是AOP吗?它的作用是什么?举个例子软技能从你的角度上来说下你对“产品经理”这个岗位的理解请解释下单线程与多线程之间的区别?浏览器本地存储和服务器端存储有区别呢?说下你对预加载的理解?你有做过直播相关开发吗?知道它的原理吗?写js代码时你喜欢哪种命名方式?这么多年来,你值得骄傲坚持的是什么?全部所有 交流讨论欢迎大家前来讨论,如果觉得对你的学习有一定的帮助,欢迎点个Star, 同时欢迎加入 “前端面试每日3+1” 微信群(扫个人微信号邀请入群)相互交流。

October 6, 2019 · 1 min · jiezi

前端面试每日-31-第173天

今天的知识点 (2019.10.06) —— 第173天[html] HTML的标签区分大小写吗?属性名区分大小写吗?[css] 你有使用过字体图标吗?它有什么好处?[js] 清空一个数组的方式有哪些?它们有什么区别?[软技能] 从你的角度上来说下你对“产品经理”这个岗位的理解《论语》,曾子曰:“吾日三省吾身”(我每天多次反省自己)。 前端面试每日3+1题,以面试题来驱动学习,每天进步一点! 让努力成为一种习惯,让奋斗成为一种享受!相信 坚持 的力量!!!欢迎在 Issues 和朋友们一同讨论学习! 项目地址:前端面试每日3+1 【推荐】欢迎跟 jsliang 一起折腾前端,系统整理前端知识,目前正在折腾 LeetCode,打算打通算法与数据结构的任督二脉。GitHub 地址 微信公众号欢迎大家前来讨论,如果觉得对你的学习有一定的帮助,欢迎点个Star, 同时欢迎微信扫码关注 前端剑解 公众号,并加入 “前端学习每日3+1” 微信群相互交流(点击公众号的菜单:进群交流)。 学习不打烊,充电加油只为遇到更好的自己,365天无节假日,每天早上5点纯手工发布面试题(死磕自己,愉悦大家)。希望大家在这浮夸的前端圈里,保持冷静,坚持每天花20分钟来学习与思考。在这千变万化,类库层出不穷的前端,建议大家不要等到找工作时,才狂刷题,提倡每日学习!(不忘初心,html、css、javascript才是基石!)欢迎大家到Issues交流,鼓励PR,感谢Star,大家有啥好的建议可以加我微信一起交流讨论!希望大家每日去学习与思考,这才达到来这里的目的!!!(不要为了谁而来,要为自己而来!)交流讨论欢迎大家前来讨论,如果觉得对你的学习有一定的帮助,欢迎点个[Star] https://github.com/haizlin/fe...

October 6, 2019 · 1 min · jiezi

第五篇-仿写Vue生态系列解析模板事件

( 第五篇 )仿写'Vue生态'系列___"解析模板事件" 本次任务 取消'eval', 改为'new Function'.支持用户使用'@'与'v-on'绑定各种事件.支持初始化'methods'数据.使用函数时可以传参与不传参, 可以使用'$event'.实现'c-center'与'c-show'指令.实现'cc_cb'函数, 模板里面也可以用if - else.一. eval 与 Function项目里面的取值操作, 我之前一直采用的都是eval函数, 但是前段时间突然发现一个特别棒的函数Function, 下面我来演示一下他的神奇之处. 1. 可以执行字符串 let fn1 = new Function('var a = 1;return a'); console.log(fn1()); // 12. 可以传递参数下面写的name与age就是传入函数的两个参数, let fn2 = new Function('name','age', ' return name+age');console.log(fn2('lulu',24)); // lulu24第二种传参方式 let fn3 = new Function('name, age', ' return name+age');console.log(fn3('lulu',24)); // lulu24综上我可以推断, 他的原理是把最后一个参数当做执行体, 然后前面如果有参数就被当做新生成函数的参数. 3. 全局作用域他执行的时候里面的作用域是全局的, 就算在函数内部, 执行时候也取不到函数内部的值, 所以想要使用的值, 都需要我们手动传进去. // 报错了, 找不到ufunction cc(){ let u = 777; let fn = new Function('var a = 5;console.log(u); return a'); console.log(fn()); } cc()// 执行成功function cc(){ u = 777; // 直接挂在window上 let fn = new Function('var a = 5;console.log(u); return a'); // 777 console.log(fn()); // 5 } cc()我也试了一下, 里面的var a 并不会污染全局, 放心使用吧; ...

October 6, 2019 · 4 min · jiezi

vue01基础指令

前言:很久之前学过vue,如今开始复习,主要用于自己查看。 1.v-cloak,v-text,v-html,v-on,v-bind <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <script src="./lib/vue-2.4.0.js"></script> <style> [v-cloak] { display: none; } </style></head><body> <!-- 表示vue控制id为app的部分 --> <div id="app"> <!-- 使用v-cloak解决插值表达式闪烁问题 --> <!-- 插值表达式是一个占位符,不会替换整个元素的内容 --> <p v-cloak>{{msg}}</p> <!-- v-text覆盖元素中原本的内容,没有闪烁问题 --> <h4 v-text="msg">000</h4> <!-- 渲染带有html内容,覆盖所有内容 --> <div v-html="msg2">00</div> <!-- 属性绑定指令v-bind,引号里面解析为js代码表达式,简写v-bind:为冒号:--> <input type="button" value="按钮v-bind" v-bind:title="mytitle+msg"> <!-- 事件绑定v-on --> <!-- 错误,alert是原生方法,没有在vue中定义 --> <!-- <input type="button" value="按钮v-on" v-on:click="alert('hello')"> --> <!-- 事件绑定指令v-on,简写v-on:为冒号@--> <input type="button" value="按钮v-on" @click="alert"> </div> <script> var vm = new Vue({ el: '#app',//表示new出来的vue实例,控制页面中的id名为app的html部分 data: { //data属性中,存放的是el属性用到的数据 msg: 'hello world!', msg2: '<h1>带标签的msg</h1>', mytitle: 'hello mytitle' }, methods: { alert: () => { alert('hello!') } }, }) </script></body></html>2.事件修饰符,stop,prevent,capture,self,once ...

October 5, 2019 · 3 min · jiezi

前端面试每日-31-第172天

今天的知识点 (2019.10.05) —— 第172天[html] HTML的注释有几种写法?有什么规范吗?[css] 你知道什么是流体排版吗?说说它的原理是什么?[js] ES5和ES6、ES7有什么区别?[软技能] 请解释下单线程与多线程之间的区别?《论语》,曾子曰:“吾日三省吾身”(我每天多次反省自己)。 前端面试每日3+1题,以面试题来驱动学习,每天进步一点! 让努力成为一种习惯,让奋斗成为一种享受!相信 坚持 的力量!!!欢迎在 Issues 和朋友们一同讨论学习! 项目地址:前端面试每日3+1 【推荐】欢迎跟 jsliang 一起折腾前端,系统整理前端知识,目前正在折腾 LeetCode,打算打通算法与数据结构的任督二脉。GitHub 地址 微信公众号欢迎大家前来讨论,如果觉得对你的学习有一定的帮助,欢迎点个Star, 同时欢迎微信扫码关注 前端剑解 公众号,并加入 “前端学习每日3+1” 微信群相互交流(点击公众号的菜单:进群交流)。 学习不打烊,充电加油只为遇到更好的自己,365天无节假日,每天早上5点纯手工发布面试题(死磕自己,愉悦大家)。希望大家在这浮夸的前端圈里,保持冷静,坚持每天花20分钟来学习与思考。在这千变万化,类库层出不穷的前端,建议大家不要等到找工作时,才狂刷题,提倡每日学习!(不忘初心,html、css、javascript才是基石!)欢迎大家到Issues交流,鼓励PR,感谢Star,大家有啥好的建议可以加我微信一起交流讨论!希望大家每日去学习与思考,这才达到来这里的目的!!!(不要为了谁而来,要为自己而来!)交流讨论欢迎大家前来讨论,如果觉得对你的学习有一定的帮助,欢迎点个[Star] https://github.com/haizlin/fe...

October 5, 2019 · 1 min · jiezi

前端面试每日-31-第171天

今天的知识点 (2019.10.04) —— 第171天[html] 怎样给radio分组呢?[css] 请说说你对vh、vw的理解以及它们的运用场景是什么?[js] 写一个根据xpath获取元素的方法[软技能] 浏览器本地存储和服务器端存储有区别呢?《论语》,曾子曰:“吾日三省吾身”(我每天多次反省自己)。 前端面试每日3+1题,以面试题来驱动学习,每天进步一点! 让努力成为一种习惯,让奋斗成为一种享受!相信 坚持 的力量!!!欢迎在 Issues 和朋友们一同讨论学习! 项目地址:前端面试每日3+1 【推荐】欢迎跟 jsliang 一起折腾前端,系统整理前端知识,目前正在折腾 LeetCode,打算打通算法与数据结构的任督二脉。GitHub 地址 微信公众号欢迎大家前来讨论,如果觉得对你的学习有一定的帮助,欢迎点个Star, 同时欢迎微信扫码关注 前端剑解 公众号,并加入 “前端学习每日3+1” 微信群相互交流(点击公众号的菜单:进群交流)。 学习不打烊,充电加油只为遇到更好的自己,365天无节假日,每天早上5点纯手工发布面试题(死磕自己,愉悦大家)。希望大家在这浮夸的前端圈里,保持冷静,坚持每天花20分钟来学习与思考。在这千变万化,类库层出不穷的前端,建议大家不要等到找工作时,才狂刷题,提倡每日学习!(不忘初心,html、css、javascript才是基石!)欢迎大家到Issues交流,鼓励PR,感谢Star,大家有啥好的建议可以加我微信一起交流讨论!希望大家每日去学习与思考,这才达到来这里的目的!!!(不要为了谁而来,要为自己而来!)交流讨论欢迎大家前来讨论,如果觉得对你的学习有一定的帮助,欢迎点个[Star] https://github.com/haizlin/fe...

October 4, 2019 · 1 min · jiezi

前端面试每日-31-第169天

今天的知识点 (2019.10.02) —— 第169天[html] 什么是Data URI?[css] 你了解css3的currentColor吗?举例说明它的作用是什么?[js] 说说你对ArrayBuffer的理解!它和Array有什么区别?[软技能] 你有做过直播相关开发吗?知道它的原理吗?《论语》,曾子曰:“吾日三省吾身”(我每天多次反省自己)。 前端面试每日3+1题,以面试题来驱动学习,每天进步一点! 让努力成为一种习惯,让奋斗成为一种享受!相信 坚持 的力量!!!欢迎在 Issues 和朋友们一同讨论学习! 项目地址:前端面试每日3+1 【推荐】欢迎跟 jsliang 一起折腾前端,系统整理前端知识,目前正在折腾 LeetCode,打算打通算法与数据结构的任督二脉。GitHub 地址 微信公众号欢迎大家前来讨论,如果觉得对你的学习有一定的帮助,欢迎点个Star, 同时欢迎微信扫码关注 前端剑解 公众号,并加入 “前端学习每日3+1” 微信群相互交流(点击公众号的菜单:进群交流)。 学习不打烊,充电加油只为遇到更好的自己,365天无节假日,每天早上5点纯手工发布面试题(死磕自己,愉悦大家)。希望大家在这浮夸的前端圈里,保持冷静,坚持每天花20分钟来学习与思考。在这千变万化,类库层出不穷的前端,建议大家不要等到找工作时,才狂刷题,提倡每日学习!(不忘初心,html、css、javascript才是基石!)欢迎大家到Issues交流,鼓励PR,感谢Star,大家有啥好的建议可以加我微信一起交流讨论!希望大家每日去学习与思考,这才达到来这里的目的!!!(不要为了谁而来,要为自己而来!)交流讨论欢迎大家前来讨论,如果觉得对你的学习有一定的帮助,欢迎点个[Star] https://github.com/haizlin/fe...

October 2, 2019 · 1 min · jiezi

月报表模板的2大优势及软件推荐

很多人在制作报表时都会觉得比较繁琐,但完全有一些简单的方法能够解决难题,比如使用月报表模板,达到报表自动化的一种效果。下面就为大家详细介绍一下月报表模板的2大优势,及相关软件推荐。 1、不再担心数据的采集比如说对于在流水线上工作的人员来说,每天可能都需要把这些数据全部都写成日报,但是如果没有月报表模板,你会发现这些许许多多的数据,需要耗费很多时间去采集或读取数据。 对于现在的企业来说,都希望拥有信息化程度较高的现象,那么要想解决这一个问题,应该怎么办呢? 对于大部分的公司来说,基本上也不可能会搭建一个完整的生产计划表格,生产的进度最多也只是通过Excel的方式来进行汇总,或者是直接放在黑板上记录。主要也就是因为,很多人根本就不懂得月报表模板到底应该怎么操作。解决办法就是,选择一些具有自动化效果的报表模板,你会发现,它快速的读取出数据,并不需要浪费很多的时间。而且随时都可以找到自己所需要的一些数据,操作也非常的方便。 2、自动生成报表现在的报表自动化,利用报表软件就可以达到这一个功能。整体的操作也是非常简单的,月报表模板适合于各种不一样的环境中,即便是每一个不同的厂家,每一个不同的班组,只需要配上各自的数据即可。 这能够减少报表制作的流程,而且所需要的时间,也只需人工的20%-50%。这也是为什么大家都会选择固定化月报表模板的主要原因。 3、月报表模板的软件推荐在经过了一番了解之后,大家对于月报表模板也有了一定的了解。它所拥有的功能还是非常多的,而且还适用于很多不一样的范围,它能满足提高工作效率的需求。 选择下载市占率较高的月报表模板,会比较容易达到好的一种效果,让大家在日常操作的过程中变得更加简单。现在市占率第一的,就是帆软报表——FineReport了,它内置了很多行业专业的BI报表模板,而且可以在1天内很快上手这款专业的报表软件。它的企业版是要按项目收费的,个人版却是永久免费的!试用一下,就知好不好了。 免费试用FineReporthttp://www.finereport.com/pro...

September 20, 2019 · 1 min · jiezi

OAuth2

为什么需要oAuth2?假设有一个“云笔记”产品,并提供了“云笔记服务”和“云相册服务”,此时用户需要在不同的设备(PC、Android、iPhone、TV、Watch)上去访问这些“资源”(笔记,图片) 那么用户如何才能访问属于自己的那部分资源呢?此时传统的做法就是提供自己的账号和密码给我们的“云笔记”,登录成功后就可以获取资源了。但这样的做法会有以下几个问题: “云笔记服务”和“云相册服务”会分别部署,难道我们要分别登录吗?如果有第三方应用程序想要接入我们的“云笔记”,难道需要用户提供账号和密码给第三方应用程序,让他记录后再访问我们的资源吗?用户如何限制第三方应用程序在我们“云笔记”的授权范围和使用期限?难道把所有资料都永久暴露给它吗?如果用户修改了密码收回了权限,那么所有第三方应用程序会全部失效.只要有一个接入的第三方应用程序遭到破解,那么用户的密码就会泄露,后果不堪设想。为了解决类似以上问题oAuth2应用而生 oAuth2是什么?OAuth(开放授权)是一个开放标准,允许用户授权第三方移动应用访问他们存储在另外的服务提供者上的信息,而不需要将用户名和密码提供给第三方移动应用或分享他们数据的所有内容,OAuth2.0是OAuth协议的延续版本,但不向后兼容OAuth 1.0即完全废止了OAuth1.0。 OAuth 2.0 的标准是 RFC 6749 文件。该文件先解释了 OAuth是引入了一个授权层,用来分离两种不同的角色:客户端和资源所有者。......资源所有者同意以后,资源服务器可以向客户端颁发令牌。客户端通过令牌,去请求数据。OAuth 的核心就是向第三方应用颁发令牌。 oAuth的2规则中的名词解释第三方应用程序(Third-party application): 又称之为客户端(client),比如上节中提到的设备(PC、Android、iPhone、TV、Watch),我们会在这些设备中安装我们自己研发的 APP。又比如我们的产品想要使用 QQ、微信等第三方登录。对我们的产品来说,QQ、微信登录是第三方登录系统。我们又需要第三方登录系统的资源(头像、昵称等)。对于 QQ、微信等系统我们又是第三方应用程序。HTTP 服务提供商(HTTP service): 我们的云笔记产品以及 QQ、微信等都可以称之为“服务提供商”。资源所有者(Resource Owner): 又称之为用户(user)。用户代理(User Agent): 比如浏览器,代替用户去访问这些资源。认证服务器(Authorization server): 即服务提供商专门用来处理认证的服务器,简单点说就是登录功能(验证用户的账号密码是否正确以及分配相应的权限)资源服务器(Resource server): 即服务提供商存放用户生成的资源的服务器。它与认证服务器,可以是同一台服务器,也可以是不同的服务器。简单点说就是资源的访问入口,比如上节中提到的“云笔记服务”和“云相册服务”都可以称之为资源服务器。oAuth2规则的运行 (A)用户打开客户端以后,客户端要求用户给予授权。 (B)用户同意给予客户端授权。 (C)客户端使用上一步获得的授权,向认证服务器申请令牌。 (D)认证服务器对客户端进行认证以后,确认无误,同意发放令牌。 (E)客户端使用令牌,向资源服务器申请获取资源。 (F)资源服务器确认令牌无误,同意向客户端开放资源。 oAuth2规则的客户端授权方式授权码模式(authorization code)(A)用户访问客户端,后者将前者导向认证服务器。 (B)用户选择是否给予客户端授权。 (C)假设用户给予授权,认证服务器将用户导向客户端事先指定的"重定向URI"(redirection URI),同时附上一个授权码。 (D)客户端收到授权码,附上早先的"重定向URI",向认证服务器申请令牌。这一步是在客户端的后台的服务器上完成的,对用户不可见。 (E)认证服务器核对了授权码和重定向URI,确认无误后,向客户端发送访问令牌(access token)和更新令牌(refresh token)。 简化模式(implicit)(A)客户端将用户导向认证服务器。 (B)用户决定是否给于客户端授权。 (C)假设用户给予授权,认证服务器将用户导向客户端指定的"重定向URI",并在URI的Hash部分包含了访问令牌。 (D)浏览器向资源服务器发出请求,其中不包括上一步收到的Hash值。 (E)资源服务器返回一个网页,其中包含的代码可以获取Hash值中的令牌。 (F)浏览器执行上一步获得的脚本,提取出令牌。 (G)浏览器将令牌发给客户端。 密码模式(resource owner password credentials)(A)用户向客户端提供用户名和密码。 (B)客户端将用户名和密码发给认证服务器,向后者请求令牌。 (C)认证服务器确认无误后,向客户端提供访问令牌。 客户端模式(client credentials)(A)客户端向认证服务器进行身份认证,并要求一个访问令牌。 (B)认证服务器确认无误后,向客户端提供访问令牌。 oAuth2客户端的授权码模式详细步骤授权码模式(authorization code)是功能最完整、流程最严密的授权模式。它的特点就是通过客户端的后台服务器,与"服务提供商"的认证服务器进行互动。 (A) 用户访问客户端,后者将前者导向认证服务器;客户端申请认证的URI,包含以下参数: ...

September 20, 2019 · 1 min · jiezi

node笔记json文件的写入

做的是一个小demo大致内容如下:1.Vue框架写的前端2.axios调用接口3.通过接口对json进行写入4.能够在局域网内所有电脑进行访问 首先需要install一些东西前端是 npm install axios后端安装express框架 npm install express --savenpm install body-parser --savenpm install cookie-parser --savenpm install multer --save前端页面: write() { this.axios .get(`http:// 自己的ip地址 :8081/?name=${this.name}&score=${this.score}`) .then(res => { console.log("res --->", res); }) .catch(err => { console.log("err --->", err); }); }内容比较简单,就写一个write方法通过axios调用接口并传参填自己的IP地址是因为要在局域网内访问,相当于本机是一个服务器,局域网内其他人填写的name和score都会到访问到本机的8081端口并写入本机的JSON文件 Api.js var fun = require('./fun')var express = require('express');var app = express();var bodyParser = require('body-parser');app.all("*", function (req, res, next) { //设置允许跨域的域名,*代表允许任意域名跨域 res.header("Access-Control-Allow-Origin", "*"); //允许的header类型 res.header("Access-Control-Allow-Headers", "content-type"); //跨域允许的请求方式 res.header("Access-Control-Allow-Methods", "DELETE,PUT,POST,GET,OPTIONS"); if (req.method.toLowerCase() == 'options') res.send(200); //让options尝试请求快速结束 else next();})// 创建 application/x-www-form-urlencoded 编码解析var urlencodedParser = bodyParser.urlencoded({ extended: false })app.use('/public', express.static('public'));app.get('/', function (req, res) { fun.writeJson(req.query)})var server = app.listen(8081, function () { var host = server.address().address var port = server.address().port console.log("<---------- 服务已启动 ---------->") console.log("<--------- 服务端口:8081 --------->")})fun是另一个提供JSON写入的函数,这个Api主要功能是设置跨域并调用接口,可以看到app.get调用了fun.writeJson方法 ...

September 19, 2019 · 1 min · jiezi

如何优雅的使用react-hooks来进行状态管理

在使用react和redux的过程中,一直有一个问题,哪些状态需要放在redux中,状态需要保存在组件内的local state中,此外不合理的使用redux可能会带来状态管理混乱的问题,此外对于local state局部状态而言,react hooks提供了一个比class中的setState更好的一个替代方案。本文主要从状态管理出发,讲讲如何优雅的使用hooks来进行状态管理。 如何使用reduxreact hooks管理local statereact hooks如何解决组件间的通信原文在我的博客中:https://github.com/forthealll...欢迎订阅 一、如何使用redux 首先要明确为什么要使用redux,这一点很重要,如果不知道为什么使用redux,那么在开发的过程中肯定不能合理的使用redux.首先来看redux的本质: redux做为一款状态管理工具,主要是为了解决组件间通信的问题。 既然是组件间的通信问题,那么显然将所有页面的状态都放入redux中,是不合理的,复杂度也很高。 (1)全量使用redux 笔者在早期也犯了这个问题,在应用中,不管什么状态,按页面级路由拆分,全部放在redux中,页面任何状态的更改,通过react-redux的mapState和mapDispatch来实现。 redux中的状态从状态更新到反馈到视图,是一个过程链太长,从dispatch一个action出发,然后走reducer等逻辑,一个完整的链路包含: 创建action,创建redux中间件,创建相应type的reducer函数,创建mapState和mapDispatch等。 如果将所有状态都保存在redux中,那么每一个状态必须走这几步流程,及其繁琐,毫无疑问增加了代码量 (2)减少局部状态和redux状态的不合理混用 全量使用redux的复杂度很高,我们当然考虑将一部分状态放在redux中,一部分状态放在local state中,但是这种情况下,很容易产生一个问题,就是如果local State跟redux中的state存在状态依赖。 举例来说,在redux中的状态中有10个学生 //redux students = [{name:"小明",score:70},{name:"小红",score:50}....]在local state中我们保存了分数在60分以上的学生 // local state state = [{name:"小明",score:70}] 如果redux中的学生改变了,我们需要从redux中动态的获取students信息,然后改变局部的state.结合react-redux,我们需要在容器组件中使用componentWillReceivedProps或者getDerivedStateFromProps这个声明周期,来根据props改变局部的local state. componentWillReceivedProps这里不讨论,为了更高的安全性,在react中用静态的getDerivedStateFromProps代替了componentWillReceivedProps这里不讨论,而getDerivedStateFromProps这个声明周期函数在props和state变化的时候都会去执行,因此如果我们需要仅仅在props的改变而改变局部的local state,在这个声明周期中会存在着很复杂的判断逻辑。 redux中的状态和local state中的状态相关联的越多,getDerivedStateFromProps这个声明周期函数就越复杂 给我们的启示就是尽可能的减少getDerivedStateFromProps的使用,如果实在是redux和local state有关联性,用id会比直接用对象或者数组好,比如上述的例子,我们可以将学生分组,并给一个组号,每次在redux中的学生信息发生改变的时候会改变相应的组号。这样在getDerivedStateFromProps只需要判断组号是否改变即可: class Container extends React.Component{ state = { group_id:number } static getDerivedStateFromProps(props,state){ if(props.group_id!==state.group_id){ ... 更新及格的学生 }else{ return null } } } 这里推荐https://github.com/paularmstr... state关联性强,可以先将数据范式化,范式化后的数据类似于给一个复杂结构一个id,这样子会简化getDerivedStateFromProps的逻辑. ...

September 19, 2019 · 3 min · jiezi

如何制作报表4大步骤

其实不管我们选择哪一种工作,在平时经常性都会涉及到各种各样不同的报表,这对于新手小白来说确实也特别的为难,即便是有一些工作者早就已经拥有多年的经验,也会觉得非常费时费力。这些看上去非常简单的报表,其实在日常操作的过程中却也存在着一定的难度。如何制作报表才是比较正确的呢?本文介绍4大步骤。 1、下载软件如何制作报表,我们首先就应该下载一个比较适合的APP。 现在要说功能比较齐全的,肯定就是市占率第一的FineReport,一般在操作的时候较为稳定,不容易会出现出错的现象。 另外,在下载的时候最好是不要把文件直接全部都下载到c盘,因为c盘如果出现了过多的文件堆积,也同样会出现明显的卡顿现象,影响到日常的运作。 2、重新新建表格如何制作保表,我们还是需要掌握一定的技巧。新建的表格方法非常的简单,当鼠标一到新建选项时,直接就会跳出一个页面,那么直接选择新工作表。 表格的新建,需要保存到分类好的文件夹里面。如此就能够有效的减少剪切粘贴的操作,在日常查找的过程中也更加方便。 3、表格重命名如何制作表格?那么当我们在选择新建表格文件之后,也需要进行重命名,如此在发送文件的时候相对来说比较直观,而且也方便日常生活的查找。 最为简单的一种方式,直接就是选中表格,然后在跳出的页面里面点击重命名。这种方法还是非常简单的。当然我们也可以直接单击选择新建的表格,等到间隔一秒之后再进行操作,这种方式相对来说并不需要花费很长的时间。 4、制作表格表格在进行重命名之后,我们可以直接双击点开。一个好的报表如何制作标题也是非常关键的。首先我们就应该选择简单明了的标记,让大家第一眼看到就能够知道是什么样的内容。那么在制定好标题之后,也应该确定需要几列内容,标题的格子最好是宽一些,如此可以带来更好的视觉效果。 写在最后如何制作报表,我们首先就应该历经上面的这几个步骤,那么就能够进入到正常的操作状态中。对于相应的知识,我们也必须要了解,否则操作的过程中存在一定的麻烦。 使用市占率较高、容易上手的报表工具,会比较容易达到好的一种效果,让大家在日常操作的过程中变得更加简单。现在市占率第一的报表,就是帆软报表——FineReport了,它内置了很多行业的权威BI报表模板,也可以1天内很快上手这款专业的报表软件。它的企业版是要按项目收费的,个人版却是永久免费的!试用一下,就知好不好了。 免费试用FineReporthttp://www.finereport.com/pro...

September 19, 2019 · 1 min · jiezi

表格制作软件的2大必备知识下载方法分类

工作时经常需要用表格来执行一些数据的操作,但是如果你不熟悉表格的制作,那会很尴尬。但是表格的制作并不像想象的那么困难,我们完全可以选择一些表格制作软件,几分钟就可以完成。本文就介绍了表格制作软件的2大必备知识:下载方法,分类。 一、表格制作软件下载的方法下载表格软件之前,我们首先就应该查询一下自己到底需要什么样的软件。 然后就可以进入到下载的过程中,当你在点击下载之后,都会有着对应的操作步骤,整体的操作也是比较简单的,而且也并不需要花费很多的时间。 与此同时我们也应该了解,表格制作软件到底有哪一些比较常见的分类。 二、表格制作软件有哪些分类1、汇总表 可以构成一些简单的形式,如学生的课程安排、时间表、成绩和工作形式。表单制作完成后,还可以直接保存到手机中。此外,它还可以执行新建、删除等功能的操作,简化后的表格最多有19行19列,非常的简单,整体的操作也并不需要花费很多的时间。 2、Excel表格制作 excel表格制作是帮助您快速学习和掌握excel办公软件的好工具,只要掌握了技能,你就可以轻松地完成各种形式的制作。此外,还可以学习excel函数、excel数据透视表等,使工作更轻松。 3、合作伙伴云表 表单是一个支持团队合作的简明在线表单。在这里,可以轻松制作各种常用表单,随时随地共享工作进度,不仅可以在网上制作表单,还可以在移动端编辑数据,同步多个终端,提高效率,更是直接可以把表格制作软件下载下来,在手机中也能够完成整体的操作。 表格制作软件只要用对了软件,整体还是比较简单的。我们也应该知道表格制作软件到底有哪一些分类是比较常见的,只有如此才能够真正的选择到适合自己的软件,提高自己的工作效率。 写在最后现在能涵盖以上3种表格的制作,以及市占率第一的BI表格软件,就是帆软报表——FineReport了,它有详实的表格制作教程,也可以1天内很快上手这款专业的报表软件。它的企业版是要按项目收费的,个人版却是永久免费的!试用一下,就知好不好了。 工作时经常需要用表格来执行一些数据的操作,但是如果你不熟悉表格的制作,那会很尴尬。但是表格的制作并不像想象的那么困难,我们完全可以选择一些表格制作软件,几分钟就可以完成。本文就介绍了表格制作软件的2大必备知识:下载方法,分类。 免费试用FineReporthttp://www.finereport.com/kno...

September 19, 2019 · 1 min · jiezi

免费报表软件有哪些4款热门工具

在企业管理过程中,报表往往都会通过一些简洁的图表方式,为大家呈现所有的数据。报表软件,可以在操作的过程中有效提升工作效率,所以有很多企业早就已经选择跟随信息技术的潮流,选择报表软件工具。很多人也一直都在关注免费报表软件有哪些,本文就为大家推荐几款比较常见的。 1、FineReport相信不少人在查询免费报表软件有哪些时就可以看到这一款,这本身就是定位于报表软件的一款,主要就是用来处理一些特别复杂的报表,通过一些可视化的操作,即便是不会复杂的代码也完全没有关系。它是类似于Excel的编辑器,一般操作的过程中只需要进行简单的拖拽即可,能够提供基本市面上所有的报表功能。另外,整体的服务质量还是比较不错的。 2、润乾我们在查询免费报表软件有哪些时,那么不少人也会发现,传统报表软件中其实也有很多。比如说润乾,这一款软件也有着强大的功能,能够处理复杂的报表。对于一些如果没有任何基础的用户来说,操作方式还是比较简单的。与此同时,也提供企业免费版本,所以说,也引来大家的关注。 3、PowerBI这其实也是目前市场上比较常见的一款免费报表软件,这一款也绝对是比较完整的报表系统工具。它有着人性化的操作效果,而且中文用户界面操作也比较上手,能有效的提供官方技术支持,可以快速的帮助用户解决所有的问题。但是开放接口相对来说就比较少,对于一些大数据量清单的报表在操作的过程中就有点麻烦。 4、RDPRDP本身就是一种企业级别的报表软件,所以我们在查询免费报表软件有哪些时,马上就看到这款软件。整体的部署真的特别简单,完全不需要下载任何的客户端,也完全不需要安装大量的软件,直接就能够拥有好的操作,而且还可以申请永久免费授权,直接绑在电脑上操作即可,还是非常方便的。 其实每一个企业都非常的关心免费报表软件有哪些,为大家介绍的这4款软件,在选择之后,工作效率马上就能够有效的改善。现在免费报表软件市占率第一的就是帆软报表——FineReport了,试用一下就知道好不好了。 免费试用FineReporthttp://www.finereport.com/pro...

September 19, 2019 · 1 min · jiezi

前端面试每日-31-第148天

今天的知识点 (2019.09.11) —— 第148天[html] input的onblur和onchange事件区别是什么?[css] 什么是脱离文档流?有什么办法可以让元素脱离标准的文档流?[js] 请使用原生的js实现斐波那契数列[软技能] 你知道什么是AST吗?说说你对AST的理解,它的运用场景有哪些?《论语》,曾子曰:“吾日三省吾身”(我每天多次反省自己)。 前端面试每日3+1题,以面试题来驱动学习,每天进步一点! 让努力成为一种习惯,让奋斗成为一种享受!相信 坚持 的力量!!!欢迎在 Issues 和朋友们一同讨论学习! 项目地址:前端面试每日3+1 【推荐】欢迎跟 jsliang 一起折腾前端,系统整理前端知识,目前正在折腾 LeetCode,打算打通算法与数据结构的任督二脉。GitHub 地址 微信公众号欢迎大家前来讨论,如果觉得对你的学习有一定的帮助,欢迎点个Star, 同时欢迎微信扫码关注 前端剑解 公众号,并加入 “前端学习每日3+1” 微信群相互交流(点击公众号的菜单:进群交流)。 学习不打烊,充电加油只为遇到更好的自己,365天无节假日,每天早上5点纯手工发布面试题(死磕自己,愉悦大家)。希望大家在这浮夸的前端圈里,保持冷静,坚持每天花20分钟来学习与思考。在这千变万化,类库层出不穷的前端,建议大家不要等到找工作时,才狂刷题,提倡每日学习!(不忘初心,html、css、javascript才是基石!)欢迎大家到Issues交流,鼓励PR,感谢Star,大家有啥好的建议可以加我微信一起交流讨论!希望大家每日去学习与思考,这才达到来这里的目的!!!(不要为了谁而来,要为自己而来!)交流讨论欢迎大家前来讨论,如果觉得对你的学习有一定的帮助,欢迎点个[Star] https://github.com/haizlin/fe...

September 11, 2019 · 1 min · jiezi

使用createreactapp脚手架-npm-run-eject提示确认后输入yes就报错了

一把我们创建的react项目是默认隐藏配置文件的。如果我们想要配置就需要自己手动开启配置。 运行一下命令开启 npm run eject注意:输入y也可能报错, 原因如下:这是个git问题,你的版本库有未提交的文件,因为reject后会多出来一些文件。为了不影响。你应该把这些文件加到ignore里或者删掉。还有错误信息已经非常明显的告诉你具体要怎么做了 处理错误:git init (在项目中生成git仓库,如果已经生成了可忽略这一步,不要带括号的字)git add .git commit -m 'save'npm run eject

September 10, 2019 · 1 min · jiezi

完成钉钉小程序的开发

背景:之前做过一个支付宝小程序,领导要求用钉钉写个一样的出来.于是乎就开始了. 首先创建一个钉钉小程序 钉钉小程序有四个场景,我尝试了前三个场景,感觉就是发布的时候不太一样.最终选中了第三方个人应用开发.如果是公司开发的话记得找公司要管理账号.我是先自己创建了一个企业写的测试应用.下面的U_Gen价签小工具是我创建好的小程序. 下载小程序开发者工具,引入官网给的git上的代码.(我服务端和前端代码都下过,后面尝试了下,不能一起写.我这个项目需求也很简单不需要服务端做很多事,所以我就讲讲我主要写的前端页面吧.) 绑定小程序,修改页面小程序开发者工具里面可以开发很多版本的,你可以在这里选择你创建的小程序的类型.然后在旁边关联你创建好的小程序就可以了.我是写完了再截图的,所以目录东西可能有的多.给介绍一下,我引入了add-button.因为我要显示icon的,在这里写icon会方便一些.static文件夹下就是我的icon图标了.至于怎么导入icon图标我的文章里描述的很清楚了.不懂的可以再看一下这篇 引入阿里icon图标todos文件夹下就是我的页面样式,逻辑等了. 这里要连接后端接口的话一定要记得添加安全域名: 然后在js文件中去发请求 dd.showLoading()就是显示个loading出来.dd.httpRequest()就是发请求了.dd.alert()是弹框,里面的content是弹框内容,buttonText是弹框提示语. 修改主题色在app.acss里面.修改小程序标题在app.json里面,"pages"里面是一进页面加载的页面路径.如果你也引入了add-button的话记得在需要用的文件里导入,就像我这个todos.json里面导入的样子一样.add-button里面的样式和内容被我改了很多,我还是贴出来吧. 我的页面代码都是在todos里面.也一并附上主要就是axml里面的内容.其他的逻辑都是根据自己需求去写的.我的页面也只用到了钉钉的几个方法而已. 设置体验版,增加体验人员 再介绍下小程序开发者工具吧:1:可以更改机型,看样式的2:上传代码到钉钉开放平台的版本管理里面3:开启手机模拟器,右侧就会显示一个这样的模拟器出来4:修改样式的. 附上我的小程序效果图: 遇到的问题1:发请求参数一直不对,最后自己写了headers指定了格式,又加上了JSON.stringify转了一下才好.2:把服务端的方法用到了前端,我一直想在前端去生成签名,玩一下免登陆,获取个用户头像啥的.但是没成功.最后发现那些方法都是服务端的.前端用不了..我想应该不会有人跟我一样.. 但还是说一下..(其实签名我参数最后都写出来了的..应该是对的)3:icon加载比文字慢.我原来是写的button,然后写了个text把icon放到button旁边.但是加载特慢,扫描后回到页面图标就会消失一会儿.体验感很差,最后没办法,只能跟支付宝小程序写一样的,来个add-button.把icon放进add-button里面.然后在用到的todos文件里,引入add-button.让它先加载.就不会有这个问题了.4:如果有些问题网上你也没搜到答案,官网的api也没找到解决方法.可以去问人工服务.哈哈哈哈.我第一次问.还真的解决了问题的.就在钉钉开发平台的右下角,可以接入人工服务的.就是回的慢了点. 关于小程序,不管是微信的,还是支付宝的,还是钉钉的,我感觉都一样的.只是调用的方法名不一样而已.你会写了一个,其他的都是依葫芦画瓢而已.

September 10, 2019 · 1 min · jiezi

4图片的显示

现今的内容展示,简单的文字已经无法吸引读者的眼球。我们往往需要添加图片、音频、视频等元素吸引用户。下面我们来一起看看图片的显示实现。1、 创建舞台 var stage = new createjs.Stage("myStage");2、实例化图片对象 // 可以使用图片url、base64字符串 // (如果使用图片url注意要将代码放在web服务器环境下访问,此处有跨域资源限制问题将不能显示图片) var img = new createjs.Bitmap('https://ss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=938848384,3548229994&fm=111&gp=0.jpg');3、 调整图片位置 img.x = 100;4、添加图片到舞台 stage.addChild(img);5、更新舞台stage.update(); 显示结果: done完成!

September 10, 2019 · 1 min · jiezi

vue-移动端-弹框出现背景禁止滑动

1- 由于弹框比较长,所以弹出的时候前面的弹框内容需要滑动,但是背景需要禁止滚动 2-所以使用watch 监听,弹窗出现禁止滚动,弹框消失可以滚动 watch: {coachCard (newVal, oldVal) { if (newVal == true) { console.log('gaibian l '); let cssStr = "overflow-y: hidden; height: 100%;"; document.getElementsByTagName('html')[0].style.cssText = cssStr; document.body.style.cssText = cssStr; } else { let cssStr = "overflow-y: auto; height: auto;"; document.getElementsByTagName('html')[0].style.cssText = cssStr; document.body.style.cssText = cssStr; } // 下面需要这两行代码,兼容不同浏览器 document.body.scrollTop = this.pageScrollYoffset; window.scroll(0, this.pageScrollYoffset);}}, 贼长的弹框

September 10, 2019 · 1 min · jiezi

H5-趣谈

以下内容来源于知乎。 王德福:先科普一下,HTML5并不是一项技术,而是一个标准。标准的意思就是:学生准则手册。你可以按照准则做,甚至可以超出准则更加严格的要求自己,也可以不按照准则来,但是会被老师训斥小伙伴讨厌,别人都不找你玩,就像IE6一样。 那HTML5这些标准浏览器厂商到底姿持不姿持呢?这要看他们各自的尿性了。像chrome这种不仅在很多标准上支持的非常好,还积极上进很多地方超出了标准,支持一些标准中还是草案的部分。 所以其实要么我们是作为理论派讨论HTML5标准,要么是作为实践派讨论HTML5标准在某浏览器的应用。但是实际上我们在说到H5的时候,并不是指标准,也不是指标准的应用,而是一个硬生生造出来的奇怪概念合集,所以我是旗帜鲜明的反对这个称呼的。 最近一年的时间,我主要靠这个东西养家(并没有家)糊口。所以我是懂得甲方打电话过来询问,“你是不是会做H5开发?”的时候,我知道他们要的是那种可以在朋友圈分享的,看起来很酷炫的小页面,他们实际要的东西拆开来看大概包括以下技术点; 1. 页面素材预加载技术,可以使用createJS之中的preloadJS。我没有看preloadJS的源码,不过预加载并不是HTML5标准中更新的方法。2. 音乐加载播放技术,createJS中同样有soundJS可以实现,而且这部分说起来确实是HTML5标准支持的内容,在上个时代并没有audio这样的标签。3.可以滑动的页面,大多数是用了swiper.js这个Jquery插件,也有一些是手写的swipe,比较拙劣的手写版页面是不会跟手滑动的,其中touchstart等四个touch系列的事件是HTML5标准中的事件4.可以涂抹擦除,多半是canvas叠加层,canvas是HTML5标准里面的标签,是代表了先进生产力的标签。5.有动态的文字和图片,常见的是使用了css3或者直接使用js动画。很多时候提到HTML5多半还会带上CSS3,而CSS的分级又是另外的一个问题了,在不同的项目标准上,CSS会独立定级,以后应该不会有CSS4这个东西,所以大家也不用担心在H5以后又冒出来了C4(不过真是想用C4炸死那些每天把H5挂在嘴上的人)6.可以填表报名,这是最基本的表单,是有网页以来就有的东西。7.可以支持分享自定义的文案和图片,这个是用到了微信的jssdk,和HTML标准半毛钱关系都没有。8.还有其他我想起来再补充的。 所以我们在谈论H5的时候,实际上是一个解决方案,一个看起来酷炫的移动端onepage网站的解决方案。而这个解决方案不仅包含了HTML5新增的audio标签,canvas,拖拽特性,本地存储,websocket通信,同时也包括了盒模型,包括绝对定位,包括一切前端的基本知识。 有学弟来问我说,学长我想学H5,应该从哪里开始?我说HTML5新增特性在W3C上都可以查得到的。学弟说,不,我想学的是H5,想做H5的页面。于是我猜测他所指的就是上面论述的这种酷炫小页面,我就说,那你要先学习HTML,包括HTML5的新标准和之前的全部标准,然后学CSS以及CSS3,了解它们在浏览器的实现情况,原生JS了解一点就可以,大多的操作可以用Jquery,了解常用的几个Jquery插件的用法,应该就差不多了。如果想要做更酷炫的的,学一下egret或者cocos2d更好。如果要优化加载速度,还要学一下grunt一类的自动化工具。微信的sdk有很多坑,至少nodejs或者php一类的后端语言要会一点。 学弟说,那这不就是前端了么?我只是想学H5啊。 所以你看,当我们对一个概念的内涵无法统一的时候,我们根本不知道彼此之间在谈论的是什么。 ”H5“本应是一个技术合集,却被意会成了一项技术,变成可以在质上而不是量上描述的概念。 对于营销来说,我们只要讲我们可以做H5或者不能做,这种定性的描述就够了。但是对于技术上,这是定量的事情,只能在具体某个技术项上是否,无法对这个本不存在的概念说是否。 就比如我遇到过有甲方说,我们之前找了一个人做H5,做的还不错,但是这个case他又说做不了,我也搞不懂H5和H5之间也有那么大差别吗?我只能笑笑和他说,世界这么大,各种各样的H5都是有的。 这就是为什么我反对H5,因为这个名词和它表示的内涵是严重不符的,这让我们难以沟通,让营销人和技术人之间产生误解,让浑水摸鱼的培训师们赚的盆满钵满,让技术新人不踏踏实实的学习技术。 每当有人问我,”你是不是做H5的?“ 我的内心都很想咆哮一句,”你才是做H5的,你全家都是做H5的“ Contra:H5是一种用在微信上的PPT。 思扬:注意注意: H5 != HTML5 H5 是一个产品名词HTML5 是一个技术名词 对于知乎多个相关问题里批判H5的叫法,我只想说: 图样图森破,上台拿衣服打个比方,如果有个人跟你说:“我要做个网站,H5的”。那TA是想让你用header、footer、nav、section等标签?让你用Geolocation、localStorage、Web Worker等API?都不是,TA们想要的功能你用HTML4就都能做出来了。更别说还得兼容老IE浏览器呢。 所以年轻人,你们要用心理解客户的需求,不要沉迷于技术。人家一定不是让你去用一种不被所有浏览器兼容的技术。 所以,H5指的不是HTML5,而是某种在微信等移动端看上去酷炫能够提升公司格调顺便亮瞎访问者氪金狗眼顿升膜拜之心就算没有内容也能被广泛转发分享的一种东西。

September 10, 2019 · 1 min · jiezi

空手套白狼我的互联网草根创业亲身经历

和大多数人一样,我出生寒门学子,没钱没势,所有的一切都是从零开始,只能空手套白狼,本文章主要是为了分享下我个人的创业经历以及一个产品从无到有的过程,后面也会聊到我做H5工具的相关技术方案,希望能帮助读者在未来的工作或者是创业路上有所帮助。2010年第一次创业务实的人都不甘于平庸,我亦如此,也许越是有挑战的东西,我越是感兴趣,创业的想法就像一颗毒瘤一直在我脑中去不掉,大学第一天上学,我把所有的生活费在阿里巴巴上进了一堆跳舞毯,开始了人生的第一次创业,我记得那是2010年上大一的事情了,虽然没有赚回本钱,但是我意外的认识了生产跳舞毯的老板。在学校里卖不完跳舞毯,于是我开了个淘宝店铺在网上卖,虽然网上也没卖完,却阴差阳错的成为了跳舞毯公司的网店兼职设计师(精通美图秀秀),再后面就自学了PS,成为了一个UI设计师,我大学学的是java,因为学习了PS,也就顺理成章的成了前端工程师。也为接下来的创业奠定了技术的基础。 2012年第一个工作室大学2年期间,我的前端技术逐渐成熟了,可以做一些官网站了,于是我打算在乐山本地找一家网络公司做兼职,很快我成功的拿到了他们的网站订单,创意的设计风格加上物美价廉,很快成为了这家公司稳定的合作方,于是我在学校里面创立了自己的工作室(馒头工作室)。我的头像也是M这个LOGO也一直沿用至今。 2014年人生第一家公司14年,我们都被大学老师赶出去找工作,刚刚出来的我找了一家公司,但是很快就按耐不住想要创业的想法,于是聚集了几个同学,我们一起创办了一家公司,受到了“云来场景应用”的启发,当时我们就在想,要是能批量生产H5就好了,我们提出了“即见即所得”的概念,很快在14年发布了第一款产品"酷APP",我这里还保留了几张珍贵的截图: 但是当时缺乏商业经验以及面临公司生存的问题,没有拿到融资的我们很快就坚持不下去了,然后项目以失败告终!团队也各奔东西。 小知识:什么是H5?微信扫描以下二维码即可查看H5 H5DS v1.x 版本虽然第一款自主研发的产品失败了,但是我依然觉得这个产品是个好东西,于是贼心不死的我在15年团队解散后发布了另外一个编辑器产品(H5DS)也就是现在的1.x版本。界面是参考PhotoShop来做的,是不是感觉很像PS? H5DS v2.x 版本有了1.x版本,那就有2.x是吧?期间我去了一家创业公司,在那家公司我用下班的业余时间,在H5DS的基础上又重构了一个版本,2.x的编辑器。界面清爽了很多,而且功能也更多了。 H5DS v3.x 版本16年的时候,大多数创业公司都输给了资本,我所在的创业公司也无法避免,随着上家创业公司的倒闭,我没有马上找工作,回到家里,我继续捣鼓我的编辑器,于是很快发布了3.x版本。界面从白变黑,整个代码也重写了。可以说3.x版本完全是重构的。 H5DS v4.x 版本到现在3年了,因为兼职的原因,所以进度很慢,后来在一次技术分享会上面,我认识了我的技术合伙人,基于3.x版本,我们一起发布了4.0版本,3.0版本是jquery的版本,那么4.x就是react的版本。 H5DS v5.x 版本4.x版本的生命周期是很短的,在多次讨论后,我们在4.x之上,我们很快就发布了5.x版本。5.x版本在界面上没有做任何改动,但是代码完全重构了,5.x也就是现在的版本。从此选择了拥抱react生态,海量react组件库在H5DS中都可以使用。 产品版本总结任何产品都非一来就完美的,如果是那样,我也不用重构那么多版本了,慢慢改进打磨迭代升级,产品就会越来越完善,越来越强大。可以看到产品的进步,也可以看到我们想法的转变,任何一次升级都是为了更好的迎合市场的需求,如果希望自己的产品能走的更远,那就不要停下来!创业也是一样,并非一开始就什么都会,什么都有,也是慢慢积累起来的经验和知识,然后学以致用。感觉有点像玩游戏打怪升级,一开始在新手村混,然后到普通玩家区,再到高玩(高端玩家)区,一开始就到高玩区,肯定死翘翘了! H5DS产品概述H5DS(HTML5 design software)h5ds.com 是一款真正意义上的HTML5页面制作工具,非常难得是这个项目我做了5年,版本也换了好几个,依旧初心不改!未来还有很多个五年,我也希望自己的工具会越做越好,下面就来聊聊这个花了我无数心血做的产品。 准确的产品定位类似的竞品也比较多。比如易企秀,maka,兔展,人人秀,wps秀堂,凡科H5等。我们的产品究竟有何不同? 普通用户而言:H5是手机上用于营销的滑动页面。 专业技术人员:H5是HTML5的简称,是一门技术方案,滑动页面只是H5的一小块应用领域。 很明显,其他竞品的定位是做营销滑动页面,而我们的定位是HTML5的编辑器。可以做滑动页面,网站,3D虚拟现实,数据报表,PC网站,小程序,在线PS,在线动画制作等应用。 从一个技术到产品再到销售任何成熟稳定的产品都不是一朝一夕就能完成的,从1.x到5.x,我从一个技术慢慢也有了产品的思维,这个项目让我学到了太多的东西,我觉得是任何公司都给不了一个技术的东西,做了这个项目,让我有了和可客户坐在咖啡厅唇枪舌战的经历,同时我也有了产品经理的经验,我规划的功能也曾遭受用户的质疑,甚至有用户专门发了一个word文档给我,里面罗列了40多个编辑器改进意见,做一个产品是一件非常有意义的事情,我也兼职了UI的工作,玩起了PS,如何设计交互让用户感觉更友好,让我掉了不少头发!这个项目让我体验了设计师,技术,产品,销售,至少哪天不写代码了,还可以去跑下业务! 创业九十九死一生一路走来,我感觉自己创业以来什么都缺,缺人才,缺资金,缺资源,的确,创业是非常艰难的,如果说九死一生是其他行业的创业,那IT行业真的是99死一生。14年在风口的创业公司有多少能活到现在?14年我们创业的时候也是冲着融资去的,但是现在不是了,我觉得首先要活下去,然后再想如何发展壮大,如何赚钱。我所知道的很多IT公司都需要靠融资才可以活下去,一旦资金链断裂了,公司立马倒闭,H5DS在发布4.x版本的时候就已经能做到自负盈亏了,所以目前我们不需要融资,不用考虑生存的问题,虽然节奏慢了点,但是不至于倒闭做不下去了,先解决温饱,才可以创造价值。我希望我们的产品能走的很远,只要活着,就有希望!虽然看上去比较悲观,但是创业真的非常残酷!我非常庆幸自己没有放弃,一直坚持做自己的产品,算下来,今年是5年了,正好是v5版本。产品也比较接近我的预期。 未来会走的更远非常庆幸,我们在第一个5年活下来了,未来我们会站在巨人的肩膀上,走的更远!至于未来五年的规划,虽然我已经做好了,但是市场永远是变化不可测的,我们也会不断的更新产品,推出新鲜的功能,只希望能在这条道路上走的更远! 技术干货分享聊了太多和技术不挂边的东西,差点忘记自己是一个技术了,接下来会聊一些技术相关的东西,也算是分享一些干货给给位技术同僚!就编辑器技术部分,这里给大家做个分享。 技术选型技术选型我们采用react + mobx + koa2 + mysql 整体都是JS技术栈,至于为什么要这样选型,因为我们人少,技术保持统一,方便维护!另外一方面原因是因为我们是一个创业团队,技术资源非常宝贵,必须尽可能的节约开发成本,也是为什么我们会选择纯JS的技术栈,这样我们每个人都可以做前端也可以做后端。 mobx 最最核心的概念只有2个。 @observable 和 @observer ,它们分别对应的是被观察者和观察者。这是大家常见的观察者模式,这里使用了ES7 中的 装饰器。参数发生变化时自动触发render更新视图,这个和vue是一样的原理。之所以没有使用vue是因为我们也需要react的state配合起来做性能优化以及灵活的数据处理。我们可以结合防抖函数去做性能优化,控制或者选择性的去更新视图。下面举个例子: import React, { Component } from 'react';import { inject, observer } from 'mobx-react';import debounce from 'lodash/debounce';@inject('h5ds')@observerclass Demo extends Component { constructor(props) { super(props); this.state = { count: props.h5ds.count // 默认是1 } } // 防抖函数控制性能 updateOtherRender = debounce(() => { const { count } = this.state; // 如果大于10才会去更新其他地方的视图 if(count > 10) { this.props.h5ds.count = this.state.count } }, 500) changeValue = e => { this.setState({count: e.target.value}, this.updateOtherRender) } render() { return <input type="number" value={this.state.count} onChange={this.changeValue}/> }}我们在很多地方都有用到上面这种写法,react提倡的最小模块化,我们也希望模块之间的影响会最小,如果一个参数在多个模块中被使用,在快速输入的时候务必会变的很慢。 ...

September 10, 2019 · 2 min · jiezi

揣包自用的前端小册

慢慢整理、修改、丰富HTML相关1.HTML5的优缺点优点: 网络标准统一、HTML5本身是由W3C推荐出来的。多设备、跨平台即时更新。提高可用性和改进用户的友好体验;有几个新的标签,这将有助于开发人员定义重要的内容;可以给站点带来更多的多媒体元素(视频和音频);可以很好的替代Flash和Silverlight;涉及到网站的抓取和索引的时候,对于SEO很友好;被大量应用于移动应用程序和游戏。缺点: 安全:像之前Firefox4的web socket和透明代理的实现存在严重的安全问题,同时web storage、web socket 这样的功能很容易被黑客利用,来盗取用户的信息和资料。完善性:许多特性各浏览器的支持程度也不一样。技术门槛:HTML5简化开发者工作的同时代表了有许多新的属性和API需要开发者学习,像web worker、web socket、web storage 等新特性,后台甚至浏览器原理的知识,机遇的同时也是巨大的挑战性能:某些平台上的引擎问题导致HTML5性能低下。浏览器兼容性:最大缺点,IE9以下浏览器几乎全军覆没2.HTML5的新特性HTML5新增了 27 个元素,废弃了 16 个元素 新特性: 语义:能够让你更恰当地描述你的内容是什么连通性:能够让你和服务器之间通过创新的新技术方法进行通信离线 & 存储:能够让网页在客户端本地存储数据以及更高效地离线运行多媒体:使 video 和 audio 成为了在所有 Web 中的一等公民2D/3D 绘图 & 效果:提供了一个更加分化范围的呈现选择性能 & 集成:提供了非常显著的性能优化和更有效的计算机硬件使用设备访问 Device Access:能够处理各种输入和输出设备样式设计: 让作者们来创作更加复杂的主题3.HTML5元素根据现有的标准规范,把 HTML5的元素按优先级定义为结构性属性、级块性元素、行内语义性元素和交互性元素 4 大类。 结构性元素主要负责web上下文结构的定义 结构性元素用途section在 web 页面应用中,该元素也可以用于区域的章节描述。header页面主体上的头部, header 元素往往在一对 body 元素中。footer页面的底部(页脚),通常会标出网站的相关信息。nav专门用于菜单导航、链接导航的元素,是 navigator 的缩写。article用于表现一篇文章的主体内容,一般为文字集中显示的区域。块性元素主要完成web页面区域的划分,确保内容的有效分割 块级元素用途aside用于表达注记、贴士、侧栏、摘要、插入的引用等作为补充主体的内容。figure是对多个元素进行组合并展示的元素,通常与 ficaption 联合使用。code表示一段代码块。dialog用于表达人与人之间的对话,该元素包含 dt 和 dd 这两个组合元素, dt 用于表示说话者,而 dd 用来表示说话内容。行内语义性元素主要完成web页面具体内容的引用和描述,是丰富内容展示的基础 行内语义元素用途meter表示特定范围内的数值,可用于工资、数量、百分比等。time表示时间值。progress用来表示进度条,可通过对其 max 、 min 、 step 等属性进行控制,完成对进度的表示和监事。video视频元素,用于支持和实现视频文件的直接播放,支持缓冲预载和多种视频媒体格式。audio音频元素,用于支持和实现音频文件的直接播放,支持缓冲预载和多种音频媒体格式。交互性元素主要用于功能性的内容表达,会有一定的内容和数据的关联,是各种事件的基础。 交互性元素用途details用来表示一段具体的内容,但是内容默认可能不显示,通过某种手段(如单击)与 legend 交互才会显示出来。datagrid用来控制客户端数据与显示,可以由动态脚本及时更新。menu主要用于交互菜单(曾被废弃又被重新启用的元素)。command用来处理命令按钮。4.Doctype作用? 严格模式与混杂模式如何区分?它们有何意义?(1)、Doctype声明位于文档中的最前面,处于标签之前。告知浏览器的解析器,用什么文档类型规范来解析这个文档。 ...

September 10, 2019 · 5 min · jiezi

前端面试每日-31-第147天

今天的知识点 (2019.09.10) —— 第147天[html] 本地存储的生命周期是什么?[css] 请问background-attachmentn属性有什么用途?[js] 阻止事件的默认行为有哪些?说说它们之间的区别是什么?[软技能] 前端的性能统计有哪些指标?《论语》,曾子曰:“吾日三省吾身”(我每天多次反省自己)。 前端面试每日3+1题,以面试题来驱动学习,每天进步一点! 让努力成为一种习惯,让奋斗成为一种享受!相信 坚持 的力量!!!欢迎在 Issues 和朋友们一同讨论学习! 项目地址:前端面试每日3+1 【推荐】欢迎跟 jsliang 一起折腾前端,系统整理前端知识,目前正在折腾 LeetCode,打算打通算法与数据结构的任督二脉。GitHub 地址 微信公众号欢迎大家前来讨论,如果觉得对你的学习有一定的帮助,欢迎点个Star, 同时欢迎微信扫码关注 前端剑解 公众号,并加入 “前端学习每日3+1” 微信群相互交流(点击公众号的菜单:进群交流)。 学习不打烊,充电加油只为遇到更好的自己,365天无节假日,每天早上5点纯手工发布面试题(死磕自己,愉悦大家)。希望大家在这浮夸的前端圈里,保持冷静,坚持每天花20分钟来学习与思考。在这千变万化,类库层出不穷的前端,建议大家不要等到找工作时,才狂刷题,提倡每日学习!(不忘初心,html、css、javascript才是基石!)欢迎大家到Issues交流,鼓励PR,感谢Star,大家有啥好的建议可以加我微信一起交流讨论!希望大家每日去学习与思考,这才达到来这里的目的!!!(不要为了谁而来,要为自己而来!)交流讨论欢迎大家前来讨论,如果觉得对你的学习有一定的帮助,欢迎点个[Star] https://github.com/haizlin/fe...

September 10, 2019 · 1 min · jiezi

打开chrome一次性打开了5个进程

打开chrome,一次性打开了5个进程?!先解释一下为什么会有这么多个进程,再说为什么需要创建这么多进程。那是因为现代浏览器采用的都是多进程浏览器,每个进程处理一个任务。 以chrome浏览器为例,打开一个chrome浏览器最少会产生4个进程,分别是: 1. 浏览器进程 2. 网络进程 3. GPU进程 4. 页面进程(正常情况下一个页面一个进程,特殊情况下面详细讲) 5. 插件进程(如果有插件的话,一个插件一个进程)详细如下图:(如何查看下图这种详细的进程,chrome右上角三个点 --> 更多工具 --> 任务管理器) 特殊情况下,两个页面会共用一个页面进程:chrome 默认每个页面一个进程,特殊情况:如果你从当前页面进入另一个新的页面,而且新页面的域名和当前页面一样,那么新页面会共用当前页面的页面进程,如下图:(场景:我从文章的评论者的名字进入了他的个人主页) 那么为什么chrome要创建这么多进程,以前的单进程架构不好吗?先说说之前的单进程架构存在的问题: 不流畅 插件:插件和页面使用同一个进程,插件会堵塞页面的加载。js: 其他页面js的死循环或者页面资源加载慢会导致整个浏览器的其他页面加载都卡死或变慢。不安全 插件:插件的权限过大,可以读取和修改本地文件,甚至修改电脑配置文件(使用c/c++编写的插件,可以完全控制你的电脑)。js: js可以通过浏览器的漏洞获取电脑权限,接浏览器之手修改本机配置。不稳定 插件:插件大部分是第三方编写的,水平参差不齐,崩溃也是家常便饭,插件的崩溃将直接导致浏览器无响应或崩溃。js: 一个页面js的死循环或崩溃将导致其他页面也卡死或崩溃。所以在多年的研究、开发后,多进程架构c位出道,基本解决了这些的问题: 流畅性: 插件和页面的js只能影响自己的进程,死循环或资源加载慢只能影响自己。(当然 现代浏览器特别吃cpu和内存资源,cpu内存吃满了还是会卡,多进程浏览器的缺点)安全性 安全沙箱:系统对进程使用沙箱机制,无法写数据,只能读有限的数据,通常是你当前域名下载的文件,将恶意插件和js的后门堵死了。稳定性: 因为进程间是相互隔离的,所以当一个页面或一个插件崩溃时,仅仅只会影响到当前页面和那个插件本身,完美解决一颗老鼠屎的问题。欢迎交流,有不完善的地方欢迎指出

September 9, 2019 · 1 min · jiezi

野子数据分析概述

野子电竞数据官网改版https://www.xxe.io/全新登场数据分析1、数据分析是什么?百度百科给出的定义:2、数据分析划分3、数据分析作用3.1 现状分析3.2 原因分析3.3 预测分析4、数据分析基本步骤明确分析目的和思路数据采集数据处理数据分析数据展现报告撰写 写在前面的话:之前工作的岗位叫做数据分析工程师,主要做生产数据分析。然而由于身处液晶面板行业一家大型国企企业,很多工作内容,跟互联网行业有些出入。通过查看资料,整理了一下互联网行业针对数据分析师的定位描述,虽有些微出入,但叫做数据分析工程师也没有什么问题。大约我们差的东西,应该是时刻需要面对的压力,以及互联网行业压力下所具备的活力。1、数据分析是什么?百度百科给出的定义:数据分析是指用适当的统计分析方法对收集来的大量数据进行分析,提取有用信息和形成结论而对数据加以详细研究和概括总结的过程。这一过程也是质量管理体系的支持过程。在实用中,数据分析可帮助人们作出判断,以便采取适当行动。 2、数据分析划分数据分析可划分为:描述性数据分析、探索性数据分析、验证性数据分析。描述性数据分析属于初级数据分析,另两个属于高级数据分析。 其中探索性分析侧重于在数据之中发现新的特征,而验证性数据分析则侧重于验证已有假设的真伪证明。我们日常学习和工作中所涉及的数据分析主要是描述性数据分析。 3、数据分析作用数据分析是为了最大化地开发数据的功能,发挥数据的作用。把隐藏在一大批看似杂乱无章的数据背后的信息集中和提炼出来,总结出所研究对象的内在规律。商业领域中, 数据分析能够给帮助企业进行判断和决策,以便采取相应的策略与行动。数据分析在企业日常经营分析中主要有三大作用: 3.1 现状分析分析数据中隐藏的当前现状信息。比如告诉你企业目前运营情况,可以通过相关业务中各个指标的完成情况来进行判断等。 3.2 原因分析分析现状发生以及存在的原因。比如企业运营情况中比较好的方面,以及比较差的方面都是由哪些原因引起的,以指导做出决策,对相关策略进行调整和优化。 3.3 预测分析分析预测将来可能会发生什么。根据以往数据,对企业未来发展趋势做出预测,为制订企业运营目标及策略提供有效的参考与决策依据。一般通过专题分析来完成。 在以往的工作中,这些方面均有涉及。主要分析生产数据,和业务部门反馈沟通,以便其做出优化改善,以达到某些指标所制定的目标。 4、数据分析基本步骤这大概是一个方法论的问题。万事皆有套路,数据分析也是,大抵都是如下几个步骤:明确分析目的和思路数据采集数据处理数据分析数据展现报告撰写 明确分析目的和思路明确分析目的和思路,这是整个流程的指引方向的灯塔,是一路前行的信念。我为什么要做数据分析?我我要达到预期的什么效果?要怎么做?都应当做到胸中有丘壑。在明确了分析目的后,需要理清我们的思路,并搭建分析框架,把分析目的分解成若干个不同的分析要点,即如何具体开展数据分析,需要从哪几个角度进行分析,采用哪些分析指标。 数据采集数据采集是按照确定的数据分析框架,收集相关数据的过程,它为数据分析提供了素材和依据。根据不同的分析目的,有不同的数据来源。数据可以是直接可以获取的原始数据,也可以是经过加工后的数据。 数据处理数据处理是指对收集到的数据进行加工整理,形成适合数据分析的样式。数据处理主要包括数据清洗、数据转化、数据提取、数据计算等处理方法。一般拿到手的数据都需要进行一定的处理才能用于后续的数据分析工作。数据处理是数据分析的基础。 数据分析数据分析是指用适当的分析方法及工具,对处理过的数据进行分析,提取有价值的信息,形成有效结论的过程。数据挖掘其实是一种高级的数据分析方法, 就是从大量的数据中挖掘出有用的信息。数据挖掘侧重解决四类数据分析问题:分类、聚类、关联和预测,重点在寻找模式和规律。 数据分析与数据挖掘的本质是一样的,都是从数据里面发现关于业务的知识。 数据展现数据是通过表格和图形的方式来呈现的,我们常说用图表说话就是这个意思。常用的数据图表包括饼图、柱形图、条形图、折线图、散点图、雷达图等。数据展现可以通过各种工具来进行。比如Echarts,其他BI工具。当然Excel的图表工具也是很好的数据展现工具。 报告撰写数据分析报告其实是对整个数据分析过程的一个总结与呈现。通过报告,把数据分析的起因、过程、结果及建议完整地呈现出来,供决策者(领导)参考。

September 9, 2019 · 1 min · jiezi

CSS-loading效果之-吃豆人

emmm 名字瞎想的2333前言这是一个用来练习的css demo,如果有哪里写的不好,还请各位指正,一定虚心接受。嘻嘻 HTML布局 <div class="container"> <div class="loading"> <div class="eat"></div> <div class="load"></div> <div class="load"></div> <div class="load"></div> </div> </div>CSS 样式主要使用了动画效果,通过不断控制元素的角度位置实现一个类似于吃豆人一样的loading demo。 body { margin: 0; padding: 0; background: #fff; } .container { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); } .loading { position: relative; width: 200px; height: 50px; display: flex; } .eat { position: relative; width: 50px; height: 50px; left: 0; color: #ff0000; animation: eat-animate 2.4s ease-in-out infinite; } @keyframes eat-animate { 100% { left: 150px; } } .eat::before { content: ''; position: absolute; width: 0; height: 0; width: 50px; height: 25px; top: 0; border-radius: 50px 50px 0 0; background: currentColor; transform: rotate(-30deg); animation: eat-top 2.4s ease-in-out infinite; } @keyframes eat-top { 20% { transform: rotate(-30deg); } 35% { transform: rotate(0deg); } 45% { transform: rotate(-30deg); } 60% { transform: rotate(0deg); } 70% { transform: rotate(-30deg); } 85% { transform: rotate(0deg); } 100% { transform: rotate(0deg); } } .eat::after { content: ''; position: absolute; width: 0; height: 0; width: 50px; height: 25px; bottom: 0; border-radius: 0 0 50px 50px; background: currentColor; transform: rotate(30deg); animation: eat-bottom 2.4s ease-in-out infinite; } @keyframes eat-bottom { 20% { transform: rotate(30deg); } 35% { transform: rotate(0deg); } 45% { transform: rotate(30deg); } 60% { transform: rotate(0deg); } 70% { transform: rotate(30deg); } 85% { transform: rotate(0deg); } 100% { transform: rotate(0deg); } } .load { position: relative; width:30px; height: 30px; margin: 10px; color: #e47272; border-radius: 50%; background: currentColor; } .load:nth-child(2) { animation: load1 2.4s linear infinite; transform: scale(1); } @keyframes load1 { 35% { transform: scale(0); } 100% { transform: scale(0); } } .load:nth-child(3) { animation: load2 2.4s linear infinite; transform: scale(1); } @keyframes load2 { 30% { transform: scale(1); } 58% { transform: scale(0); } 100% { transform: scale(0); } } .load:nth-child(4) { animation: load3 2.4s linear infinite; transform: scale(1); } @keyframes load3 { 60% { transform: scale(1); } 80% { transform: scale(0); } 100% { transform: scale(0); } }Preview ...

September 9, 2019 · 2 min · jiezi

前端面试每日-31-第146天

今天的知识点 (2019.09.09) —— 第146天[html] 请说说viewport是什么?在什么时候下使用?有什么作用?[css] 移动页面底部工具条有3个图标,如何平分?在设置边框后最后一个图标掉下去了怎么办?[js] 请举例说明动态操作DOM的方法有哪些?[软技能] 移动端的用户体验有哪些优化的方法?《论语》,曾子曰:“吾日三省吾身”(我每天多次反省自己)。 前端面试每日3+1题,以面试题来驱动学习,每天进步一点! 让努力成为一种习惯,让奋斗成为一种享受!相信 坚持 的力量!!!欢迎在 Issues 和朋友们一同讨论学习! 项目地址:前端面试每日3+1 【推荐】欢迎跟 jsliang 一起折腾前端,系统整理前端知识,目前正在折腾 LeetCode,打算打通算法与数据结构的任督二脉。GitHub 地址 微信公众号欢迎大家前来讨论,如果觉得对你的学习有一定的帮助,欢迎点个Star, 同时欢迎微信扫码关注 前端剑解 公众号,并加入 “前端学习每日3+1” 微信群相互交流(点击公众号的菜单:进群交流)。 学习不打烊,充电加油只为遇到更好的自己,365天无节假日,每天早上5点纯手工发布面试题(死磕自己,愉悦大家)。希望大家在这浮夸的前端圈里,保持冷静,坚持每天花20分钟来学习与思考。在这千变万化,类库层出不穷的前端,建议大家不要等到找工作时,才狂刷题,提倡每日学习!(不忘初心,html、css、javascript才是基石!)欢迎大家到Issues交流,鼓励PR,感谢Star,大家有啥好的建议可以加我微信一起交流讨论!希望大家每日去学习与思考,这才达到来这里的目的!!!(不要为了谁而来,要为自己而来!)交流讨论欢迎大家前来讨论,如果觉得对你的学习有一定的帮助,欢迎点个[Star] https://github.com/haizlin/fe...

September 9, 2019 · 1 min · jiezi

Angular8集成Editormd的Markdown编辑器并解析markdown

Angular8集成Editor.md编辑器就不必多说了。这里主要介绍集成editormd后通过他自带的解析markdown方法,解析markdown生成html文章地址:http://www.bowen-tech.top/art...

September 8, 2019 · 1 min · jiezi

你好websocket

你好,WebSocket定义WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议(注意是协议)。 WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。 为什么使用WebSocket原本的通过HTTP协议的客户端与服务端的通信,只能由客户端发起。HTTP 协议做不到服务器主动向客户端推送信息。而且一次客户端与服务端的通信完成之后,客户端与服务端的链接就会断开,但是WebSocket是长链接,当一次连接建立以后,如果不是其中一端主动断开连接,两端的连接就会一直连接着。 WebSocket是为了解决类似聊天室的场景,原本HTTP协议这种单向请求的特点,注定了如果服务器有连续的状态变化,客户端要获知就非常麻烦。我们只能使用"轮询":每隔一段时候,就发出一个询问,了解服务器有没有新的信息。轮询的效率低,非常浪费资源(因为必须不停连接,或者 HTTP 连接始终打开)。因此,工程师们一直在思考,有没有更好的方法。WebSocket 就是这样发明的。 一:组成和特点长连接:一个连接上可以连续发送多个数据包,在连接期间,如果没有数据包发送,需要双方发链路检查包。 TCP/IP:TCP/IP属于传输层,主要解决数据在网络中的传输问题,只管传输数据。但是那样对传输的数据没有一个规范的封装、解析等处理,使得传输的数据就很难识别,所以才有了应用层协议对数据的封装、解析等,如HTTP协议。 HTTP:HTTP是应用层协议,封装解析传输的数据。从HTTP1.1开始其实就默认开启了长连接,也就是请求header中看到的Connection:Keep-alive。但是这个长连接只是说保持了(服务器可以告诉客户端保持时间Keep-Alive:timeout=200;max=20;)这个TCP通道,直接Request - Response,而不需要再创建一个连接通道,做到了一个性能优化。但是HTTP通讯本身还是Request - Response。 socket:与HTTP不一样,socket不是协议,它是在程序层面上对传输层协议(可以主要理解为TCP/IP)的接口封装。我们知道传输层的协议,是解决数据在网络中传输的,那么socket就是传输通道两端的接口。所以对于前端而言,socket也可以简单的理解为对TCP/IP的抽象协议。 WebSocket:WebSocket是包装成了一个应用层协议作为socket,从而能够让客户端和远程服务端通过web建立全双工通信。websocket提供ws和wss两种URL方案。 WebSocket 实例WebSocket 协议本质上是一个基于 TCP 的协议。 为了建立一个 WebSocket 连接,客户端浏览器首先要向服务器发起一个 HTTP 请求,这个请求和通常的 HTTP 请求不同,包含了一些附加头信息,其中附加头信息"Upgrade: WebSocket"表明这是一个申请协议升级的 HTTP 请求,服务器端解析这些附加的头信息然后产生应答信息返回给客户端,客户端和服务器端的 WebSocket 连接就建立起来了,双方就可以通过这个连接通道自由的传递信息,并且这个连接会持续存在直到客户端或者服务器端的某一方主动的关闭连接。 二:WebSocket使用创建WebSocket对象 var ws = new WebSocket(url, [protocol] ); 以上代码中的第一个参数 url, 指定连接的 URL。第二个参数 protocol 是可选的,指定了可接受的子协议。 1:属性ws.readyState: 0 - 表示连接尚未建立。 1 - 表示连接已建立,可以进行通信。 ...

September 8, 2019 · 2 min · jiezi

如何写一份好的前端面试简历

项目地址项目地址: https://github.com/Wscats/CV简历的本质在写简历之前,我们必须清楚的了解一件事情,那就是简历是什么?它不是人生履历,不是项目清单,也不是技能大放送。简历的存在只有一个目的 —— 帮你约到面试。只要能达到这个目的,简历可以是一段视频,一个开源项目,一张照片,甚至是一行字,比如: I wrote javascript当然,绝大部分简历的形式,就是我们所熟知的,是一篇文章。即使你通过其他方式获得了面试,当你入职的时候,还是要有这么一份纸质简历的,所以不要想着偷懒。 其实简历不只是表现自己,更是传递以下三个信息,增强通过率。 是什么(你能做什么?,擅长什么?)比别人好在哪些地方(相比其他同行,你的优势?)如果雇佣你,招聘方会得到什么好处 (能不能为企业带来效益?)正如你抉择跳槽,思考要不要留在这个公司的时候,你也可能考虑下面三点 待遇(给的钱够不够?福利好不好)环境(同事nice不?老板好不好?事少离家近?工作开心与否?是否帅哥美女多?嗯哼)个人(有晋升机会不?能否再进步?)当然企业和你的相互选择其实正如上面几点中的考量和博弈,当然面试是平等的,是相互选择的结果,所以有你对企业的考量,也有企业对你的考量 回归到写简历,和很多人在大学写议论文写作文是不同的,过分的论证会显得自夸,反而容易引起反感,所以要点到为止。这里的技巧是,提供论据,把论点留给阅读简历的人自己去得出。放论据要具体,最基本的是要数字化,好的论据要让人印象深刻。 举个例子,下边内容是虚构的: 2015年(时间可以具体到年月,或者经历的项目周期),我共同(一般都是团队开发了,单干就别写了,除非你个人能力非常突出)参与了XX新闻网站后端发布系统的开发(这部分是大家都会写的)。作为团队里面的核心程序员,我不但完成了网站界面、功能逻辑的开发工作,更提出了高效的组件化和模块化开发方案,通过模块化开发让团队成员较少编写代码时候的冲突,通过组件化让团队成员分工合作,各善其职,有效的提升了系统的的开发效率。(这部分是很多人忘掉的,记得写出你在这个项目中具体负责的部分,以及你贡献出来的价值。)在该系统上线后,Web前端性能从10QPS提升到200QPS,服务器由10台减少到3台( 通过量化的数字来增强可信度 )。2016年我升任WAPCMS项目负责人,带领一个3人小组支持着每天超过2亿的PV( 这就是你自身的优势。你能带给旧企业的价值,也就是你能带给新企业的价值。 )。 有同学问,如果我在项目里边没有那么显赫的成绩可以说怎么办?讲不出成绩时,就讲你的成长。因为学习能力也是每家公司都看中的东西。你可以写你在这个项目里边遇到了一个什么样的问题,别人怎么解决的,你怎么解决的,你的方案好在什么地方,最终这个方案的效果如何。 具体、量化、有说服力,是技术简历特别需要注重的地方。 (以上内容在写完简历后,对每一段进行评估,完成后再删除) 联系方式(HR会打印你的简历,用于在面试的时候联系,所以联系方式放到最上边会比较方便) 头像(如果你觉得自己长得可以,你可以放哈)手机:139 (如果是外地手机,可注明。如经常关机,要写上最优联系时间)Email:wscats@gmail.com (虽然我觉得QQ邮箱无所谓,不过有些技术人员比较反感,建议用163,gmail也可以)QQ/微信号:7*(提供一个通过网络可以联系到你的方式)个人信息易佳梦/女/1990本科/XX大学计算机系工作年限/经验:3年技术博客:https://wscats.github.io/blog ( 使用GitHub Page映射页面会显得的逼格较高 )Github:https://github.com/Wscats ( 原创repo+多star的Github帐号会极大的提升你的个人品牌 )期望职位:Web前端程序员/工程师期望薪资:税前月薪15k~20k,特别喜欢的公司可例外期望城市:广州工作经历工作经历按逆序排列,最新的在最前边,因为HR更多的是了解你在上一家公司或者近几年你的工作情况,我建议实际工作小于半年的你也可以不写当然(IT行业跳槽如此平凡~),因为短的在职经历会让HR觉得你不够稳定,存在录用后的风险,还有工作经历最好有层次感,比如你刚开始第一份前端工作你用的技术比较简单,你可以写你自己负责切图,用jQuery写逻辑,用sass写样式,然后再下一份工作你可能技术加强了,你就可以写你用vue,angular来开发了一个单页面应用,还负责写了部分后端接口,这样可以让面试官觉得你有自我学习,不断进步的习惯。 123公司 ( 2016年9月 ~ 2017年9月 )456项目我在此项目负责了哪些工作,分别在哪些地方做得出色/和别人不一样/成长快,这个项目中,我最困难的问题是什么,我采取了什么措施,最后结果如何。这个项目中,我最自豪的技术细节是什么,为什么,实施前和实施后的数据对比如何,同事和领导对此的反应如何。 789项目我在此项目负责了哪些工作,分别在哪些地方做得出色/和别人不一样/成长快,这个项目中,我最困难的问题是什么,我采取了什么措施,最后结果如何。这个项目中,我最自豪的技术细节是什么,为什么,实施前和实施后的数据对比如何,同事和领导对此的反应如何。 其他项目(每个公司写2~3个核心项目就好了,如果你有非常大量的项目,那么按分类进行合并,每一类选一个典型写出来。其他的一笔带过即可。) 根据上面的模板你可以这样来写 广州XX有限公司(2016.09 ~ 2017.03)技术部-前端工程师这个项目目的主要以成人学历为主线开发,有大专、本科、资格证等线上销售的教育培训产品。我在此项目负责了前期界面研究,做出原型设计,原型切图,配合后台开发人员设计界面与开发功能,并负责框架开发,封装公共组件,以及根据需要引进第三方插件。我在项目中遇到的最大困难是实现产品前端界面效果与设计图纸在某些界面上难以绝对统一我采用Vue+jQuery开发方案,在细节上我运用了jwplayer.js、jquery.KinSlideshow来实现幻灯片轮播效果,增强用户体验更好等。自我评价最好突出自己的优势,比如学习能力,解决问题能力,带队能力,沟通能力和技术能力等等想简单点可以这样写: 1.喜欢学习新技术,有良好的文档编写和代码书写规范,耐心打磨用户体验和用户界面2.有良好的沟通能力和团队合作能力,性格随和,认真负责,自学能力强详细的你也可以这样来 1. 对前端技术具有浓厚的兴趣,喜欢逛CSDN,博客园等技术论坛;2. 具备良好的审美能力,有良好的代码编程习惯;(说好的审美,可以和设计师好好玩耍)3. 学习适应能力强,愿意不断学习新知识丰富自己;(学习能力大企业最看重)4. 抗压能力强,有信心在不同的工作强度下进行开发工作;(抗压技能点加上,去常加班的公司有独特优势,额)5. 性格随和,具有良好的团队合作精神。(性格最好能适应团队)开源项目和作品选取你自己Github上的某个开源项目即可,当然开源项目最好写清楚文档,比如安装方法,核心代码的分析(这一段用于放置工作以外的、关键来证明你的能力的材料,也可以理解为其他工程师或者开源社区对你的认可度) 开源项目(对于程序员来讲,没有什么比Show me the code能有说服力了) Piano:????用键盘8个键演奏一首蒲公英的约定送给自己或月亮代表我的心送给她(项目的简要说明,Star和Fork数多的可以注明)Articles:????分享我的学习片段和与你的回忆(项目的简要说明,Star和Fork数多的可以注明)技术文章(挑选你写作或翻译的技术文章,好的文章可以从侧面证实你的表达和沟通能力,也帮助招聘方更了解你) 我如何用前端技术得到XXOO网站的VIP前端程序员经常忽视的一个JavaScript面试题 ( 或者好的翻译文章可以侧证你对英文技术文档的阅读能力)技能清单(我一般主张将技能清单写入到工作经历里边去。不过很难完整,所以有这么一段也不错)以下均为我熟练使用的技能 后端开发:PHP/Node后端框架:ThinkPHP/CodeIgniter前端框架:ReactJS/VueJS/AngularJS/Omi/EmberJS/Cocos2dJS/Ionic前端样式库:WeUI/Bootstrap/AntDesign/ElementUI/AmazeUI前端工具库:jQuery/Zepto/Lodash/Axios前端调试:Postman/Charles/Vue(React) Dev Tools前端插件:Swiper/Iscroll前端模块工具:Webpack/Gulp/RequireJS/Fis/Grunt预编译语言:Typescript/Sass/Less/Pug/JadeNative开发:Weex/React Native/Cordova/Uni App小程序相关:Mpvue/Taro/Kbone/Wepy数据库相关:MySQL/MongoDB/PgSQL/PDO/SQLite版本管理、文档和自动化部署工具:SVN/Git单元测试:PHPUnit/SimpleTest/Qunit/Mocha云和开放平台:SAE/BAE/AWS/微博开放平台/微信应用开发例如你可以这样写,当然你得根据自己的个人情况进行修改 1、熟练使用合理的结构和样式编写兼容主流浏览器的页面;2、能适当运用CSS3使页面在现代浏览器上效果更佳;3、熟练运用rem单位和flex布局实现不同浏览器宽度下的整页缩放;4、熟练使用photoshop软件进行简单的图片处理,能根据图片特征保存成最优的格式;5、熟练使用原生javaScript以及常用javaScript库,如jQuery、zepto;6、能运用模块化、面向对象的方式编程;7、了解http协议,能够根据http请求报文、响应报文和状态码排查问题;8、熟练运用ajax实现异步数据传递,熟悉JSON等数据交换格式;了解php和数据库;9、了解如何使用node.js搭建本地server模拟接口返回数据测试ajax接口;10、能使用Bootstrap、WeUI、Ionic等前端样式库和框架进行开发;11、熟练运用AngularJS,VueJS进行模块开发,了解双向数据绑定原理,熟练编写控制器、服务、组件、过滤器等12、熟练使用Gulp对代码进行压缩合并;熟悉使用Git和SVN进行代码管理和版本控制;当然再举个例子(精通慎用!熟悉可以多用,不够自信就用了解吧,额哼) 1、熟练HTML、DIV+CSS的页面布局,能根据设计图完成页面制作2、熟练响应式布局、弹性盒布局,熟悉基于HTML5的WebApp开发以及移动端适配3、熟练主流浏览器的兼容性以及相应的适配技术,完成页面的完整兼容4、熟练掌握HTML5、CSS3新增功能,了解Canvas动画制作5、熟悉掌握原生JavaScript,熟悉jQuery,了解Zepto6、熟练Bootstrap、AngularJS等前段框架,了解MUI、Vue框架7、熟练使用AJAX进行数据交互,协助后端开发工程师完成项目8、熟练JSON数据的使用以及处理方式9、熟练LocalStorage、SessionStorage、Cookie等本地存储10、熟悉使用Swiper、Font-awesome、jQueryUI以及jQuery插件等前端插件11、熟练使用Cordova插件将WebApp打包成安卓App,实现混合App开发12、熟练使用Visual Studio Code、SublimeText、HBulider、Git、Gulp、Scss、Photoshop 等开发工具这里尽量不要重复叙述相同的技能点,保持好每一条都是独特的,每一条描述出现的英文技能点关键词尽量保持大小统一,比如Bootstrap、WeUI、Ionic,这样写没问题,但是不要个别大写个别小写bootstrap、WeUI、ionic,遇到强迫症的HR就尴尬了,不过有些还是例外的比如jQuery,还是第二个字母大写吧(...额,不解释),还有这里不要出现一些“感性“的描述,比如熟悉使用PHP,能跟后端工程师愉快的合作(什么鬼),这些句子就不要出现了 ...

September 8, 2019 · 1 min · jiezi

前端面试每日31周汇总20190908

《论语》,曾子曰:“吾日三省吾身”(我每天多次反省自己)。 前端面试每日3+1题,以面试题来驱动学习,每天进步一点! 让努力成为一种习惯,让奋斗成为一种享受!相信 坚持 的力量!!!学习不打烊,充电加油只为遇到更好的自己,365天无节假日,每天早上5点纯手工发布面试题(死磕自己,愉悦大家)。希望大家在这浮夸的前端圈里,保持冷静,坚持每天花20分钟来学习与思考。在这千变万化,类库层出不穷的前端,建议大家不要等到找工作时,才狂刷题,提倡每日学习!(不忘初心,html、css、javascript才是基石!)欢迎大家到Issues交流,鼓励PR,感谢Star,大家有啥好的建议可以加我微信一起交流讨论!希望大家每日去学习与思考,这才达到来这里的目的!!!(不要为了谁而来,要为自己而来!)【推荐】欢迎跟 jsliang 一起折腾前端,系统整理前端知识,目前正在折腾 LeetCode,打算打通算法与数据结构的任督二脉。GitHub 地址 html说说你对表单属性type="hidden"的理解,它的运用场景有哪些?SGML(标准通用标记语言)和HTML(超文本标记语言),XML(可扩展标记语言)和HTML的之间有什么关系?请说说<pre>和<code>标签的区别?如何实现应用缓存?说说你对manifest的理解form标签定义请求类型和请求地址分别是哪个属性?说说你对HTML5的keygen标签的理解,它的作用是什么?如何让textarea标签中的内容原格式输出?csscss怎样使每个字符宽度一样?说下你对background-size的理解,它有什么运用场景?如何自定义radio按钮的样式word-wrap、word-break和white-space有什么区别?说说你对字母"X"在CSS中有什么作用?CSS3中的transition是否可以过渡opacity和display?说下background-color:transparent和opacity:0的区别是什么?js原生Math的方法有哪些?请列举并描述其功能什么是词法分析?请描述下js词法分析的过程?自己实现数组的 map、filter、find 方法请描述下函数的执行过程写一个洗扑克牌的方法说用原生js实现封装一个选项卡的功能说下你对柯里化函数(currying)的理解,它有什么运用场景?软技能为什么提倡利用多个域名来存储网站的资源?W3C是什么?请说说你对它的理解你有自己的博客吗?维护的频率是多久呢?在选择框架时应该考虑哪些因素?你觉得你上家公司的前端开发流程有什么地方要优化的吗?怎么优化呢?你会PHP、JAVA、Python或GO吗?都有做过哪些应用呢?你知道Jenkins吗?有没有用过?说说你对它的理解全部所有 交流讨论欢迎大家前来讨论,如果觉得对你的学习有一定的帮助,欢迎点个Star, 同时欢迎加入 “前端面试每日3+1” 微信群(扫个人微信号邀请入群)相互交流。

September 8, 2019 · 1 min · jiezi