使用-Authing-Lambda-替代-AWS-Cognito

Amazon Web Services(AWS) 虽然作为市场份额全球第一的云计算厂商,其产品也不是完美无缺的,Cognito (AWS 的身份认证解决方案)及其附带的中文文档就是一个反面教材,其难用程度令人发指。当然,除了不易用之外,还有访问速度缓慢,不适用于中国市场等问题存在。 而国产的 Authing 可以解决使用 Cognito 的诸多问题,先看一下 Authing 的介绍: Authing 是一个身份认证服务商,其提供了企业级身份认证和管理解决方案,客户分布教育、IoT、互联网和电商等多个行业。Lambda 是一个由 AWS 提供的 Function-as-a-Service (FaaS) 平台 。Lambda 和 AWS 生态结合的非常紧密,接入 Lambda 后,开发者可以使用 AWS 生态内的所有资源。比如,我们可以创建一个 Lambda 函数,让用户通过 Cognito 登录(当然这篇文章是让用户使用 Authing 登录),然后再调用另外一个可以上传文件到 S3(AWS 的存储服务) 的 Lambda 函数。 这类平台(现在多被称为 Serverless,无服务器架构)的一个好处是可以让开发者无需担心基础设施,专心业务研发。 FaaS 或者说 Serverless 平台正在逐渐获得市场关注,因为这种类型的平台可以让开发者不用再关注基础设施。"What is serverless" 这篇文章详细的讲解了什么是「无服务器计算」和「无服务器计算」的好处,推荐读一下。 这篇文章的主要目的是介绍如何使用 Authing + Lambda 替代 AWS Cogito,点击这里体验最终 demo。 此外,Authing 遵循 OIDC 规范,所以本篇文章将使用 OIDC 来做认证,如果你还不了解什么是 OIDC,请查看这篇文章。 首先确认下用户的操作流程: ...

April 30, 2019 · 4 min · jiezi

阿里云-TXD-前端月刊望穿春色满园四月烟蓑雨笠

【Alibaba-TXD 前端小报】- 热门前端技术快报,聚焦业界新视界;前端领域急速发展的节奏从未停歇,即将流逝的四月里,Nodejs 发布了 v12 版本,Chrome75 也将原生支持懒加载……也许是大潮将至,亦或是好事将近,总之,在下还能学!!! 欢迎 订阅 & 投稿本期小编:佐七 学习专栏 2019 前端工程师手册(front-end-handbook-2019)这个受欢迎的前端详细指南于本年度再次回归。更新了大量有用的资源、学习资料和开发工具。内容非常全面,值得一看。 Css Layout CookbookMDN 官网为前端开发者总结的一些常用布局模块的实现方案。包括面包屑,分页,导航栏等,值得参考。 11 个教程中不常被提及的 JavaScript 小技巧本文作者选取了 11 个在我们工作中经常出现却容易被忽略的 JavaScript 小技巧,可以帮助我们更高效的进行编码。 45 个值得收藏的 CSS 形状本文列举了一些我们日常会用到的一些 CSS 形状,值得参考。此外,在Houdini 已经到来的当下,也许一句 --shape: 'triangle' ,即可使用,无需重复编写这些 CSS 形状。 新闻快报 第五届 CSS 大会顺利举行第五届 CSS 大会于 2019 年 3 月 30 日在深圳举办,本次会议共邀请了 7 位演讲嘉宾出席演讲,其中有我们熟悉的大漠,张鑫旭,勾三股四等,为我们分享了一些新时代下的 CSS 技术。 Chrome75 将原生支持懒加载过去我们一直通过 js 来实现图片的延迟加载,而 Chrome75 的到来将原生支持该功能。我们可以通过设置 loading 属性来控制浏览器是否延迟加载屏幕外的图像和 iframe。示例代码如下: <img src="celebration.jpg" loading="lazy" alt="..." /><iframe src="video-player.html" loading="lazy"></iframe>让我们看一下效果: ...

April 30, 2019 · 2 min · jiezi

css两种垂直居中对齐解决方案

第一种垂直居中方法利用vertical-align:middle进行垂直方向上的居中对齐,此方法需要满足的条件: 设置父元素的行高line-height等于父元素height的高度子元素必须是行内块级元素display:inline-block;子元素设置vertical-align:middle此方法在开发中不能右浮动(不能靠右边)下方是完整代码,可以新建一个HTML文件进行测试(绿色的盒子): <html><head><title>导航条</title><meta charset="utf-8" /></head><style>*{ margin:0; padding:0;}.div1{ height:200px; background:yellow; /*行高等于容器高度*/ line-height:200px;}.div2{ width:100px; height:100px; background:green; /*行内块级元素*/ display:inline-block; /*中线和父元素基线上方出对其,参考字母"x"*/ vertical-align:middle;}.div3{ width:100px; height:100px; background:red; display:inline-block;} </style><body><div class="div1">xxxxxxxxxxx <div class="div2" > </div> <div class="div3" > </div></div></body></html>第一种方法结束。 第二种垂直居中方法这种方法比较暴力,利用定位解决: 父元素开启相对定位子元素绝对定位子元素先向下移动父元素的50%,此时子元素的顶部与父元素的中线对齐了子元素再向上移动自身高度"height"的一半,此时子元素的中线和父元素的中线对齐了此方法可以右对齐,设置子元素right:0px;即可下方是完整代码,可以新建一个HTML文件进行测试(绿色的盒子): <html><head><title>导航条</title><meta charset="utf-8" /></head><style>*{ margin:0; padding:0;}.div1{ height:200px; background:yellow; /*相对定位开启*/ position:relative;}.div2{ width:100px; height:100px; background:green; /*绝对定位*/ position:absolute; /*可以右对齐*/ right:0px; /*先向下移动父元素的50%,此时子元素的顶部与父元素的中线对齐了*/ top:50%; /*再向上移动自身高度"height"的一半,此时子元素的中线和父元素的中线对齐了*/ margin-top:-50px} </style><body><div class="div1"> <div class="div2" > </div></div></body></html>第二种方法结束。 总结上面两种方法的特点都是让子元素的中线和父元素的中线对齐。

April 30, 2019 · 1 min · jiezi

重学前端学习笔记六JavaScript类型有哪些你不知道的细节

笔记说明重学前端是程劭非(winter)【前手机淘宝前端负责人】在极客时间开的一个专栏,每天10分钟,重构你的前端知识体系,笔者主要整理学习过程的一些要点笔记以及感悟,完整的可以加入winter的专栏学习【原文有winter的语音】,如有侵权请联系我,邮箱:kaimo313@foxmail.com。JavaScript类型有哪些你不知道的细节?winter提了几个问题测试:能回答对几个?1、为什么有的编程规范要求用 void 0 代替 undefined?2、字符串有最大长度吗?3、0.1 + 0.2 不是等于 0.3 么?为什么 JavaScript 里不是这样的?4、ES6 新加入的 Symbol 是个什么东西?5、为什么给对象添加的方法能用在基本类型上?如果有点犹豫,不妨看看下面的介绍,或者找找资料温习一下。类型UndefinedNullBooleanStringNumberSymbolObject1、Undefined、NullUndefined: Undefined 类型表示未定义,它的类型只有一个值,就是 undefined任何变量在赋值前是 Undefined 类型、值为 undefinedJavaScript 的代码 undefined 是一个变量,而并非是一个关键字,这是 JavaScript 语言公认的设计失误之一为了避免无意中被篡改,可以使用 void 0 来获取 undefined 值。Null: Null 类型也只有一个值,就是 null,它的语义表示空值与 undefined 不同,null 是 JavaScript 关键字在任何代码中,都可以用 null 关键字来获取null值2、StringString 用于表示文本数据String 有最大长度是 2^53 - 1字符串的最大长度,实际上是受字符串的编码长度影响的。Note: 现行的字符集国际标准,字符是以 Unicode 的方式表示的,每一个 Unicode 的码点表示一个字符,理论上,Unicode 的范围是无限的。UTF 是 Unicode 的编码方式,规定了码点在计算机中的表示方法,常见的有 UTF16 和 UTF8。Unicode 的码点通常用 U+??? 来表示,其中 ??? 是十六进制的码点值。0-65536(U+0000 - U+FFFF)的码点被称为基本字符区域(BMP)。3、NumberJavaScript 中的 Number 类型有 18437736874454810627(即 2^64-2^53+3) 个值NaN,占用了 9007199254740990,这原本是符合 IEEE 规则的数字Infinity,无穷大-Infinity,负无穷大根据双精度浮点数的定义,Number 类型中有效的整数范围是-0x1fffffffffffff 至 0x1fffffffffffff,所以 Number 无法精确表示此范围外的整数根据浮点数的定义,非整数的 Number 类型无法用 ==(=== 也不行)来比较关于javaScript中 0.1 + 0.2 == 0.3 ? 这个问题的解释: ...

April 30, 2019 · 2 min · jiezi

微信网页授权分享踩过的坑

页面用浏览器自带返回和安卓物理返回死循环的话,直接看高潮部分 背景折磨我两个工作日加周末一天的问题,我觉得还是有必要记录一下,为什么程序员总是加班,就是遇到这些意想不到的问题 需求领导:我想做两个页面,放在微信里面可以访问我:简单啊,用H5实现产品设计中...产品:好了,看看没问题就开始开发吧我:什么时候多了一个需要获取用户信息(产品总是给人惊喜不端) 没有试过微信授权这一块,首先内心三连问,能不能拒绝,能不能改需求,能不能通过熟悉的秘方实现;然而并没有什么用(笑哭表情) 开发中业务功能没什么难点,模拟一个用户信息,很快就开发完成了... 微信网页授权官方文档:https://mp.weixin.qq.com/wiki... 1.登录自己的服务号,查看已有的权限 注意:这里只能是服务号,订阅号没有权限,服务号只能由企业和组织申请 2.公众号设置 注意:授权回调域名配置规范为全域名,比如需要网页授权的域名为:www.qq.com,配置以后此域名下面的页面http://www.qq.com/music.html 、 http://www.qq.com/login.html 都可以进行OAuth2.0鉴权。但http://pay.qq.com 、 http://music.qq.com 、 http://qq.com无法进行OAuth2.0... 注意:下载这个文件放在域名对应的根目录下 3.链接的生成 https://open.weixin.qq.com/co... 以访问www.qq.com/#/detail.html为例,上面第2步的网页授权域名设置成 www.qq.comREDIRECT_URI为encodeURIComponent('http://www.qq.com/#/detail.html')SCOPE为snsapi_base或snsapi_userinfo,区别是只获取用户id,还是获取更多用户信息state随便写吧,以123为例(没有看出具体有什么用)其它参数不变 注意:为什么要用encodeURIComponent,你想想,你在url里面直接写url,怎么能直接把它解析成参数 4.放在微信里访问 把第3步上面生成的链接,做为聊天消息,拷贝到微信里面,点击打开,此时我们用alert(location.href)就会发现,地址变成了http://www.qq.com/?code=生成... // 获取url参数export function getQueryVariable(variable) { const query = window.location.search.substring(1) const vars = query.split("&") for (let i=0; i<vars.length; i++) { const pair = vars[i].split("=") if(pair[0] === variable) return pair[1] } return undefined}// 获取code的值const code = getQueryVariable('code')注意:code只能用一次,而且还有时间限制,code插入的位置尤其要注意,不是在/#/后面,所以用vue或react的路由组件中获取路由参数方式是不可行的,老老实实的写原生js获取 5.通过code获取用户id code获取到了以后前端就无能为力了,接下来的步骤只能交给后台了(数据安全性考虑,比如AppSecret不能暴露给前端),自古以来,前端的地位略低于后端,nodejs的出现极大的拯救了前端,虽然后面的事情前端做不了,但我们可以用nodejs或者是类似于postman这种的工具,把后面的接口模拟跑通,然后直接告诉后端,你该调什么接口,用什么参数,后端文档都不用看;当然你也可以做个小白纸,什么都抛给后端,让后端指挥你怎么做(在一个团队中,各个角色的重要性,就看能做的事情) ...

April 29, 2019 · 2 min · jiezi

移动端下开启控制台

最近在做H5的微信登录,自己的账号没有问题,其他账号就有问题,也不能都让人家放到开发者工具测试吧,很麻烦,所以为了定位到问题,在网上搜索了一下,就是在移动端下也能看见控制台,真是个贴心的工具 // 加载控制台export const loadScript = (url, callback) => { const script = document.createElement('script') script.onload = () => callback() script.src = url document.body.appendChild(script)} loadScript('https://res.wx.qq.com/mmbizwap/zh_CN/htmledition/js/vconsole/3.0.0/vconsole.min.js', () => {// eslint-disable-next-linenew VConsole()具体参考了__Daniel的文章

April 29, 2019 · 1 min · jiezi

XorPay-支付平台-新增个人支付宝当面付接口

XorPay 支付平台 新增 个人支付宝当面付 接口,支付宝官方支付接口个人可申请,欢迎开发者使用。 「 XorPay 支付平台」 是个人可用的 支付宝/微信支付 接口,支持 当面付 / NATIVE / JSAPI / 收银台 / 小程序 / WAP / H5 等支付方式,资金由 支付宝/微信 官方 T+1 结算自动下发个人银行卡( 其中支付宝为即时到账,到你的支付宝账号) 个人支付宝当面付接口XorPay 技术文档GitHub 仓库Demo欢迎留言讨论

April 29, 2019 · 1 min · jiezi

前端面试题总结jshtml小程序ReactES6Vue算法全栈热门视频资源

本文是关注微信小程序的开发和面试问题,由基础到困难循序渐进,适合面试和开发小程序。并总结vue React html css js 经典面试题 集各种算法和插件、前端视频源码资源于一身的文档,优化项目,在浏览器端的层面上提升速度,帮助初中级前端工程师快速搭建项目。 参考答案https://www.kancloud.cn/lemon-m/js-html-css Vue面试题生命周期函数面试题 1.什么是 vue 生命周期 2.vue生命周期的作用是什么 3.第一次页面加载会触发哪几个钩子 4.简述每个周期具体适合哪些场景 5.created和mounted的区别 6.vue获取数据在哪个周期函数 7.请详细说下你对vue生命周期的理解?vue路由面试题 1.mvvm 框架是什么? 2.vue-router 是什么?它有哪些组件 3.active-class 是哪个组件的属性? 4.怎么定义 vue-router 的动态路由? 怎么获取传过来的值 5.vue-router 有哪几种导航钩子? 6.$route 和 $router 的区别 7.vue-router响应路由参数的变化 8.vue-router传参 9.vue-router的两种模式 10.vue-router实现路由懒加载( 动态加载路由 )vue常见面试题 1.vue优点 2.vue父组件向子组件传递数据? 3.子组件像父组件传递事件 4.v-show和v-if指令的共同点和不同点 5.如何让CSS只在当前组件中起作用 6.<keep-alive></keep-alive>的作用是什么? 7.如何获取dom 8.说出几种vue当中的指令和它的用法? 9. vue-loader是什么?使用它的用途有哪些? 10.为什么使用key 11.axios及安装 12.axios解决跨域 13.v-modal的使用 14.scss的安装以及使用 15. 请说出vue.cli项目中src目录每个文件夹和文件的用法? 16.分别简述computed和watch的使用场景 17.v-on可以监听多个方法吗 18.$nextTick的使用 19.vue组件中data为什么必须是一个函数 20.vue事件对象的使用 21 组件间的通信 22.渐进式框架的理解 23.Vue中双向数据绑定是如何实现的 24.单页面应用和多页面应用区别及优缺点 25.vue中过滤器有什么作用及详解 26.v-if和v-for的优先级 27.assets和static的区别 28.列举常用的指令 29.vue常用的修饰符 30.数组更新检测 31.Vue.set视图更新 32.自定义指令详解 33.vue的两个核心点 34.vue和jQuery的区别 35 引进组件的步骤 36.Vue-cli打包命令是什么?打包后悔导致路径问题,应该在哪里修改 37.三大框架的对比 38. 跨组件双向数据绑定 39.delete和Vue.delete删除数组的区别 40.SPA首屏加载慢如何解决 41.Vue-router跳转和location.href有什么区别 42. vue slot 43.你们vue项目是打包了一个js文件,一个css文件,还是有多个文件? 44.vue遇到的坑,如何解决的? 45.Vue里面router-link在电脑上有用,在安卓上没反应怎么解决? 46.Vue2中注册在router-link上事件无效解决方法 47.RouterLink在IE和Firefox中不起作用(路由不跳转)的问题 48.axios的特点有哪些 49.请说下封装 vue 组件的过程?vuex常见面试题 1.vuex是什么?怎么使用?哪种功能场景使用它? 2.vuex有哪几种属性 3.不使用Vuex会带来什么问题 4.Vue.js中ajax请求代码应该写在组件的methods中还是vuex的actions中? 5.vuex一个例子方法 6.Vuex中如何异步修改状态 7.Vuex中actions和mutations的区别ES6面试题ES6新增方法面试题 1.let const var比较 2.反引号(`)标识 3.函数默认参数 4.箭头函数 5.属性简写 6.方法简写 7.Object.keys()方法,获取对象的所有属性名或方法名 8.Object.assign ()原对象的属性和方法都合并到了目标对象 9.for...of 循环 10.import和export 11.Promise对象 12.解构赋值 13.set数据结构(可用于快速去重) 14.Spread Operator 展开运算符(...) 15.字符串新增方法ES6数组面试题 1.forEach() 2.map() 3.filter() 4.reduce() 5.some() 6.every() 7.all()方法ES6编程题 1.使用解构,实现两个变量的值的交换 2.利用数组推导,计算出数组 [1,2,3,4] 每一个元素的平方并组成新的数组。 3.使用ES6改下面的模板 4.把以下代码使用两种方法,来依次输出0到9?react面试题react生命周期面试题 1.react 生命周期函数 2.react生命周期中,最适合与服务端进行数据交互的是哪个函数 3.运行阶段生命周期调用顺序 4.shouldComponentUpdate 是做什么的,(react 性能优化是哪个周期函数?) 5.指出(组件)生命周期方法的不同react 基础面试题 1.React 中 keys 的作用是什么? 2.React 中 refs 的作用是什么? 3.React 中有三种构建组件的方式 4.调用 setState 之后发生了什么? 5.react diff 原理(常考,大厂必考) 6.为什么建议传递给 setState 的参数是一个 callback 而不是一个对象 7.除了在构造函数中绑定 this,还有其它方式吗 8.setState第二个参数的作用 9.(在构造函数中)调用 super(props) 的目的是什么 10.简述 flux 思想 11.在 React 当中 Element 和 Component 有何区别? 12.描述事件在 React 中的处理方式。 13.createElement 和 cloneElement 有什么区别? 14.如何告诉 React 它应该编译生产环境版本? 15.Controlled Component 与 Uncontrolled Component 之间的区别是什么?react组件面试题 1.展示组件(Presentational component)和容器组件(Container component)之间有何不同 2.类组件(Class component)和函数式组件(Functional component)之间有何不同 3.(组件的)状态(state)和属性(props)之间有何不同 4.何为受控组件(controlled component) 5.何为高阶组件(higher order component) 6.应该在 React 组件的何处发起 Ajax 请求 7.react中组件传值 8.什么时候在功能组件( Class Component )上使用类组件( Functional Component )? 9.受控组件( controlled component )与不受控制的组件( uncontrolled component )有什么区别? 10.react 组件的划分业务组件技术组件?redux面试题 1.redux中间件 2.redux有什么缺点 3.了解 redux 么,说一下 redux 把react性能比较面试题 1.vue和react的区别 2.react性能优化的方案 3.React 项目用过什么脚手架 4.介绍一下webpack webpack 5.如果你创建了类似于下面的 Twitter 元素,那么它相关的类定义是啥样子的? 6.为什么我们需要使用 React 提供的 Children API 而不是 JavaScript 的 map?js面试题1.简述同步和异步的区别2.怎么添加、移除、复制、创建、和查找节点3.实现一个函数clone 可以对Javascript中的五种主要数据类型(Number、string、Object、Array、Boolean)进行复制4.如何消除一个数组里面重复的元素5.写一个返回闭包的函数6.使用递归完成1到100的累加7.Javascript有哪几种数据类型8.如何判断数据类型9.console.log(1+'2')和console.log(1-'2')的打印结果10.Js的事件委托是什么,原理是什么11.如何改变函数内部的this指针的指向12.列举几种解决跨域问题的方式,且说明原理13.谈谈垃圾回收机制的方式及内存管理14.写一个function ,清除字符串前后的空格15.js实现继承的方法有哪些16.判断一个变量是否是数组,有哪些办法17.let ,const ,var 有什么区别18.箭头函数与普通函数有什么区别19.随机取1-10之间的整数20.new操作符具体干了什么21.Ajax原理22.模块化开发怎么做23.异步加载Js的方式有哪些24.xml和 json的区别25.webpack如何实现打包的26.常见web安全及防护原理27.用过哪些设计模式28.为什么要同源限制29.offsetWidth/offsetHeight,clientWidth/clientHeight与scrollWidth/scrollHeight的区别30.javascript有哪些方法定义对象31.说说你对promise的了解32.谈谈你对AMD、CMD的理解33.web开发中会话跟踪的方法有哪些34.介绍js有哪些内置对象?35.说几条写JavaScript的基本规范?36.javascript创建对象的几种方式?37.eval是做什么的?38.null,undefined 的区别?39.[“1”, “2”, “3”].map(parseInt) 答案是多少?40.javascript 代码中的”use strict”;是什么意思 ? 使用它区别是什么?41.js延迟加载的方式有哪些?42.defer和async43.说说严格模式的限制44.attribute和property的区别是什么?45.ECMAScript6 怎么写class么,为什么会出现class这种东西?46.常见兼容性问题47.函数防抖节流的原理48.原始类型有哪几种?null是对象吗?49.为什么console.log(0.2+0.1==0.3) //false50.说一下JS中类型转换的规则?51.深拷贝和浅拷贝的区别?如何实现52.如何判断this?箭头函数的this是什么53.== 和 ===的区别54.什么是闭包55.JavaScript原型,原型链 ? 有什么特点?56.typeof()和instanceof()的用法区别57.什么是变量提升58.all、apply以及bind函数内部实现是怎么样的59.为什么会出现setTimeout倒计时误差?如何减少60.谈谈你对JS执行上下文栈和作用域链的理解61.new的原理是什么?通过new的方式创建对象和通过字面量创建有什么区别?62.prototype 和 proto 区别是什么?63.使用ES5实现一个继承?64.取数组的最大值(ES5、ES6)65.ES6新的特性有哪些?66.promise 有几种状态, Promise 有什么优缺点 ?67.Promise构造函数是同步还是异步执行,then呢 ?promise如何实现then处理 ?68.Promise和setTimeout的区别 ?69.如何实现 Promise.all ?70.如何实现 Promise.finally ?71.如何判断img加载完成72.如何阻止冒泡?73.如何阻止默认事件?74.ajax请求时,如何解释json数据75.json和jsonp的区别?76.如何用原生js给一个按钮绑定两个onclick事件?77.拖拽会用到哪些事件78.document.write和innerHTML的区别79.jQuery的事件委托方法bind 、live、delegate、on之间有什么区别?80.浏览器是如何渲染页面的?81.$(document).ready()方法和window.onload有什么区别?82. jquery中$.get()提交和$.post()提交有区别吗?83.对前端路由的理解?前后端路由的区别?84.手写一个类的继承85.XMLHttpRequest:XMLHttpRequest.readyState;状态码的意思浏览器/html/css面试题1.什么是盒模型2.行内元素有哪些?块级元素有哪些? 空(void)元素有那些?行内元素和块级元素有什么区别?3.简述src和href的区别4.什么是css Hack5.什么叫优雅降级和渐进增强6.px和em的区别7.HTML5 为什么只写<!DOCTYPE HTML>8.Http的状态码有哪些9.一次完整的HTTP事务是怎么一个过程10.HTTPS是如何实现加密11.浏览器是如何渲染页面的12.浏览器的内核有哪些?分别有什么代表的浏览器13.页面导入时,使用link和@import有什么区别14.如何优化图像,图像格式的区别15.列举你了解Html5. Css3 新特性16.可以通过哪些方法优化css3 animation渲染17.列举几个前端性能方面的优化18.如何实现同一个浏览器多个标签页之间的通信19.浏览器的存储技术有哪些20.css定位方式21.尽可能多的写出浏览器兼容性问题22.垂直上下居中的方法23.响应式布局原理25.清除浮动的方法26.http协议和tcp协议27.刷新页面,js请求一般会有哪些地方有缓存处理28.如何对网站的文件和资源进行优化29.你对网页标准和W3C重要性的理解30.Http和https的区别31.data-属性的作用32.如何让Chrome浏览器显示小于12px的文字33.哪些操作会引起页面回流(Reflow)34.CSS预处理器的比较less sass35.如何实现页面每次打开时清除本页缓存36.什么是Virtual DOM,为何要用Virtual DOM37.伪元素和伪类的区别38.http的几种请求方法和区别39.前端需要注意哪些SEO40.<img>的title和alt有什么区别41.从浏览器地址栏输入url到显示页面的步骤42.如何进行网站性能优化43.语义化的理解44.HTML5的离线储存怎么使用,工作原理能不能解释一下?45.浏览器是怎么对HTML5的离线储存资源进行管理和加载的呢46.iframe有那些缺点?47.WEB标准以及W3C标准是什么?48.Doctype作用? 严格模式与混杂模式如何区分?它们有何意义?49.HTML全局属性(global attribute)有哪些50.Canvas和SVG有什么区别?51.如何在页面上实现一个圆形的可点击区域?52.网页验证码是干嘛的,是为了解决什么安全问题53.请描述一下 cookies,sessionStorage 和 localStorage 的区别?微信小程序开发(持续更新)初识小程序 1.注册小程序 2.微信开发者工具 3.小程序与普通网页开发的区别 4.小程序尺寸单位rpx 5.样式导入(WeUI for) 6.选择器 7.小程序image高度自适应及裁剪问题 8.微信小程序长按识别二维码 9.给页面加背景色 10.微信小程序获取用户信息 11.代码审核和发布 12.小程序微信认证 13.小程序申请微信支付 14.小程序的目录解构及四种文件类型 15.小程序文件的作用域 16.小程序常用组件 1.view 2.scroll-view 3.swiper组件 4.movable-view 5.cover-view 6.cover-image小程序基础 17.授权得到用户信息 18.数据绑定 19.列表渲染 20.条件渲染 21.公共模板建立 22.事件及事件绑定 23.引用 24.页面跳转 1.wx.switchTab 2.wx.reLaunch 3.wx.redirectTo 4.wx.navigateTo 5.wx.navigateBack 25.设置tabBar 26.页面生命周期 27.转发分享小程序高级 28.request请求后台接口 29.http-promise 封装 30.webview 31.获取用户收货地址 32.获取地里位置 33.自定义组件 34.微信小程序支付问题小程序项目实战 35.微信小程序本地数据缓存 36.下拉刷新和下拉加载 37.列表页向详情页跳转(动态修改title) 38.客服电话 39.星级评分组件 40.小程序插槽的使用slot 41.模糊查询 42.wxs过滤 43.小程序动画 44.列表根据索引值渲染 45.小程序动态修改class 46.小程序常用框架 47.参数传值的方法 48.提高小程序的应用速度 49.微信小程序的优劣势 50.小程序的双向绑定和vue的区别 51.微信小程序给按钮添加动画 52.微信小程序的tab按钮的转换 53.微信小程序引进echarts 54.APP打开小程序流程 55.小程序解析富文本编辑器 前端资源1.vue教学视频 01.Vue 电商 实战 02.Vue 实战 03.vue.js 音乐播放器实战 04.vue 新闻客户端实战 05. vue 实战 团购网 06.vue 实战 移动端音乐App 07. vue+Node.js+MongoDB全栈打造商城系统 08.Vue+Node+MongoDB高级全栈 09.vue.js 外卖实战 10.其他培训机构vue教学视频2.微信小程序开发视频 01. 2018最新小程序开发教程 02.Java仿抖音项目实战 03.mpvue小程序开发实战 04.微信小游戏入门开发与实战 05.最新豆瓣电影+贪吃蛇项目 06.服务器部署+SSL证书安装教程 07.后台讲解单独 08.小程序APi教程 09.零基础开始搭建微信小程序CMS后台教程 10.企业类小程序开发实战视频教程 11.微信小程序组价化开发视频教程 12.ThinkPHP5.0+小程序商城构建全栈应用 13.Vue.js后台接口微信小程序入门与项目实战教程 14.Node.js快速开发微信公众号视频教程3.Linux教学视频 ...

April 29, 2019 · 3 min · jiezi

前端开发中遇到的一些问题持续更新

页面两个div之间有一个小margin,样式怎么改都去不掉解决:html中div换行了,把两个div放到同一行可以解决,还有一种好办法就是使用flex。 app上点击有背景解决:全局添加样式-webkit-tap-highlight-color: rgba(255, 255, 255, 0); 手机端input边框阴影解决:添加-webkit-appearance: none; chrome模拟器里点击元素错位解决:我把百分比改成fit to window 好了,也可以来回切换几次机型。 git push 报错RPC failed; curl 55 SSLWrite() returned error -9805解决:一次性提交代码太多导致,使用git log找到最近一次commit的代码,git reset {id}回退到commit前的状态,再分批次提交。 代码丢失,git log找不到解决:git reset --hard xxx的记录,使用git reflog。 sudo nginx -s reload启动nginx报错:nginx: [error] open() "/usr/local/var/run/nginx.pid" failed (2: No such file or directory) 解决:sudo nginx -c /usr/local/etc/nginx/nginx.conf => sudo nginx -s reload input中type为number时maxlength失效解决:input type="tel" 微信授权callback有多个参数,出现丢失的情况。解决:因为授权接口中&的多个参数会变成整个接口地址的参数,所以需要对&进行加密,使用var callbackurl = encodeURIComponent(window.location.href)进行加密 滚动不顺畅解决:添加样式 -webkit-overflow-scrolling: touch;-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;事件冒泡解决: stopPropagation,cancelBubble(ie) 移入移出多次触发解决: mouseleave 对子元素不生效,不会冒泡 ...

April 29, 2019 · 2 min · jiezi

浏览器触发保存密码条件

触发浏览器保存密码条件input[password]submit提交https(Firefox)关闭密码填充设置autocomplete无效值,有效值见https://developer.mozilla.org...注:autocomplete="off"是无效的,原因好像是chrome觉的他们更懂用户体验 nwjs设置保存密码chrome.privacy.services.passwordSavingEnabled.set({ value:true });

April 28, 2019 · 1 min · jiezi

前端面试题总结jshtml小程序ReactES6Vue算法全栈热门视频资源

本文是关注微信小程序的开发和面试问题,由基础到困难循序渐进,适合面试和开发小程序。并总结React html css js 经典面试题 集各种算法和插件、前端视频源码资源于一身的文档,优化项目,在浏览器端的层面上提升速度,帮助初中级前端工程师快速搭建项目。 Vue面试题生命周期函数面试题 1.什么是 vue 生命周期 2.vue生命周期的作用是什么 3.第一次页面加载会触发哪几个钩子 4.简述每个周期具体适合哪些场景 5.created和mounted的区别 6.vue获取数据在哪个周期函数 7.请详细说下你对vue生命周期的理解?vue路由面试题 1.mvvm 框架是什么? 2.vue-router 是什么?它有哪些组件 3.active-class 是哪个组件的属性? 4.怎么定义 vue-router 的动态路由? 怎么获取传过来的值 5.vue-router 有哪几种导航钩子? 6.$route 和 $router 的区别 7.vue-router响应路由参数的变化 8.vue-router传参 9.vue-router的两种模式 10.vue-router实现路由懒加载( 动态加载路由 )vue常见面试题 1.vue优点 2.vue父组件向子组件传递数据? 3.子组件像父组件传递事件 4.v-show和v-if指令的共同点和不同点 5.如何让CSS只在当前组件中起作用 6.<keep-alive></keep-alive>的作用是什么? 7.如何获取dom 8.说出几种vue当中的指令和它的用法? 9. vue-loader是什么?使用它的用途有哪些? 10.为什么使用key 11.axios及安装 12.axios解决跨域 13.v-modal的使用 14.scss的安装以及使用 15. 请说出vue.cli项目中src目录每个文件夹和文件的用法? 16.分别简述computed和watch的使用场景 17.v-on可以监听多个方法吗 18.$nextTick的使用 19.vue组件中data为什么必须是一个函数 20.vue事件对象的使用 21 组件间的通信 22.渐进式框架的理解 23.Vue中双向数据绑定是如何实现的 24.单页面应用和多页面应用区别及优缺点 25.vue中过滤器有什么作用及详解 26.v-if和v-for的优先级 27.assets和static的区别 28.列举常用的指令 29.vue常用的修饰符 30.数组更新检测 31.Vue.set视图更新 32.自定义指令详解 33.vue的两个核心点 34.vue和jQuery的区别 35 引进组件的步骤 36.Vue-cli打包命令是什么?打包后悔导致路径问题,应该在哪里修改 37.三大框架的对比 38. 跨组件双向数据绑定 39.delete和Vue.delete删除数组的区别 40.SPA首屏加载慢如何解决 41.Vue-router跳转和location.href有什么区别 42. vue slot 43.你们vue项目是打包了一个js文件,一个css文件,还是有多个文件? 44.vue遇到的坑,如何解决的? 45.Vue里面router-link在电脑上有用,在安卓上没反应怎么解决? 46.Vue2中注册在router-link上事件无效解决方法 47.RouterLink在IE和Firefox中不起作用(路由不跳转)的问题 48.axios的特点有哪些 49.请说下封装 vue 组件的过程?vuex常见面试题 1.vuex是什么?怎么使用?哪种功能场景使用它? 2.vuex有哪几种属性 3.不使用Vuex会带来什么问题 4.Vue.js中ajax请求代码应该写在组件的methods中还是vuex的actions中? 5.vuex一个例子方法 6.Vuex中如何异步修改状态 7.Vuex中actions和mutations的区别参考答案:https://www.kancloud.cn/lemon-m/js-html-css/1039363 ...

April 28, 2019 · 1 min · jiezi

重学前端学习笔记五如何运用语义类标签来呈现Wiki网页

笔记说明重学前端是程劭非(winter)【前手机淘宝前端负责人】在极客时间开的一个专栏,每天10分钟,重构你的前端知识体系,笔者主要整理学习过程的一些要点笔记以及感悟,完整的可以加入winter的专栏学习【原文有winter的语音】,如有侵权请联系我,邮箱:kaimo313@foxmail.com。HTML语义:如何运用语义类标签来呈现Wiki网页?通过wiki网页案例来学习语义类标签HTML最初的设计场景就是“超文本”,早期HTML工作组的专家都是出版界书籍排版的专家。案例网址: https://en.wikipedia.org/wiki/World_Wide_Web 打不开上面这个网址的,(winter很贴心)提供了副本网址: http://static001.geekbang.org/static/time/quote/World_Wide_Web-Wikipedia.html 说明:本文图片由winter专栏提供,觉得不错的可以去订阅winter的专栏学习全文。1、aside 标记的这块区域属于aside内容主要就是起到导航作用。 2、article 标记的这块区域文章的主体部分可使用article,具有明确的独立性。 3、hgroup,h1,h2 标记的部分可以像下面这样解析: hgroup是标题组h1是一级标题:World Wide Webh2是二级标题:From Wikipedia, the free encyclopedia代码的话就类似这样: <hgroup><h1>World Wide Web </h1><h2>From Wikipedia, the free encyclopedia</h2></hgroup>4、abbr 说实话这个标签我没有见过,有点惭愧,我特意查了一下w3c的abbr标签的定义和用法: <abbr> 标签指示简称或缩写,比如 "WWW" 或 "NATO"。通过对缩写进行标记,您能够为浏览器、拼写检查和搜索引擎提供有用的信息。<abbr> 标签最初是在 HTML 4.0 中引入的,表示它所包含的文本是一个更长的单词或短语的缩写形式。浏览器支持情况: 所有浏览器都支持 <abbr> 标签注释:IE 6 或更早版本的 IE 浏览器不支持 <abbr> 标签。实列:标记一个缩写 The <abbr title="People's Republic of China">PRC</abbr> was founded in 1949.通过这些介绍,winter这里提的WWW就很好理解了: <abbr title="World Wide Web">WWW</abbr>.5、hr 你们一开始是不是觉得这里是不是用hr吗? 我一开始认为就是用hr,但被winter打脸了_(:3」∠)_. 答案是不用。 解释如下: winter: hr表示故事走向的转变和话题的转变,显然这里是两个标题,并没有这种关系,应该通过css的border来实现<hr>注意的几个点 修改颜色使用background-color属性hr标签是块级标签,有边框设置它自身的边框为0,然后在设置height。6、p 标记的部分有三个注记(note),它在文章中的作用就是额外的注释,但是html中并没有note相关的语义,这时可以使用p标签进行相关实现。 7、strong 如果上下文中某些词很重要我们可以用strong标签 ...

April 28, 2019 · 2 min · jiezi

使用vue完成微信公众号网页小记

前言:公司最近有一个H5页面的功能,比较简单的一个调查表功能,嵌套在我们微信公众号里面。选用的技术栈是Vue。同时用到了微信的登录和分享接口。ps:本人小白,如果有问题希望大家能指出来,写文章不止是为了记录,还是为了发现自己的问题。谢谢大噶!!! 主要功能以及遇到的问题:左右切换动画路由带参数跳转移动端引入外部字体样式使用htmtl2canvas截图功能使用微信接口(前端部分)移动端屏幕适配移动端点击一个页面点击多次只执行一次问题ios使用输入框的时键盘弹起来掩盖住按钮问题打包项目遇到静态资源加载问题1.左右切换动画--首先我考虑到用vue的移动端动画库,看了好久,但是项目非常小,就放弃了这个选择自己开始手写。首先我考虑到的是过渡效果。并且找到了相关的文章参考。代码如下: `<template> <div id="app"> <transition :name="'fade-'+(direction==='forward'?'last':'next')"> <router-view></router-view> </transition> </div></template><script>export default { name: "app", data: () => { return { direction: "" }; }, watch: { $route(to, from) { let toName = to.name; const toIndex = to.meta.index; const fromIndex = from.meta.index; this.direction = toIndex < fromIndex ? "forward" : ""; } }}</script><style scoped>.fade-last-enter-active { animation: bounce-in 0.6s;}.fade-next-enter-active { animation: bounce-out 0.6s;}@keyframes bounce-in { 0% { transform: translateX(-100%); } 100% { transform: translateX(0rem); }}@keyframes bounce-out { 0% { transform: translateX(100%); } 100% { transform: translateX(0rem); }}</style>`参考:https://yq.aliyun.com/article... ...

April 28, 2019 · 2 min · jiezi

续命之移动适配

最近看了好多移动适配的资料,整理了一下以作后续开发少出bug(哈哈~)移动端布局,为了适配各种大屏手机,目前最好用的方案莫过于使用相对单位rem。基于rem的原理,我们要做的就是: 针对不同手机屏幕尺寸和dpr动态的改变根节点html的font-size大小(基准值)。这里我们提取了一个公式(rem表示基准值)rem = document.documentElement.clientWidth * dpr / 10 如何转换成rem单位呢?公式如下:rem = px / 基准值; rem方案一首先,先说一个常识,浏览器的默认字体高都是16px。使用%单位方便使用css中的body中先全局声明font-size=62.5%,这里的%的算法和rem一样。因为100%=16px,1px=6.25%,所以10px=62.5%,这是的1rem=10px,所以12px=1.2rem。px与rem的转换通过10就可以得来,很方便了吧!使用方法注意,rem是只相对于根元素htm的font-size,即只需要设置根元素的font-size,其它元素使用rem单位设置成相应的百分比即可;例子: 一般情况下,是这样子使用的 移动端做适配的时候,可以使用这样的方法 方案二 js中rem是怎么用的首先得让文字和标签的大小随着屏幕的尺寸做变化 等比缩放,然后在把计算出的值赋给html 这样当前窗口的字体就能获取到了,然后我们再设置窗口大小改变的情况,其实也就是加一个窗口改变的监听事件onresize。发生了onresize,就重新计算该窗口下根目录字体的大小。 方案三 从dpr维度的适配上文也提到了dpr那么什么是dpr呢 通俗点讲就是花了200px的长宽来渲染CSS里面定义的100px的长宽而样式pixels和设备pixels的比值,就是dpr,即Device Pixel Ratio<!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><style> .box1{ height: 5rem; width: 5rem; background-color:red; }</style></head><body> <div class="box1"></div></body><script> var dpr = window.devicePixelRatio;//当前显示设备的物理像素分辨率与CSS像素分辨率的比值 var meta = document.createElement('meta'); // dpr meta.setAttribute('content', 'initial-scale=' + 1 / dpr + ', maximum-scale=' + 1 / dpr + ', minimum-scale=' + 1 / dpr + ', user-scalable=no'); document.getElementsByTagName('head')[0].appendChild(meta); ...

April 28, 2019 · 2 min · jiezi

HTML5废弃元素

了解HTML5废弃的元素对重构有所帮助,下面就是HTML5废弃的元素: 1. 表现性元素下面的元素被废弃的原因是用CSS处理可以更好地替代他们:1). basefont2). big3). center4). font5). strike6). tt2. 框架类元素下面的元素被废弃的原因是他们的使用破坏了可使用性和可访问性:1). frame2). frameset3). noframes※ **但要注意,html5支持iframe**3. 其他下面的元素被废弃的原因是不经常使用他们,也会引起混乱,而且其它元素也可以很好地实现他们的功能:1). acronym被废弃是因为它经常使页面错乱,可以使用abbr代替2). applet被废弃是因为可以使用object代替3). isindex被废弃是因为使用表单控件代替4). dir被废弃是因为使用ul代替4. html5废弃属性对应替代方案:https://html.spec.whatwg.org/multipage/obsolete.html#non-conforming-features 以下元素的视觉属性也被废弃,可用CSS来代替:

April 28, 2019 · 1 min · jiezi

前端跨域经验

接口跨域jsonpwindow.name + iframedomain(主域相同)cors跨域资源共享 CORS 详解重点: 1.简单请求&复杂请求;2.cookie 图片跨域canvas getImageData&toDataURL 也有跨域问题解决方法:cors a标签 download 跨域失效解决思路: 通过fetch或者xhr下载下来,转为blob,再createObjectURL注意:诺通过axios发请求下载文件出错,具体原因未查 const a = document.createElement('a'); const url = "http://*******.zip"; const filename = "文件名称"; const xhr = new XMLHttpRequest(); xhr.open('get', url); xhr.responseType = 'blob'; xhr.onreadystatechange = function () { if (xhr.readyState === 4 && xhr.status === 200) { const blob = new Blob([xhr.response]); a.href = URL.createObjectURL(blob); a.download = filename; a.click(); } }; xhr.send();

April 28, 2019 · 1 min · jiezi

为什么img标签是inline元素还可以设置宽高

之前刷面试题,看到一道题目 如题!?惊到了,以前写代码怎么没注意到这样的细节 ( ̄▽ ̄)"真是才疏学浅了。参考:可替换元素 - CSS:层叠样式表 | MDN 原来CSS中还有一个概念:可替换元素 MDN上是这么解释的: 在 CSS 中,可替换元素(replaced element)的展现效果不是由 CSS 来控制的。这些元素是一种外部对象,它们外观的渲染,是独立于 CSS 的。 简单来说,它们的内容不受当前文档的样式的影响。CSS 可以影响可替换元素的位置,但不会影响到可替换元素自身的内容。例如 <iframe> 元素,可能具有自己的样式表,但它们不会继承父文档的样式。典型的可替换元素有: <iframe><video><embed><img>有些元素仅在特定情况下被作为可替换元素处理,例如: <input>"image" 类型的 <input> 元素就像<img>一样可替换 <option><audio><canvas><object><applet>(已废弃)CSS的 content 属性用于在元素的  ::before 和 ::after 伪元素中插入内容。使用content 属性插入的内容都是匿名的可替换元素。 这些元素有一个共性,就是他们的内容都不是通过在标签内添加文本,而是通过某个属性(src、data(<object>)、label(<option>)或js控制(<canvas>))来显示内容的。可替换元素拥有内置宽高,他们可以设置width和height。他们的性质同设置了display:inline-block的元素一致。 ps:我在看别人的资料的时候,看到个误区,textarea、button等并不是可替换元素,他们是浏览器默认的内联块元素。 额外知识: 当需要给图片设定固定宽高,并需要不拉伸时(等类似情况),1)背景图,background-size配合background-position。(适用于装饰性图片)background-size: [ <length-percentage> | auto ]{1,2} | cover | contain;background-position: [ left | center | right | top | bottom | <length-percentage> ]{1,2}background-position值还可以是边偏移量:例:background-position: bottom 10px right 20px;2)img元素,object-fit配合object-position。(适用于内容图片)object-fit: fill | contain | cover | none | scale-down;object-position: 同background-position;object-position和background-position的区别在于默认值不同,object-position默认为50% 50%;background-position默认为0% 0%; ...

April 27, 2019 · 1 min · jiezi

阿里云前端技术周刊第二期

作者:@也树 校对:@染陌 素材:@也树、@英布《阿里云前端技术周刊》由阿里云智能商业中台体验技术团队整理编写。 知乎:阿里云中台前端/全栈团队专栏 Github:阿里云前端技术周刊 给我们投稿:传送门 参与交流:传送门 前端速报本周 Node.js 12 发布第一个 Current 版本,包括 V8 引擎升级、ES 新特性支持、启动及解析速度提升,以及诊断工具的优化升级等,官方原文介绍请看 Node.js 12 值得关注的新特性。著名 CSS 专家 Rachel Andrew 4 月份在加拿大 W3C交流会议 上关于 CSS 新功能的分享,包括 CSS-Grid-2、CSS Scroll Snap、Conic Gradients 等。演示文稿传送门本周 create-react-app 发布 3.0 版本,主要变化有升级 Jest,更好地支持 hooks、Typescript 以及浏览器兼容能力增强。完整 Changelog 编者推荐[useEffect 完整指南](https://overreacted.io/zh-han...React 团队核心成员 Dan Abramov 关于 useEffect API 的详细介绍与示例,有多个语言版本可供查看。 CSS layout cookbookMDN 为前端开发者总结的常用 CSS 布局方式,可以了解 CSS 新特性为我们的页面布局方式带来的改变。 趣前端quicklink预加载视窗内的链接对应下探页的静态资源,让你的页面切换如丝般顺滑。立即体验 VisBug通过这个 Chrome 插件,能让任意一个网页变成画板,肆意挥洒你的设计灵感吧! React95能够让你梦回 windows95 的 React 组件库。 ...

April 27, 2019 · 1 min · jiezi

JavaScript-到底是面向对象还是基于对象

与其它的语言相比,JavaScript 中的“对象”总是显得不是那么合群。一些新人在学习 JavaScript 面向对象时,往往也会有疑惑:为什么 JavaScript(直到 ES6)有对象的概念,但是却没有像其他的语言那样,有类的概念呢?为什么在 JavaScript 对象里可以自由添加属性,而其他的语言却不能呢? 甚至一些争论中,有人强调,JavaScript 并非“面向对象的语言”,而是“基于对象的语言”,这个说法一度流传甚广,而事实上,我至今遇到的持有这一说法的人中,无一能够回答“如何定义面向对象和基于对象”这个问题。如果大家如果在自学遇到困难,想找一个前端的学习环境,可以加入我们的前端学习圈,点击我加入吧,会节约很多时间,减少很多在学习中遇到的难题。 实际上,基于对象和面向对象两个形容词都出现在了 JavaScript 标准的各个版本当中。我们可以先看看 JavaScript 标准对基于对象的定义,这个定义的具体内容是:“语言和宿主的基础设施由对象来提供,并且 ECMAScript 程序即是一系列互相通讯的对象集合”。这里的意思根本不是表达弱化的面向对象的意思,反而是表达对象对于语言的重要性。 那么,在本篇文章中,我会尝试让你去理解面向对象和 JavaScript 中的面向对象究竟是什么。 JavaScript 到底是面向对象还是基于对象? 什么是对象? 我们先来说说什么是对象,因为翻译的原因,中文语境下我们很难理解“对象”的真正含义。事实上,Object(对象)在英文中,是一切事物的总称,这和面向对象编程的抽象思维有互通之处。中文的“对象”却没有这样的普适性,我们在学习编程的过程中,更多是把它当作一个专业名词来理解。 但不论如何,我们应该认识到,对象并不是计算机领域凭空造出来的概念,它是顺着人类思维模式产生的一种抽象(于是面向对象编程也被认为是:更接近人类思维模式的一种编程范式)。 那么,我们先来看看在人类思维模式下,对象究竟是什么。 JavaScript 到底是面向对象还是基于对象? 对象这一概念在人类的幼儿期形成,这远远早于我们编程逻辑中常用的值、过程等概念。在幼年期,我们总是先认识到某一个苹果能吃(这里的某一个苹果就是一个对象),继而认识到所有的苹果都可以吃(这里的所有苹果,就是一个类),再到后来我们才能意识到三个苹果和三个梨之间的联系,进而产生数字“3”(值)的概念。 在《面向对象分析与设计》这本书中,Grady Booch 替我们做了总结,他认为,从人类的认知角度来说,对象应该是下列事物之一: 一个可以触摸或者可以看见的东西;人的智力可以理解的东西;可以指导思考或行动(进行想象或施加动作)的东西。有了对象的自然定义后,我们就可以描述编程语言中的对象了。在不同的编程语言中,设计者也利用各种不同的语言特性来抽象描述对象,最为成功的流派是使用“类”的方式来描述对象,这诞生了诸如 C++、Java 等流行的编程语言。而 JavaScript 早年却选择了一个更为冷门的方式:原型。这是我在前面说它不合群的原因之一。 ipt 推出之时受管理层之命被要求模仿 Java,所以,JavaScript 创始人 Brendan Eich 在“原型运行时”的基础上引入了 new、this 等语言特性,使之“看起来更像 Java”。 在 ES6 出现之前,大量 JavaScript 程序员试图在原型体系的基础上,把 JavaScript 变得更像是基于类的编程,进而产生了很多所谓的“框架”,比如 PrototypeJS、Dojo。事实上,它们成为了某种 JavaScript 的古怪方言,甚至产生了一系列互不相容的社群,显然这样做的收益远远小于损失。 如果我们从运行时角度来谈论对象,就是在讨论 JavaScript 实际运行中的模型,这是由于任何代码执行都必定绕不开运行时的对象模型,不过,幸运的是,从运行时的角度看,可以不必受到这些“基于类的设施”的困扰,这是因为任何语言运行时类的概念都是被弱化的。 JavaScript 到底是面向对象还是基于对象? 首先我们来了解一下 JavaScript 是如何设计对象模型的。 JavaScript 对象的特征 ...

April 27, 2019 · 2 min · jiezi

前端面试题甄选持续更新

2019.04.23 已知如下代码,如何修改才能让图片宽度为 300px ?注意下面代码不可修改<img src="1.jpg" style="width:480px!important;”>解决方案: css3的缩放: transform(scale(0.625, 0.625));js: document.getElementsByTagName("img")[0].setAttribute("style","width:300px!important;")css: max-width: 300px; (这个我当时没想到...)css: box-sizing: border-box; padding-left: 90px; padding-right: 90px; (这个我当时也没想到...)2019.03.22 Promise 构造函数是同步执行还是异步执行,那么 then 方法呢?这个很明显,promise构造函数是同步执行的,then方法是异步执行的。我从回答中选了个稍微复杂点的例子: const promise = new Promise((resolve, reject) => { console.log(1); resolve(5); console.log(2);}).then(val => { console.log(val);});promise.then(() => { console.log(3);});console.log(4);setTimeout(function() { console.log(6);});//执行结果: 124536这里会牵涉一个宏任务(macrotask)和微任务(microtask)的执行顺序问题,进而牵出javascript的事件循环(EventLoop)。 上干货:这一次,彻底弄懂 JavaScript 执行机制,阮一峰 JavaScript 运行机制详解:再谈Event Loop不想看的也可以直接看这里:先执行一个宏任务(其实运行js的时候这个宏任务已经在运行),然后执行微任务,清空微任务队列,再执行宏任务,再执行微任务,清空微任务队列... 常见的任务类型: 微任务 microtask(jobs): promise / ajax / Object.observe(该方法已废弃)宏任务 macrotask(task): setTimout / script / IO / UI Rendering

April 27, 2019 · 1 min · jiezi

TypeScript-React-Redux和AntDesign的最佳实践

阿特伍德定律,指的是any application that can be written in JavaScript, will eventually be written in JavaScript,意即“任何可以用JavaScript来写的应用,最终都将用JavaScript来写”在使用新技术的时候,切忌要一步一步的来,如果当你尝试把两门不熟悉的新技术一起结合使用,你很大概率会被按在地上摩擦,会yarn/npm和React脚手架等技术是前提,后面我会继续写PWA深入和Node.js集群负载均衡Nginx,webpack原理解析等~谢谢思否官方对我上篇文章的加精~ 在使用TypeScript前,请你务必万分投入学习好以下内容再尝试:TypeScript必须知识点: javaScript,特别是阮一峰的ES6教程必须要多看几遍,看仔细了,否则你会被TS按在地上摩擦TypeScript文档,什么是TypeScript,一定要看得非常仔细,因为有可能开发时一个极小的问题是你不会的知识点,那么可能会耗费你大量的时间去解决前端性能优化不完全手册 , 这是本人的一篇文章,也应该看看。 哈哈哈~介绍完了配置,后面会有大量的总结~React直接看文档,React官方中文文档,我认为React的中文文档已经写得非常好了,学起来还是比较简单的~Redux,学习Redux之前,建议把官方文档看几遍,然后props context 自定义事件 pubsub-js这些组件传递数据的方式都用熟悉后再上Redux,因为Redux写法非常固定,只是在TS中无法使用修饰器而已,需要最原始的写法。后面的代码有注释,到时候可以看看。(HOOKS和HOC都可以尝试使用,因为React的未来可能大概率使用这些写法)Redux官方文档Ant-Design,目前React生态最好的UI组件库,百分90的使用率,移动端、PC端都支持,pro还可以开箱即用,强烈推荐,开启配置按需加载,后台TO-B项目用起来不要太舒服。Ant-Design官网~学技术切忌过分急躁,一步登天,什么都想学却什么都学不好。作者的心得,持之以恒的努力,把每个技术逐个击破,最后结合起来使用,如鱼得水,基础不牢,地动山摇,本文的代码会把所有配置和Redux,Ant-Design全部配好,开箱即用,其他的功能你看Ant-Design的文档往里面加就行了~正式开启:本文介绍如何配置,已经整体的业务流程如何搭建 GitHub源码地址 包管理器,使用yarn或者npm都可以,这里建议使用yarn,因为Ant-Design官方推荐yarn,它会自动添加依赖。使用官方的 create-react-app的另外一种版本 和 Create React App 一起使用 TypeScriptreact-scripts-ts 自动配置了一个 create-react-app 项目支持 TypeScript。你可以像这样使用:create-react-app my-app --scripts-version=react-scripts-ts, -前提你必须全局下载 create-react-app请注意它是一个第三方项目,而且不是 Create React App 的一部分。 需要的依赖:都在package.json文件中。这里请万分注意,TS的包大部分都是需要下两个,一个原生,一个@types/开头 { "name": "antd-demo-ts", "version": "0.1.0", "private": true, "dependencies": { "@types/jest": "24.0.11", "@types/node": "11.13.7", "@types/react": "16.8.14", "@types/react-dom": "16.8.4", "@types/react-redux": "^7.0.8", "@types/react-router-dom": "^4.3.2", "@types/redux-thunk": "^2.1.0", "babel-plugin-import": "^1.11.0", "customize-cra": "^0.2.12", "less": "^3.9.0", "less-loader": "^4.1.0", "prop-types": "^15.7.2", "react": "^16.8.6", "react-app-rewired": "^2.1.3", "react-dom": "^16.8.6", "react-redux": "^7.0.2", "react-router-dom": "^5.0.0", "react-scripts": "3.0.0", "redux-chunk": "^1.0.11", "redux-devtools-extension": "^2.13.8", "redux-thunk": "^2.3.0", "typescript": "3.4.5" }, "scripts": { "start": "react-app-rewired start", "build": "react-app-rewired build", "test": "react-app-rewired test" }, "eslintConfig": { "extends": "react-app" }, "browserslist": { "production": [ ">0.2%", "not dead", "not op_mini all" ], "development": [ "last 1 chrome version", "last 1 firefox version", "last 1 safari version" ] } * `Ant-Design`按需加载配置 `config-overrides.js`const { override, fixBabelImports, addLessLoader } = require('customize-cra');module.exports = override( fixBabelImports('import', { libraryName: 'antd', libraryDirectory: 'es', style: true, }), addLessLoader({ javascriptEnabled: true, modifyVars: { '@primary-color': '#1DA57A' }, })); ```tsconfig.json ,TS的配置文件 我基本上没怎么改动 ...

April 27, 2019 · 2 min · jiezi

重学前端学习笔记四div和span不是够用吗

笔记说明重学前端是程劭非(winter)【前手机淘宝前端负责人】在极客时间开的一个专栏,每天10分钟,重构你的前端知识体系,笔者主要整理学习过程的一些要点笔记以及感悟,完整的可以加入winter的专栏学习【原文有winter的语音】,如有侵权请联系我,邮箱:kaimo313@foxmail.com。HTML语义:div和span不是够用了吗?一、语义类标签是什么,使用它有什么好处?1、语义类标签语义类标签就是尽量使用有相对应的结构的含义的Html的标签2、好处对开发者友好,增加可读性,网页结构清晰,便于开发维护利用SEO,爬虫...3、使用语义标签的建议“用对”比“不用”好,“不用”比“用错”好。二、作为自然语言延伸的语义类标签作为自然语言和纯文本的补充,用来表达一定的结构或者消除歧义winter举了两个例子:html5中的ruby标签,em标签来进行说明比如em标签例子 把“今天我吃了一个苹果”这句话放到不同上下文中,表达的意思会不同 昨天我吃了一个香蕉。今天我吃了一个苹果。昨天我吃了两个苹果。今天我吃了一个苹果。是不是感觉不同,当没有上下文的时候,可以用em标签 今天我吃了一个 <em> 苹果 </em>。今天我吃了 <em> 一个 </em> 苹果。三、作为标题摘要的语义类标签语义化的 HTML 能够支持自动生成目录结构,HTML 标准中还专门规定了生成目录结构的算法例如:<h1>HTML 语义 </h1><p>balah balah balah balah</p><h2> 弱语义 </h2><p>balah balah</p><h2> 结构性元素 </h2><p>balah balah</p>......h1-h6是最基本的标题,它们表示了文章中不同层级的标题。避免副标题可以使用html5的hgroup标签<h1>JavaScript 对象 </h1><h2> 我们需要模拟类吗?</h2><p>balah balah</p>......生成标题结构如下 JavaScript 对象 我们需要模拟类吗?...<hgroup><h1>JavaScript 对象 </h1><h2> 我们需要模拟类吗?</h2></hgroup><p>balah balah</p>......生成标题结构如下 JavaScript 对象——我们需要模拟类吗? ...section标签的嵌套会使h1-h6下降一级<section> <h1>HTML 语义 </h1> <p>balah balah balah balah</p> <section> <h1> 弱语义 </h1> <p>balah balah</p> </section> <section> <h1> 结构性元素 </h1> <p>balah balah</p> </section>......</section>标题结构如下 HTML 语义 弱语义结构性元素......四、作为整体结构的语义类标签正确使用整体结构类的语义标签,可以让页面对机器更友好<body> <header> <nav> …… </nav> </header> <aside> <nav> …… </nav> </aside> <section> …… </section> <section> …… </section> <section> …… </section> <article> <header>……</header> <section>……</section> <section>……</section> <section>……</section> <footer>……</footer> </article> <footer> <address>……</address> </footer></body>个人总结HTML并不简单,它是典型的“入门容易,精通困难”的一部分知识,我在看这篇文章的时候,就发现自己有些东西是没有留意的,查漏补缺很重要,一步一步完善自己的知识架构。 ...

April 26, 2019 · 1 min · jiezi

前端拼音模糊搜索

前端实现拼音模糊搜索pinyin-match[https://github.com/xmflswood/...[1] const PinyinMatch = require('pinyin-match');let test = '123曾经沧海难为水除却巫山不是云' PinyinMatch.match(test, '23曾'); // [1, 3] PinyinMatch.match(test, 'cjc') // [3, 5] PinyinMatch.match(test, 'cengjingcanghai') // [3, 6] PinyinMatch.match(test, 'cengjingcangha') // [3, 6] PinyinMatch.match(test, 'engjingcanghai') // false PinyinMatch.match(test, 'zengjingcang') // [3, 5] PinyinMatch.match(test, 'sdjkelwqf') // false PinyinMatch.match(text, 'zengji ng cang') // [3, 5] PinyinMatch.match(text, 'zengji ng cangsdjfkl') // false PinyinMatch.match(' 我 爱你 中 国 ', 'nzg') // [6, 12] PinyinMatch.match(' 我 爱你 中 国 ', '爱你中') // [5, 8] ...

April 26, 2019 · 1 min · jiezi

响应式布局flex

响应式布局【flex】来源于 响应式方法汇总 了解了以上响应式布局,下面重点介绍一下 flex弹性布局 ,非常有用,但是有记忆障碍的我,为了下次还能顺利的记起来,还是总结一下吧,顺便把我看的几个博客内容和大家分享一下,写的非常详细,很好理解。 扩展1.查看css属性兼容性情况 https://caniuse.com/2.盒子模型 box-sizing content-box(标准盒子模型) width = content-width;解析:当盒子内容宽度固定时,设置盒子的padding和border,盒子模型宽高会变大,向外扩展,实际content内容不变(注意:margin始终在盒子外); border-box(IE盒子模型) width = content-width + padding +border;解析:当盒子内容宽度固定时,设置盒子的padding和border,盒子模型宽高不变,向内扩展,实际content内容变小(注意:margin始终在盒子外); 3. 样式兼容(postCss插件) vscode 自动添加 css 兼容代码插件flex弹性布局采用 Flex 布局的元素,称为 Flex 容器(flex container),简称”容器”。它的所有子元素称为 Flex 项目(flex item),简称”项目”。注意,设为 Flex 布局以后,子元素的float、clear和vertical-align属性将失效。 1.弹性容器 display:flex;2.容器属性 justify-content------------项目在主轴上的对齐方式( 水平或垂直由flex-direction决定 ) flex-start ( 默认 居左 )flex-end ( 居右 )center( 居中 )space-between( 两端对齐项目之间的间隔都相等 )space-around( 每个项目两侧的间隔相等 )align-items------------交叉轴上如何对齐( 水平或垂直由flex-direction决定 ) stretch( 默认 如果项目未设置高度或设为auto,将占满整个容器的高度 )flex-start ( 对齐起点 )flex-end ( 对齐终点 )center( 对齐中点 )baseline( 项目的第一行文字的基线对齐 )flex-direction------------决定主轴的方向 ...

April 26, 2019 · 1 min · jiezi

这一次彻底弄懂-JavaScript-执行机制

不论你是Javascript新手还是老鸟,不论是面试求职,还是日常开发工作,我们经常会遇到这样的情况:给定的几行代码,我们需要知道其输出内容和顺序。因为javascript是一门单线程语言,所以我们可以得出结论: javascript是按照语句出现的顺序执行的 最后,如果大家如果在自学遇到困难,想找一个前端的学习环境,可以加入我们的前端学习圈,点击我加入吧,会节约很多时间,减少很多在学习中遇到的难题。 看到这里读者要打人了:我难道不知道js是一行一行执行的?还用你说?稍安勿躁,正因为js是一行一行执行的,所以我们以为js都是这样的: let a = '1'; console.log(a); let b = '2'; console.log(b); 然而实际上js是这样的: setTimeout(function(){ console.log('定时器开始啦') }); new Promise(function(resolve){ console.log('马上执行for循环啦'); for(var i = 0; i < 10000; i++){ i == 99 && resolve(); } }).then(function(){ console.log('执行then函数啦') }); console.log('代码执行结束'); 依照js是按照语句出现的顺序执行这个理念,我自信的写下输出结果: //"定时器开始啦" //"马上执行for循环啦" //"执行then函数啦" //"代码执行结束"去chrome上验证下,结果完全不对,瞬间懵了,说好的一行一行执行的呢? 我们真的要彻底弄明白javascript的执行机制了。 1.关于javascriptjavascript是一门单线程语言,在的HTML5中提出了Web-Worker,但javascript是单线程这一核心仍未改变。所以一切javascript版的"多线程"都是用单线程模拟出来的,一切javascript多线程都是纸老虎! 2.javascript事件循环既然js是单线程,那就像只有一个窗口的银行,客户需要排队一个一个办理业务,同理js任务也要一个一个顺序执行。如果一个任务耗时过长,那么后一个任务也必须等着。那么问题来了,假如我们想浏览新闻,但是新闻包含的超清图片加载很慢,难道我们的网页要一直卡着直到图片完全显示出来?因此聪明的程序员将任务分为两类: 同步任务 异步任务 当我们打开网站时,网页的渲染过程就是一大堆同步任务,比如页面骨架和页面元素的渲染。而像加载图片音乐之类占用资源大耗时久的任务,就是异步任务。关于这部分有严格的文字定义,但本文的目的是用最小的学习成本彻底弄懂执行机制,所以我们用导图来说明: 这一次,彻底弄懂 JavaScript 执行机制 导图要表达的内容用文字来表述的话: 同步和异步任务分别进入不同的执行"场所",同步的进入主线程,异步的进入Event Table并注册函数。 当指定的事情完成时,Event Table会将这个函数移入Event Queue。 主线程内的任务执行完毕为空,会去Event Queue读取对应的函数,进入主线程执行。 上述过程会不断重复,也就是常说的Event Loop(事件循环)。 我们不禁要问了,那怎么知道主线程执行栈为空啊?js引擎存在monitoring process进程,会持续不断的检查主线程执行栈是否为空,一旦为空,就会去Event Queue那里检查是否有等待被调用的函数。 ...

April 26, 2019 · 2 min · jiezi

马蜂窝火车票系统服务化改造初探

交通方式是用户旅行前要考虑的核心要素之一。为了帮助用户更好地完成消费决策闭环,马蜂窝上线了大交通业务。现在,用户在马蜂窝也可以完成购买机票、火车票等操作。 与大多数业务系统相同,我们一样经历着从无到有,再到快速发展的过程。本文将以火车票业务系统为例,主要从技术的角度,和大家分享在一个新兴业务发展的不同阶段背后,系统建设与架构演变方面的一些经验。 第一阶段:从无到有在这个阶段,快速支撑起业务,填补业务空白是第一目标。基于这样的考虑,当时的火车票业务从模式上选择的是供应商代购;从技术的角度需要优先实现用户在马蜂窝 App 查询车次余票信息、购票、支付,以及取消、退票退款等核心功能的开发。 图1-核心功能与流程 技术架构综合考虑项目目标、时间、成本、人力等因素,当时网站服务架构我们选择的是 LNMP(Linux 系统下 Nginx+MySQL+PHP)。整个系统从物理层划分为访问层 ( App,H5,PC 运营后台),接入层 (Nginx),应用层 (PHP 程序),中间件层 (MQ,ElasticSearch),存储层 (MySQL,Redis)。 对外部系统依赖主要包括公司内部支付、对账、订单中心等二方系统,和外部供应商系统。 图 2-火车票系统 V1.0 技术架构 如图所示,对外展现功能主要分为两大块,一块是 C 端 App 和 H5,另外是运营后台。二者分别经过外网 Nginx 和内网 Nginx 统一打到 php train 应用上。程序内部主要有四个入口,分别是: 供其他二方系统调用的 facade 模块运营后台调用的 admin 模块处理 App 和 H5 请求的 train 核心模块处理外部供应商回调模块四个入口会依赖于下层 modules 模块实现各自功能。对外调用上分两种情况,一种是调用二方系统的 facade 模块满足其公司内部依赖;一种是调用外部供应商。基础设施上依赖于搜索、消息中间件、数据库、缓存等。 这是典型的单体架构模式,部署简单,分层结构清晰,容易快速实现,可以满足初期产品快速迭代的要求,而且建立在公司已经比较成熟的 PHP 技术基础之上,不必过多担心稳定性和可靠性的问题。 该架构支撑火车票业务发展了将近一年的时间,简单、易维护的架构为火车票业务的快速发展做出了很大的贡献。然而随着业务的推进,单体架构的缺陷逐渐暴露出来: 所有功能聚合在一起,代码修改和重构成本增大研发团队规模逐渐扩大,一个系统多人开发协作难度增加交付效率低,变动范围难以评估。在自动化测试机制不完善的情况下,易导致「修复越多,缺陷越多」的恶性循环伸缩性差,只能横向扩展,无法按模块垂直扩展可靠性差,一个 Bug 可能引起系统崩溃阻碍技术创新,升级困难,牵一发而动全身为了解决单体架构所带来的一系列问题,我们开始尝试向微服务架构演进,并将其作为后续系统建设的方向。 第二阶段:架构转变及服务化初探从 2018 年开始,整个大交通业务开始从 LNMP 架构向服务化演变。 架构转变——从单体应用到服务化「工欲善其事,必先利其器」,首先简单介绍一下大交通在实施服务化过程中积累的一些核心设施和组件。 ...

April 26, 2019 · 2 min · jiezi

面向对象编程和简单的设计模式1

先说说,设计模式:直接,简单,暴力。上代码: //单体模式var teacer={ name:'lewis', age:33, showName:function(){ return this.name }}teacer.showName();//原型模式//属性放在构造函数里,方法放在原型上function teacer(name,age){ this.name=name; this.age=age;};teacer.prototype.showName=function(){ return this.name;}var lewis=new teacer('lewis',17);lewis.showName();//伪类模式class teacer{ constructor(name,age){ this.name=name; this.age=age; } showName(){ return this.name; }}var lewis=new teacer('lewis',22);lewis.showName();

April 26, 2019 · 1 min · jiezi

IIFE跟闭包的理解

一言不合,翠花,上酸菜! //随便写个函数哈var arr=[];for(var i=0;i<3;i++){ arr[i]=function(){ return i; }}//你猜会怎么输出console.log(arr[0]());//3console.log(arr[1]());//3console.log(arr[3]());//3哦,这是为什么呢?奥,这个嘛,就是说的块级作用域问题下面开始回归正题:其实你这样写,结果也是一样: var arr=[];for(var i=0;i<3;i++){ //留空}console.log(i)//太暴力了,也是3!来看看IIFE跟闭包结合大法: var arr=[];for(var i=0;i<3;i++){ (function(i){ arr[i].function(i){ return i; } })(i);}console.log(arr[0]());//0console.log(arr[1]());//1console.log(arr[2]());//2其实,搞了半天,有个更吊炸天的技能,都没想告诉你,知道为什么那么多人喜欢ES6,因为真的非常666: var arr=[];for(let i=0;i<3;i++){ arr[i]=function(){ return i; }}//This is a Amazing world!console.log(arr[0]());//0console.log(arr[1]());//1console.log(arr[2]());//2var 要哭了,真的,怎么可以这样,卑鄙!下流!无耻!打码...

April 26, 2019 · 1 min · jiezi

WebGL-threejs学习笔记-法向量网格材质MeshNormalMaterial的介绍和创建360度全景天空盒的方法

WebGL学习----Three.js学习笔记(5)点击查看demo演示Demo地址:https://nsytsqdtn.github.io/d...简单网格材质 MeshNormalMaterialMeshNormalMaterial是一种不受渲染时使用的颜色影响的材质,它只与自己每一个面从内到外的法向量有关。法向量在webgl中用处十分广泛,光的反射,以及三维图形的纹理映射都与这个有关。从图中可以看到,网格的每一面渲染的颜色都是不一样的,如果我们想要在物体表面添加法向量,我们可以使用的THREE.ArrowHelper去表示每一个法向量,它的参数为 THREE.ArrowHelper(dir, origin, length, color, headLength, headWidth) **其中参数的意义为:dir:方向,默认是法向量origin:开始的坐标位置 length:辅助线的长度color:辅助线的颜色headLength:头部的长度headWidth:头部的宽度** 对于一个球体,要描述它每一个面的法向量,首先需要对它的每一个面进行遍历,取出这个面上的三个顶点(因为webgl的面都是三角形,所以是三个顶点),通过divideScalar(3)这个函数计算它的中心位置,我们就可以在这个中心位置点上,从内向外引出一个ArrowHelper,来模拟法向量。 for(let i=0;i<sphereGeometry.faces.length;i++){//在每一个面上面循环 let face = sphereGeometry.faces[i];//得到每个面的对象 let centroid = new THREE.Vector3(); //先创建一个vector3对象,要使用这个对象找到每个面的中心 centroid.add(sphereGeometry.vertices[face.a]); // 将这该面的三个顶点的索引传给sphereGeometry.vertices找到其顶点的坐标 //再添加进centroid centroid.add(sphereGeometry.vertices[face.b]); centroid.add(sphereGeometry.vertices[face.c]); centroid.divideScalar(3);//三角形的中心点坐标 let arrow = new THREE.ArrowHelper( face.normal,//face这个面的法向量 centroid, 2, 0xffcc55, 0.5, 0.5);//箭头辅助线,相当于把法向量用箭头表示出来 sphere.add(arrow); }其中,centroid.add(sphereGeometry.vertices[face.a])这段代码中的sphereGeometry.vertices存有几何体的所有顶点信息,通过[ ]索引可以取得其中的某一个顶点。face.a还有下面的face.b和c都是该面的顶点索引号,表示这个面是由顶点编号为face.a,face.b,face.c的三个顶点所构成的一个三角形(webgl的面都是三角形),然后我们再计算这三个顶点的中心点。 菜单面板的设置在菜单面板中设置一些MeshNormalmaterial的一些属性,便于去测试这种材质的一些特质其中:**this.visible = meshMaterial.visible;//是否可见 this.wireframe = meshMaterial.wireframe;//是否以线框的方式渲染物体 this.wireframeWidth = meshMaterial.wireframeLinewidth;//线框的宽度 this.transparent = meshMaterial.transparent;//是否透明 this.opacity = meshMaterial.opacity;//透明度,需要transparent为true才有效果 this.side = "front";//边的渲染方式,有三种,前面,后面,还有双面 this.selectMesh = "sphere";//当前选择的几何体 this.shading = "smooth";//着色方式,有平面着色和平滑着色,对一个面很平的几何体几乎看不出区别,如正方体** function initDatGUI() { //设置菜单中需要的参数 controls = new function () { this.rotationSpeed = 0.02; this.visible = meshMaterial.visible;//是否可见 this.wireframe = meshMaterial.wireframe;//是否以线框的方式渲染物体 this.wireframeWidth = meshMaterial.wireframeLinewidth;//线框的宽度 this.transparent = meshMaterial.transparent;//是否透明 this.opacity = meshMaterial.opacity;//透明度,需要transparent为true才有效果 this.side = "front";//边的渲染方式,有三种,前面,后面,还有双面 this.selectMesh = "sphere";//当前选择的几何体 this.shading = "smooth";//着色方式,有平面着色和平滑着色,对一个面很平的几何体几乎看不出区别,如正方体 }; let gui = new dat.GUI(); //将刚刚设置的参数添加到菜单中 let F1 = gui.addFolder("Mesh"); F1.add(controls, "rotationSpeed", 0, 0.1); F1.add(controls, "visible").onChange(function (e) { meshMaterial.visible = e; }); F1.add(controls, "wireframe").onChange(function (e) { meshMaterial.wireframe = e; }); F1.add(controls, "wireframeWidth",0,10).onChange(function (e) { meshMaterial.wireframeWidth = e; }); F1.add(controls, "transparent").onChange(function (e) { meshMaterial.transparent = e; }); F1.add(controls, "opacity",0,1).onChange(function (e) { meshMaterial.opacity = e; }); F1.add(controls, "side",["front","back","double"]).onChange(function (e) { switch (e) { case "front": meshMaterial.side = THREE.FrontSide; break; case "back": meshMaterial.side = THREE.BackSide; break; case "double": meshMaterial.side = THREE.DoubleSide; break; } meshMaterial.needsUpdate = true;//要在程序中让材质更新需要添加这一句话 }); F1.add(controls, "selectMesh",["sphere","cube","plane"]).onChange(function (e) { //先把场景的物体清除,再来添加 scene.remove(cube); scene.remove(sphere); scene.remove(plane); switch (e) { case "sphere": scene.add(sphere); break; case "cube": scene.add(cube); break; case "plane": scene.add(plane); break; } }); F1.add(controls, "shading",["flat","smooth"]).onChange(function (e) { switch (e) { case "flat": meshMaterial.shading = THREE.FlatShading; break; case "smooth": meshMaterial.shading = THREE.SmoothShading; break; } meshMaterial.needsUpdate = true;//要在程序中让材质更新需要添加这一句话 }); }**注意在程序运行过程中想要改变材质的属性,需要在改完以后,添加一句meshMaterial.needsUpdate = true,这样才能更新成功。** ...

April 26, 2019 · 4 min · jiezi

重学前端学习笔记三前端知识框架图

笔记说明重学前端是程劭非(winter)【前手机淘宝前端负责人】在极客时间开的一个专栏,每天10分钟,重构你的前端知识体系,笔者主要整理学习过程的一些要点笔记以及感悟,完整的可以加入winter的专栏学习【原文有winter的语音】,如有侵权请联系我,邮箱:kaimo313@foxmail.com。列一份前端知识框架图两个目标1、把无法通查阅解决的原理和背景讲清楚2、把不方便查阅和记忆的内容整理好前端知识划分本文所有知识架构图由winter专栏提供1、基础部分JavaScript知识架构 编程语言一般规律:用一定的词法和语法,表达一定语义,从而操作运行时 CSS和HTML知识架构 文档元信息:通常是出现在 head 标签中的元素,包含了描述文档自身的一些信息语义相关:扩展了纯文本,表达文章结构、不同语言要素的标签链接:提供到文档内和文档外的链接替换型标签:引入声音、图片、视频等外部元素替换自身的一类标签表单:用于填写和提交信息的一类标签表格:表头、表尾、单元格等表格的结构 浏览器的实现原理知识架构 2、实践部分前端工程实践 性能工具链持续集成搭建系统架构与基础库前端的知识框架 个人总结我上大学那一会,还没有专门开设前端课程,只有几本书简单讲解了JavaScript跟部分网页知识,前端也没有十分重视,也没有听过前端工程师这个职位,想必大家很多都一样,从事前端这份工作要不是自学过来的,要不就是培训过来的,当然也有很多大佬是从事其他语言开发过来的,如果觉得自己的前端知识架构不太完善的话,希望这篇能帮助到你

April 25, 2019 · 1 min · jiezi

关于-wkhtmltopdfhtml-转-pdf-的命令行工具

一、什么是 wkhtmltopdf?wkhtmltopdf 是一个开源的,使用Qt WebKit 渲染引擎,把 html 转换为 pdf 文件的命令行工具。wkhtmltopdf 还有一个双胞胎兄弟 wkhtmltoimage,顾名思义,它可以把 html 转换为 image 图片。 简单的讲,wkhtmltopdf 用于把网页转换成 pdf 文件。 详情可以参考:官网github地址 二、简单使用1. 下载下载对应操作系统的安装文件:下载地址 2. 使用安装成功后就可以通过命令来直接使用了,它的命令格式为 wkhtmltopdf [GLOBAL OPTION]... [OBJECT]... <output file>[GLOBAL OPTION] 是用来添加全局参数的区域,[OBJECT] 是用来添加 wkhtmltopdf 对象(wkhtmltopdf 把对象分为 3 类,后文有详细内容)的区域,如果有多个对象,则按顺序放入。<output file>则用以指定输出的 PDF 文件。 3. 示例使用默认参数,把 csdn 网页转为 pdf 的示例如下: ➜ ~ wkhtmltopdf https://www.csdn.net /Users/kevin/Desktop/csdn.pdfLoading pages (1/6)QFont::setPixelSize: Pixel size <= 0 (0) ] 61%Counting pages (2/6)Resolving links (4/6)Loading headers and footers (5/6)Printing pages (6/6)Done➜ ~三、对象和参数详解三类对象命令 wkhtmltopdf [GLOBAL OPTION]... [OBJECT]... <output file> 中,OBJECT 表示一个对象。在 wkhtmltopdf 中,wkhtmltopdf 可以把多个对象输出到文件中,其中每个对象可以是页面对象,封面对象和大纲对象。对象按照命令行中的顺序,输出到pdf的结果文件里。 ...

April 25, 2019 · 2 min · jiezi

四年前端狗面试被虐如何翻身

April 25, 2019 · 0 min · jiezi

移动端video局部播放视频

前一阵子写了一个移动端视频播放 但是发现不能局部播放,只能全屏播放,话不多说,贴代码 <video ref="myVideo" id="myVideo" preload="auto" style="width:100%;height:4.22rem;" :src="playItem.play.playUrl" controls webkit-displaying-fullscreen="false" x-webkit-airplay="true" x5-playsinline="true" webkit-playsinline="true" playsinline="true"></video>具体参考了苹果的开发文档

April 25, 2019 · 1 min · jiezi

flex布局中某个行内元素居右并垂直居中

首先父盒子设置成display: flex子元素(行内元素)设flex: 1和text-align: right<div class="flex-box"> <div>1</div> <div>2</div> <div>3</div> <span class="item-right">水平居右并垂直居中</span> </div>.flex-box { display: flex; flex-direction: row;}.flex-box div { width: 100px; height: 100px; background: #f9f9f9; margin-right: 10px;}.item-right { flex: 1; text-align: right; align-self: center;}完整的HTML如下: <!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> <style> .flex-box { display: flex; flex-direction: row; } .flex-box div { width: 100px; height: 100px; background: #f9f9f9; margin-right: 10px; } .item-right { flex: 1; text-align: right; align-self: center; } </style></head><body> <div class="flex-box"> <div>1</div> <div>2</div> <div>3</div> <span class="item-right">水平居右并垂直居中</span> </div></body></html>

April 25, 2019 · 1 min · jiezi

Vue-阻止事件冒泡和默认行为案例

话不多说,三句多。先上一段代码: <script> window.onload=function(){ let vm=new Vue({ el:"#div", data:{ }, methods:{ show(){ console.log(111); //原生写法: //js:show(e){console.log(111); e.stopPropagation();} //html:<button @click="show($event)"> }, print(){ console.log(222); }, write(){ console.log(333); }, study(){ console.log(444); //原生写法: //js:show(e){console.log(111); e.preventDefult();} } } }); }</script><body> <div id="div"> <!--事件冒泡--> <div @click="write"> <p @click="print"> <button @click.stop="show">click me</button> <!--+.stop直接完事,简单干脆--> </p> </div> <!--阻止默认行为--> <a href="#" @click.prevent="study"></a> <!--+.prevent直接完事,简单暴力,握草--> </div></body>感觉 Vue 就是神仙操作,简单直接暴力,关键也会记不住,真是一把鼻涕一把辛酸泪啊。

April 25, 2019 · 1 min · jiezi

如何从零开始-Web-前端学习之路

工具篇 工欲善其事,必先利其器,所以在开始之前选择一个合适好用的编辑器是很重要的,工具不再多,在于好用就行,除了编辑器,我们也要掌握其他的一些工具,才能够让我们在学习的道路上更加的顺畅。最后,如果大家如果在自学遇到困难,想找一个前端的学习环境,可以加入我们的前端学习圈,点击我加入吧,会节约很多时间,减少很多在学习中遇到的难题。 WebStorm不必多说,前端最强大的编辑器,特别是那无敌的智能提示,但是它的缺点在于如果项目多于大时,出现的卡顿让很多人苦恼。 WebStorm 官网下载地址:https://www.jetbrains.com/web...。WebStorm 有哪些过人之处?(https://www.zhihu.com/questio...)激活 WebStorm2018(https://blog.csdn.net/qq_3213...) Visual Studio Code微软开源免费产品,受到非常多技术人员的喜爱,基本上成为前端开发者的必备编辑器,强大的插件扩展,可以灵活的打造自己喜欢的风格。给你们送上常用插件列表拿走不谢。 Visual Studio Code 官网下载地址:https://code.visualstudio.com/。VSCode 拓展推荐:https://github.com/varHarrie/...使用顶级 VSCode 扩展来加快开发 JavaScript:https://www.html.cn/archives/...vscode 插件推荐:https://segmentfault.com/a/11... atom也是一款免费开源的编辑器,受到很多人的喜爱,但是我本人用的较少,所以插件方面就不推荐了,大家可以按照自己的爱好去寻找。 科学上网每个程序员都应该具备的工具和能力,否则很多事情都无法办到,至于怎么做,你可以自己查阅资料,这里不就不在多说了。而且下面推荐的很多资源都是需要科学上网之后才能访问,所以一定要学会。 Google在使用「Google」之前必须学会科学上网,不然无法访问,学会使用搜索可以帮助我们解决很多问题,一个人的知识是有限的,掌握了搜索的技巧才能以不变应万变,很多时候百度出来的东西重复性很大,最重要的是垃圾信息很多,在百度找不到的答案,在这里很容易找到,Google 是我的必备搜索。 Github全球最大的「同性」开源交流社区,没有账号的赶紧注册,在这有很多优秀的资源项目,各种大神。观摩优秀代码是我们学习的很好路径。另外在开发过程中,很多时候任务重、时间紧,应该避免重复造轮子,这里能够找到你需要的工具或代码。 Stack Overflow国外著名的技术问答交流社区,开发时碰到的很多问题在这里都能找到答案。 SegmentFault对应的国内版的技术问答交流社区,如果你英文不好,也可以在这里找找答案。 MarkdownMarkdown 轻量级标记语言,简洁的语法,让作者专注内容而非复杂的格式要求,我认为人人都应该掌握,特别是经常写博客的人。想想你在用 world 时的场景,每次写完文章之后,不得不话费很多时间进行格式的排版,使用它你就可以避免这些烦恼。 Markdown 中文文档:https://markdown-zh.readthedo...HTML 篇 一些准备就绪之后,开始我们的学习之旅,首先我们先从 HTML 开始。 HTML名为「超文本标记语言」,是整个页面的结构基础,它承载了我们的页面内容。 基础w3school 在线教程(http://www.w3school.com.cn/h.asp):内容非常的基础,适合小白学习,对 HTML 有一个入门了解。freeCodeCamp(https://www.freecodecamp.cn/):一个非常好的入门学习网站,采用闯关的模式,就像游戏打怪升级一样,非常的有乐趣,准备自学的小伙伴不妨试试。 进阶MDN HTML(https://developer.mozilla.org...):这里的内容质量更好,错误更少,内容也更加的全面。HTML 和 CSS 编码规范(https://codeguide.bootcss.com/):掌握一些代码技巧,写出更好,更高质量的代码。CSS 篇 HTML 承载了页面的内容,但是有时候会略显单调与「丑陋」,CSS 的作用就是为这些内容加上样式,就像一个美女也要有漂亮的外衣去修饰才会更加漂亮,「人靠衣装马靠鞍」,网页的内容也是需要穿上一件漂亮的外衣去吸引用户。而 CSS 则完成了这个装饰。 基础学习 CSS 布局(http://zh.learnlayout.com/):带你一步一步的完成 CSS 的学习。CSS 参考手册(https://css.doyoe.com/):对CSS可以有一个全面入门的学习。w3school CSS 参考手册(http://www.w3school.com.cn/cs...):同上也是非常基础的知识,适合入门。 进阶书籍: 《CSS揭秘》(https://book.douban.com/subje...):非常推荐的一本 CSS 书籍,可以学到很多鲜为人知的技巧。 在线系列: MDN CSS(https://developer.mozilla.org...):和 HTML 都是 MDN 社区文档,质量保障。HTML和CSS编码规范(https://codeguide.bootcss.com/):掌握一些代码技巧,写出更好,更高质量的代码。大漠老师的CSS系列(https://www.w3cplus.com/CSS3):大漠老师对CSS有非常深入的认识和丰富的实践经验,《图解CSS3:核心技术与案例实战》的作者。大漠老师的SASS系列(https://www.w3cplus.com/blog/...):大漠老师的 sass 文章系列。SASS中文网(https://www.sasscss.com/):成熟、稳定、强大的 CSS 扩展语言解析器,它可以让你使用变量,条件语句等书写 CSS。Stylus官网(https://stylus.bootcss.com/):同样是 CSS 预编译器,但它省去了一些符号,让 CSS 写起来更加的简洁,清爽。HTML5和CSS3(https://github.com/qianguyiha...):详解HTML5 和 CSS3。知识点: ...

April 25, 2019 · 2 min · jiezi

八问WebSocket协议为你快速解答WebSocket热门疑问

一、引言WebSocket是一种比较新的协议,它是伴随着html5规范而生的,虽然还比较年轻,但大多主流浏览器都已经支持。它使用方面、应用广泛,已经渗透到前后端开发的各种场景中。 对http一问一答中二式流程(就是从所周之的“长轮询”技要啦)的不满,催生了支持双向通信的WebSocket诞生。WebSocket是个不太干净协议。 本文将从8个常见的疑问入手,为还不了解WebSocket协议的开发者快速普及相关知识,从而节省您学习WebSocket的时间。 另外,如果您对Web端的即时通讯技术还完全不了解,那么《新手入门贴:详解Web端即时通讯技术的原理》、《Web端即时通讯技术盘点:短轮询、Comet、Websocket、SSE》这两篇文章请您务必抽时间读一读。 学习交流: 即时通讯/推送技术开发交流4群:101279154[推荐]移动端IM开发入门文章:《新手入门一篇就够:从零开发移动端IM》(本文同步发布于:http://www.52im.net/thread-24...) 二、参考文章《WebSocket详解(一):初步认识WebSocket技术》 《WebSocket详解(二):技术原理、代码演示和应用案例》 《WebSocket详解(三):深入WebSocket通信协议细节》 《WebSocket详解(四):刨根问底HTTP与WebSocket的关系(上篇)》 《WebSocket详解(五):刨根问底HTTP与WebSocket的关系(下篇)》 《WebSocket详解(六):刨根问底WebSocket与Socket的关系》 《理论联系实际:从零理解WebSocket的通信原理、协议格式、安全性》 三、更多资料Web端即时通讯新手入门贴: 《新手入门贴:详解Web端即时通讯技术的原理》 Web端即时通讯技术盘点请参见: 《Web端即时通讯技术盘点:短轮询、Comet、Websocket、SSE》 关于Ajax短轮询: 找这方面的资料没什么意义,除非忽悠客户,否则请考虑其它3种方案即可。 有关Comet技术的详细介绍请参见: 《Comet技术详解:基于HTTP长连接的Web端实时通信技术》 《WEB端即时通讯:HTTP长连接、长轮询(long polling)详解》 《WEB端即时通讯:不用WebSocket也一样能搞定消息的即时性》 《开源Comet服务器iComet:支持百万并发的Web端即时通讯方案》 更多WebSocket的详细介绍请参见: 《新手快速入门:WebSocket简明教程》 《Socket.IO介绍:支持WebSocket、用于WEB端的即时通讯的框架》 《socket.io和websocket 之间是什么关系?有什么区别?》 有关SSE的详细介绍文章请参见: 《SSE技术详解:一种全新的HTML5服务器推送事件技术》 更多WEB端即时通讯文章请见: http://www.52im.net/forum.php... 四、1问WebSocket:WebSocket协议只能浏览器发起么?不是。目前此协议的受众的也不仅仅是web开发者。 WebSocket只是一种协议,它和http协议一样,使用类似okhttp的组件,可以在任何地方进行调用,甚至可以借助WebSocket实现RPC框架。 五、2问WebSocket:WebSocket和HTTP什么关系?WebSocket和http一样,都是处于OSI模型中的最高层:应用层。 WebSocket借助http协议进行握手,握手成功后,就会变身为TCP通道,从此与http不再相见。 使用netstat或者ss,能够看到对应的连接,它与处于抽象层的socket,在外观上没有区别。 更多WebSocket和HTTP的关系,以及与Socket的区别,可进一步阅读以下文章: 《WebSocket详解(四):刨根问底HTTP与WebSocket的关系(上篇)》 《WebSocket详解(五):刨根问底HTTP与WebSocket的关系(下篇)》 《WebSocket详解(六):刨根问底WebSocket与Socket的关系》 六、3问WebSocket:WebSocket和长轮询有什么区别?长轮询,就是客户端发送一个请求,服务端将一直在这个连接上等待(当然有一个超长的超时时间),直到有数据才返回,它依然是一个一问一答的模式。比如著名的comted。 WebSocket在握手成功后,就是全双工的TCP通道,数据可以主动从服务端发送到客户端,处于链接两端的应用没有任何区别。 WebSocket创建的连接和Http的长连接是不一样的。由于Http长连接底层依然是Http协议,所以它还是一问一答,只是Hold住了一条命长点的连接而已。 长轮询和Http长连接是阻塞的I/O,但WebSocket可以是非阻塞的(具体是多路复用)。 这方面更深入的资料,请进一步学习: 《Comet技术详解:基于HTTP长连接的Web端实时通信技术》 《WEB端即时通讯:HTTP长连接、长轮询(long polling)详解》 七、4问WebSocket:如何创建一个WebSocket连接?WebSocket的连接创建是借助Http协议进行的。这样设计主要是考虑兼容性,在浏览器中就可以很方便的发起请求,看起来比较具有迷惑性。 下图是一个典型的由浏览器发起的ws请求,可以看到和http请求长的是非常相似的。 但是,它只是请求阶段长得像而已: 请求的地址,一般是:ws://***,或者是使用了SSL/TLS加密的安全协议wss:,用来标识是WebSocket请求。 1)首先,通过Http头里面的Upgrade域,请求进行协议转换。如果服务端支持的话,就可以切换到WebSocket协议。简单点讲:连接已经在那了,通过握手切换成ws协议,就是切换了连接的一个状态而已。 2)Connection域可以认为是与Upgrade域配对的头信息。像nginx等代理服务器,是要先处理Connection,然后再发起协议转换的。 3)Sec-WebSocket-Key 是随机的字符串,服务器端会用这些数据来构造出一个 SHA-1 的信息摘要。如此操作,可以尽量避免普通 HTTP 请求被误认为 WebSocket 协议。 其他的,像Sec-WebSocket*字样的头信息,表明了客户端支持的子协议以及其他信息。像loT中很流行的mqtt,就可以作为WebSocket的子协议。 ...

April 25, 2019 · 1 min · jiezi

✨如何用JS实现划词高亮的在线笔记功能✨????️

1. 什么是“划词高亮”?有些同学可能不太清楚“划词高亮”是指什么,下面就是一个典型的“划词高亮”: 上图的示例网站可以点击这里访问。用户选择一段文本(即划词),即会自动将这段选取的文本添加高亮背景,用户可以很方便地为网页添加在线笔记。 笔者前段时间为线上业务实现了一个与内容结构非耦合的文本高亮在线笔记功能。非耦合是指不需要为高亮功能建立特殊的页面 DOM 结构,而高亮功能对业务近乎透明。该功能核心部分具有较强的通用性与移植性,故拿出来和大家分享交流一下。 本文具体的核心代码已封装成独立库 web-highlighter,阅读中如有疑问可参考其中代码↓↓。2. 实现“划词高亮”需要解决哪些问题?实现一个“划词高亮”的在线笔记功能需要解决的核心问题有两个: 加高亮背景。即如何根据用户在网页上的选取,为相应的文本添加高亮背景;高亮区域的持久化与还原。即如何保存用户高亮信息,并在下次浏览时准确还原,否则下次打开页面用户高亮的信息就丢失了。一般来说,划词高亮的业务需求方主要是针对自己产出的内容,你可以比较容易对内容在网页上的排版、HTML 标签等方面进行控制。这种情况下,处理高亮需求会更方便一些,毕竟自己可以根据高亮需求调整现有内容的 HTML。 而笔者面对的情况是,页面 HTML 排版结构复杂,且无法根据高亮需求来推动业务改动 HTML。这也催生出了对解决方案更通用化的要求,目标就是:针对任意内容均可“划词高亮”并支持后续访问时还原高亮状态,而不用去关心内容的组织结构。 下面就来具体说说,如何解决上面的两个核心问题。 3. 如何“加高亮背景”?根据动图演示我们可以知道,用户选择某一段文本(下文称为“用户选区”)后,我们会给这段文本加一个高亮背景。 例如用户选择了上图中的文本(即蓝色部分)。为其加高亮的基本思路如下: 获取选中的文本节点:通过用户选择的区域信息,获取所有被选中的所有文本节点;为文本节点添加背景色:给这些文本节点包裹一层新的元素,该元素具有指定的背景颜色。3.1. 如何获取选中的文本节点?1)Selection API需要基于浏览器为我们提供的 Selection API 。它的兼容性还不错。如果要支持更低版本的浏览器则需要用 polyfill。 Selection API 可以返回一系列关于用户选区的信息。那么是不是可以通过它直接获取选取中的所有 DOM 元素呢? 很遗憾并不能。但好在它可以返回选区的首尾节点信息: const range = window.getSelection().getRangeAt(0);const start = { node: range.startContainer, offset: range.startOffset};const end = { node: range.endContainer, offset: range.endOffset};Range 对象包含了选区的开始与结束信息,其中包括节点(node)与文本偏移量(offset)。节点信息不用多说,这里解释一下 offset 是指什么:例如,标签<p>这是一段文本的示例</p>,用户选取的部分是“一段文本”这四个字,这时首尾的 node 均为 p 元素内的文本节点(Text Node),而 startOffset 和 endOffset 分别为 2 和 6。 ...

April 25, 2019 · 4 min · jiezi

重学前端学习笔记一

笔记说明重学前端是程劭非(winter)【前手机淘宝前端负责人】在极客时间开的一个专栏,每天10分钟,重构你的前端知识体系,笔者主要整理学习过程的一些要点笔记以及感悟,完整的可以加入winter的专栏学习【原文有winter的语音】,如有侵权请联系我,邮箱:kaimo313@foxmail.com。前端发展史:从青铜时代-->黄金时代青铜时代据winter回忆,06年的时候接触前端时,网页的主要交互都还是依靠切换超链接来完成那时候谷歌刚刚基于ajax发布的gmail也没多久,ajax的出现标志着web1.0(静态网页)到web2.0(动态网页)的迈进,但国内很少人懂白银时代winter在08年毕业后在微软北京负责window CE上的IE浏览器的开发两年后加入盛大做电子书,负责电子书的文本排版工作盛大后期加入webOS项目,负责前端框架最直观的的表现之一:前端慢慢的从后端分离出来,代码也变得复杂,需要保存数据,处理数据,生成视图等,工程化的思想也逐渐萌芽。黄金时代盛大离职后,winter加入阿里做手机淘宝开发随着移动互联网的到来,前端开启了'黄金时代',形成前端的工程体系,诸如持续集成,前后端分离,线上监控...架构方面:从简单的解决兼容和风格问题-->组件化UI架构模式,形成了新一代的三大前端框架Angular, React, Vue前端开发之痛:散点学习 + 基础不牢个人感受:前端知识点很杂,多,框架更新太快,需要个人投入的时间学习比较多,并且对于前端的知识体系和底层原理没有真正的系统地理解成长的两个视角1、立足标准系统性的总结和整理前端知识,建立自己的认知和方法论 2、放眼团队从业务和工程角度思考前端团队的价值和发展需要 前端知识体系四个模块javaScriptcss和html浏览器实践前端综合应用重学前端初衷提供一些视角,以完备、体系化的方式理解和思考前端的基础知识和工程实践 个人总结重学前端这个专栏我是一开篇就跟着winter学习过来的,但是最近很多东西又开始遗忘,我正好也准备写一点东西,就打算把学习的一些要点梳理一下,养成一个自己不喜欢的习惯很不容易,比如整理笔记,希望刻意的练习能帮助你我。

April 24, 2019 · 1 min · jiezi

如何理解语义semantic化

前端工程师的招聘中,经常有这样的要求:对Web 语义化有深刻理解。那么到底什么才是深刻理解Web语义化呢?读完这篇博客你就知道了。 前端工程师们口里的web语义化,实际上是指HTML5标签的语义化。但是这并不完全正确,在W3C标准,有semantic web的详细介绍,我将结合W3C标准的介绍和其他资料,深入理解web语义化,而不仅仅停留在标签层面。那么HTML的语义化就不重要了吗?显然不是,medium上有一篇很好的博客。 语义学与计算机科学的关系是什么?semantic web是什么?通过TypeScript理解为什么Semantic HTML很重要?除了增强可读性,Semantic HTML还有哪些方面很重要?HTML语义化标签参考手册进一步增强Web语义化的WAI-ARIA语义学与计算机科学的关系是什么以下内容摘自维基百科: 一个逻辑系统通常由三个部分组成,即词汇部分、句法部分和基于模型论的语义部分。所谓的词汇部分就是列举出一个形式系统所使用的所有符号,句法部分是这些符号的组合规则,规定什么样的符号序列可以是这个系统的句子,语义部分是对合格句子的解释,这样的解释通常是:在一个模型中进行的对真值条件推导。逻辑学的语义学着眼点在于逻辑系统的语义解释,是一个理想化的模型系统,不直接涉及自然语言。互联网理论中讨论的Web 2.0的一个很重要的特征就是语义网络,其目的是以语义为纲领组织网络资源。semantic web是什么?除了经典的"Web of documents" W3C也致力于构建一个技术栈去支持"Web of data",也就是数据库中你的数据的顺序。Web of data的终极目的在于:让计算机做更多的有用的工作去开发系统,从而通过网络去支持可以信赖的交互。W3C术语"Semantic Web"指的是对Web链接的数据。语义Web技术使人们可以在Web上创建数据仓库,建立词汇表,为需要处理的数据写规则。Linked data 由类似RDF,SPARQL,OWL和SKOS。 Linked DataSemantic Web是建立在数据上的Web,包括日期,标题和部分数字以及机制属性以及任何其他的可以想象到的数据。RDF提供了发布和链接数据的基础。多种技术允许你在文档中嵌入数据(RDFa,GRDDL)或者暴露SQL数据库里的数据,或者通过RDF文件嵌入。 Vocabulary有时候组织数据更重要更有价值。使用OWL(构建词汇或者本体)以及SKOS(设计知识组织系统),通过附属的意义enrich数据,这就可以允许更多的人或者更多的机器基于数据做更多的事。 Query查询语言与数据库息息相关。如果Semantic Web被当做一个全局的数据库,那么理解为什么需要一门语言用来查询数据就很轻松了。SPARQL就是Semantic Web的查询语言。 Inference在Semantic Web栈顶,可以找到引用--通过规则推理数据。W3C基于规则工作,主要通过RIF和OWL,集中精力在不同系统之间的规则语言和交换规则。 Vertical ApplicationW3C工作在不同的产业,例如在医疗健康和生命科学,电子政务,提升合作能力的能力,研究和开发,以及通过语义化的Web创新革新的技术改革。例如,通过帮助临床研究中的决策,语义Web技术将跨机构桥接多种形式的生物和医学信息。 通过TypeScript理解为什么Semantic HTML很重要?原文链接:Understanding why Semantic HTML is important, as told by TypeScript. 为了控制时间成本,我将只记录自己认为重要的知识点,而不是通篇翻译了。 当今有一种宣扬JavaScript,贬低HTML的趋势,这是不正确的!TypeScript引入了类型,确保我们debug,写,读的时候更加高效。HTML若是同样按照TypeScript这样,严格按照类型码标签,会更加严格。写一个标题,很多标签都可以实现,但是选择header可以更加准确的代表我们的元素,也可以让代码可读性更好。充分利用好HTML这们语言,而不是到处都是div。将HTML当做一门语言,选择最最合适的代码去表现自己的内容。语义化好的web与语义化不好的web间的对比:语义化好的TS和HTML: interface dog { name: string age: number isFluffy: boolean} 语义化不好的TS和HTML: interface dog { name: any age: any isFluffy: any} “…to build for people and the long term, then simple, structural, semantic HTML was best — each element deployed for it’s intended purpose. Don’t use a div when you mean a p” — Jeffery ZeldmanGet to know the HTML elements available to you, and use the appropriate one for your content. Make the most it, like you would any language you choose to code with. ...

April 24, 2019 · 2 min · jiezi

ES6入门之正则的扩展

1. 正则的扩展参数为字符串, 那么第二个参数表示正则表达式的修饰符,如下:var regex = new RegExp('xyz', 'i') // 等价于var regex = /xyz/i参数为一个正则表达式,这时返回一个原有正则表达式的拷贝。如下:var regex = new RegExp(/xyz/i)// 等价于var regex = /xyz/iEs6中改变了这种行文。如果RegExp构造函数第一个参数是正则对象,那第二个参数可以指定修饰符,并且返回的正则表达式会忽略原有正则表达式的修饰符,只使用新指定的修饰符。 如下:new RegExp(/abc/ig, 'i').flags// 原有的ig 被 i 覆盖2. 字符串的正则方法字符串对象共有4个方法,可以使用正则表达式: match()、 replace()、search() 和 split()。在Es6中 全部调用RegExp的实例方法,全部定义在RegExp对象上。如下:String.prototype.match 调用 RegExp.prototype[Symbol.match]String.prototype.replace 调用 RegExp.prototype[Symbol.replace]String.prototype.search 调用 RegExp.prototype[Symbol.search]String.prototype.split 调用 RegExp.prototype[Symbol.split3. u 修饰符ES6 对正则表达式添加了 u 修饰符,用来正确处理大于uFFFF的Unicode字符。如下:/^\uD83D/u.test('\uD83D\uDC2A') // false/^\uD83D/.test('\uD83D\uDC2A') // true// 如上代码因为在ES5中 不支持四个字节的 UTF-16编码,会将为识别为两个字符 导致 第二行为true但是加了 u 修饰符后,ES6将为识别为一个字符,所以第一行为flase4. RegExp.prototype.unicode 属性正则实例对象新增 unicode 属性,用来判断表示是否设置了u修饰符,如下:const r1 = /hello/;const r2 = /hello/u;r1.unicode // falser2.unicode // true5. y 修饰符和 g 修饰符相似,全局匹配,但是下次匹配都是从上次匹配成功的下一个位置开始。而g 只要剩余位置中存在匹配即可,y 必须从剩余的第一个位置开始。如下:var s = 'aaa_aa_a';var r1 = /a+/g;var r2 = /a+/y;r1.exec(s) // ["aaa"]r2.exec(s) // ["aaa"]r1.exec(s) // ["aa"]r2.exec(s) // null// 第一次执行后 为 _aa_a g 只要剩余位置存在即可匹配,返回 aa// y 则是从上一次结果后的第一个位置开始,因为是_ 所以返回null6. RegExp.prototype.sticky 属性与y修饰符相匹配,ES6 的正则实例对象多了sticky属性,表示是否设置了y修饰符 如下:var r = /hello\d/y;r.sticky // true7. RegExp.prototype.flags 属性ES6 为正则表达式新增了flags属性,会返回正则表达式的修饰符。// ES5 的 source 属性// 返回正则表达式的正文/abc/ig.source// "abc"// ES6 的 flags 属性// 返回正则表达式的修饰符/abc/ig.flags// 'gi'8. s 修饰符:dotAll 模式匹配的是任意单个字符,用来匹配任意单个字符,如下:/foo.bar/s.test('foo\nbar') // true9. Unicode 属性类ES2018 引入了一种新的类的写法p{...}和P{...},允许正则表达式匹配符合 Unicode 某种属性的所有字符。const regexGreekSymbol = /\p{Script=Greek}/u;regexGreekSymbol.test('') // true10. 具名组匹配正常多个匹配 可能用圆括号包起,如下:const RE_DATE = /(\d{4})-(\d{2})-(\d{2})/;const matchObj = RE_DATE.exec('1999-12-31');const year = matchObj[1]; // 1999const month = matchObj[2]; // 12const day = matchObj[3]; // 31但是以上的写法不容易看懂,理解较为困难,而且只能用数字序号,另外如果数组顺序变了,还需要修改引用的序号。所以就有了具名组匹配。允许为每一个组匹配指定一个名字,既便于阅读代码,又便于引用。即使组的顺序变了,叶不用去更改匹配后的处理代码。如下: ...

April 23, 2019 · 2 min · jiezi

挖财-有赞电话面试-题目分享

动画相关//html<div class="btn"> <div class="change"></div></div>//css .btn { width: 100px; height: 20px; background: coral; border: 1px solid #5e6d82; } .change { width: 0; height: 20px; background: #2D93CA; transition: all 2s; } .btn:hover .change { width: 100px; }参考:https://codepen.io/JulianLava... 案例可能会变,主要考察 transition / animation 动画相关的知识点 浏览器内核相关trident / IE浏览器 gecko / firefox浏览器 webkit 内核 / safari & Chorome 差异:渲染机制不同 参考:https://juejin.im/entry/5a05a... 搜索引擎找了一波,分享内容不多,特别是针对差异的文章。。。 JS语言特性1、 解释型语言 - 不需要编译,直接解释运行 2、弱类型 - 对变量没有严格数据类型要求 3、跨平台 - 只要有js解释器 支持,能在任何地方运行 4、 基于对象 - 不仅能创建对象,也能基于对象创建对象 (原型链) ...

April 23, 2019 · 2 min · jiezi

前端必懂之Sticky-Footer粘性页脚

写在最前:Sticky Footer是css的一种布局场景。页脚footer永远固定在页面的底部,页面内容不够长的时候页脚黏在视窗底部,内容足够长时会被向下移动。老式门户网站由于内容过短常常版权页脚前移,移动端特定布局也需要Sticky Footer来解决这些问题。 一、利用绝对定位和padding完美兼容已知底部高度,利用绝对定位和padding完美兼容https://codepen.io/qietuniu/pen/KYxMwv 去除标签多余的margin,padding,给html和body设置100%外部容器min-height为100%,使得内容少时也能撑开主体内容设置padding-bottom,这个为底部的高度,可以使内容完全显示否则会使主体内容有底部面积大小区域被遮挡footer高度固定,进行绝对定位DOM节点 <div class="container"> <div class="header"></div> <div class="section"> </div> <div class="footer">Copyright© 1994-2019 切图妞</div></div>样式代码 html,body { height: 100%;}.container { position: relative; min-height: 100%; height: auto !important; height: 100%; /*IE6不识别min-height*/}.section { padding-bottom: 60px;}.footer { position: absolute; width: 100%; height: 60px; bottom: 0px;}二、利用padding-bottom和margin-top完美兼容已知底部高度,利用padding-bottom和margin-top完美兼容https://codepen.io/qietuniu/pen/dLqpdR 去除标签多余的margin,padding,给html和body设置100%;外部容器min-height为100%,使得内容少时也能撑开主体内容设置padding-bottom,这个为底部的高度footer高度固定,margin-top的值为高度负值DOM节点 <div class="container"> <div class="header"></div> <div class="section"> </div> <div class="footer">Copyright© 1994-2019 切图妞</div></div>样式代码 html,body { height: 100%;}.container { min-height: 100%; height: auto !important; height: 100%; /*IE6不识别min-height*/}.section { padding-bottom: 60px;}.footer { position: relative; margin-top: -60px; width: 100%; height: 60px;}三、新增块级元素填补页脚遮挡已知底部高度,新增块级元素填补页脚遮挡,实现完美兼容https://codepen.io/qietuniu/pen/dLqpez ...

April 23, 2019 · 1 min · jiezi

前端的性能优化针对内容方面

性能优化减少Http请求:1.尽量减少HTTP请求数 80%的终端用户响应时间都花在了前端上,其中大部分时间都在下载页面上的各种组件:图片,样式表,脚本,Flash等等。减少组件数必然能够减少页面提交的HTTP请求数。这是让页面更快的关键。 2.减少页面组件数的一种方式是简化页面设计。但有没有一种方法可以在构建复杂的页面同时加快响应时间呢?嗯,确实有鱼和熊掌兼得的办法。 3.合并文件是通过把所有脚本放在一个文件中的方式来减少请求数的,当然,也可以合并所有的CSS。如果各个页面的脚本和样式不一样的话,合并文件就是一项比较麻烦的工作了,但把这个作为站点发布过程的一部分确实可以提高响应时间。 4.CSS Sprites是减少图片请求数量的首选方式。把背景图片都整合到一张图片中,然后用CSS的background-image和background-position属性来定位要显示的部分。 5.图像映射可以把多张图片合并成单张图片,总大小是一样的,但减少了请求数并加速了页面加载。图片映射只有在图像在页面中连续的时候才有用,比如导航条。给image map设置坐标的过程既无聊又容易出错,用image map来做导航也不容易,所以不推荐用这种方式。 6.行内图片(Base64编码)用data: URL模式来把图片嵌入页面。这样会增加HTML文件的大小,把行内图片放在(缓存的)样式表中是个好办法,而且成功避免了页面变“重”。但目前主流浏览器并不能很好地支持行内图片。 7.减少页面的HTTP请求数是个起点,这是提升站点首次访问速度的重要指导原则。 减少DNS查找:1.域名系统建立了主机名和IP地址间的映射,就像电话簿上人名和号码的映射一样。当你在浏览器输入www.yahoo.com的时候,浏览器就会联系DNS解析器返回服务器的IP地址。DNS是有成本的,它需要20到120毫秒去查找给定主机名的IP地址。在DNS查找完成之前,浏览器无法从主机名下载任何东西。 2.DNS查找被缓存起来更高效,由用户的ISP(网络服务提供商)或者本地网络存在一个特殊的缓存服务器上,但还可以缓存在个人用户的计算机上。DNS信息被保存在操作系统的DNS cache(微软Windows上的”DNS客户端服务”)里。大多数浏览器有独立于操作系统的自己的cache。只要浏览器在自己的cache里还保留着这条记录,它就不会向操作系统查询DNS。 3.IE默认缓存DNS查找30分钟,写在DnsCacheTimeout注册表设置中。Firefox缓存1分钟,可以用network.dnsCacheExpiration配置项设置。(Fasterfox把缓存时间改成了1小时 P.S. Fasterfox是FF的一个提速插件) 4.如果客户端的DNS cache是空的(包括浏览器的和操作系统的),DNS查找数等于页面上不同的主机名数,包括页面URL,图片,脚本文件,样式表,Flash对象等等组件中的主机名,减少不同的主机名就可以减少DNS查找。 5.减少不同主机名的数量同时也减少了页面能够并行下载的组件数量,避免DNS查找削减了响应时间,而减少并行下载数量却增加了响应时间。我的原则是把组件分散在2到4个主机名下,这是同时减少DNS查找和允许高并发下载的折中方案。 避免重定向 重定向用301和302状态码,下面是一个有301状态码的HTTP头:1.HTTP/1.1 301 Moved Permanently Location: http://example.com/newuri Content-Type: text/html 浏览器会自动跳转到Location域指明的URL。重定向需要的所有信息都在HTTP头部,而响应体一般是空的。其实额外的HTTP头,比如Expires和Cache-Control也表示重定向。除此之外还有别的跳转方式:refresh元标签和JavaScript,但如果你必须得做重定向,最好用标准的3xxHTTP状态码,主要是为了让返回按钮能正常使用。 2.牢记重定向会拖慢用户体验,在用户和HTML文档之间插入重定向会延迟页面上的所有东西,页面无法渲染,组件也无法开始下载,直到HTML文档被送达浏览器。 3.有一种常见的极其浪费资源的重定向,而且web开发人员一般都意识不到这一点,就是URL尾部缺少一个斜线的时候。例如,跳转到http://astrology.yahoo.com/as...://astrology.yahoo.com/astrology/的301响应(注意添在尾部的斜线)。在Apache中可以用Alias,mod_rewrite或者DirectorySlash指令来取消不必要的重定向。 4.重定向最常见的用途是把旧站点连接到新的站点,还可以连接同一站点的不同部分,针对用户的不同情况(浏览器类型,用户帐号类型等等)做一些处理。用重定向来连接两个网站是最简单的,只需要少量的额外代码。虽然在这些时候使用重定向减少了开发人员的开发复杂度,但降低了用户体验。一种替代方案是用Alias和mod_rewrite,前提是两个代码路径都在相同的服务器上。如果是因为域名变化而使用了重定向,就可以创建一条CNAME(创建一个指向另一个域名的DNS记录作为别名)结合Alias或者mod_rewrite指令。 让Ajax可缓存:1.Ajax的一个好处是可以给用户提供即时反馈,因为它能够从后台服务器异步请求信息。然而,用了Ajax就无法保证用户在等待异步JavaScript和XML响应返回期间不会非常无聊。在很多应用程序中,用户能够一直等待取决于如何使用Ajax。例如,在基于web的电子邮件客户端中,用户为了寻找符合他们搜索标准的邮件消息,将会保持对Ajax请求返回结果的关注。重要的是,要记得“异步”并不意味着“即时”。 2.要提高性能,优化这些Ajax响应至关重要。最重要的提高Ajax性能的方法就是让响应变得可缓存,就像在添上Expires或者Cache-Control HTTP头中讨论的一样。下面适用于Ajax的其它规则: 3.Gzip组件 减少DNS查找 压缩JavaScript 避免重定向 配置ETags 我们一起看看例子,一个Web 2.0的电子邮件客户端用了Ajax来下载用户的通讯录,以便实现自动完成功能。如果用户从上一次使用之后再没有修改过她的通讯录,而且Ajax响应是可缓存的,有尚未过期的Expires或者Cache-Control HTTP头,那么之前的通讯录就可以从缓存中读出。必须通知浏览器,应该继续使用之前缓存的通讯录响应,还是去请求一个新的。可以通过给通讯录的Ajax URL里添加一个表明用户通讯录最后修改时间的时间戳来实现,例如&t=1190241612。如果通讯录从上一次下载之后再没有被修改过,时间戳不变,通讯录就将从浏览器缓存中直接读出,从而避免一次额外的HTTP往返消耗。如果用户已经修改了通讯录,时间戳也可以确保新的URL不会匹配缓存的响应,浏览器将请求新的通讯录条目。 4.即使Ajax响应是动态创建的,而且可能只适用于单用户,它们也可以被缓存,而这样会让你的Web 2.0应用更快。 延迟加载组件:可以凑近看看页面并问自己:什么才是一开始渲染页面所必须的?其余内容都可以等会儿。1.JavaScript是分隔onload事件之前和之后的一个理想选择。例如,如果有JavaScript代码和支持拖放以及动画的库,这些都可以先等会儿,因为拖放元素是在页面最初渲染之后的。其它可以延迟加载的部分包括隐藏内容(在某个交互动作之后才出现的内容)和折叠的图片。 2.工具可帮你减轻工作量:YUI Image Loader可以延迟加载折叠的图片,还有YUI Get utility是一种引入JS和CSS的简单方法。Yahoo!主页就是一个例子,可以打开Firebug的网络面板仔细看看。 3.最好让性能目标符合其它web开发最佳实践,比如“渐进增强”。如果客户端支持JavaScript,可以提高用户体验,但必须确保页面在不支持JavaScript时也能正常工作。所以,在确定页面运行正常之后,可以用一些延迟加载脚本增强它,以支持一些拖放和动画之类的华丽效果。 预加载组件:预加载可能看起来和延迟加载是相反的,但它其实有不同的目标。通过预加载组件可以充分利用浏览器空闲的时间来请求将来会用到的组件(图片,样式和脚本)。用户访问下一页的时候,大部分组件都已经在缓存里了,所以在用户看来页面会加载得更快。实际应用中有以下几种预加载的类型: 1.无条件预加载——尽快开始加载,获取一些额外的组件。google.com就是一个sprite图片预加载的好例子,这个sprite图片并不是google.com主页需要的,而是搜索结果页面上的内容。 条件性预加载——根据用户操作猜测用户将要跳转到哪里并据此预加载。在search.yahoo.com的输入框里键入内容后,可以看到那些额外组件是怎样请求加载的。 提前预加载——在推出新设计之前预加载。经常在重新设计之后会听到:“这个新网站不错,但比以前更慢了”,一部分原因是用户访问先前的页面都是有旧缓存的,但新的却是一种空缓存状态下的体验。可以通过在将要推出新设计之前预加载一些组件来减轻这种负面影响,老站可以利用浏览器空闲的时间来请求那些新站需要的图片和脚本。 减少DOM元素的数量:一个复杂的页面意味着要下载更多的字节,而且用JavaScript访问DOM也会更慢。举个例子,想要添加一个事件处理器的时候,循环遍历页面上的500个DOM元素和5000个DOM元素是有区别的。1.大量的DOM元素是一种征兆——页面上有些内容无关的标记需要清理。正在用嵌套表格来布局吗?还是为了修复布局问题而添了一堆的<div>s?或许应该用更好的语义化标记。 2.YUI CSS utilities对布局有很大帮助:grids.css针对整体布局,fonts.css和reset.css可以用来去除浏览器的默认格式。这是个开始清理和思考标记的好机会,例如只在语义上有意义的时候使用<div>,而不是因为它能够渲染一个新行。 3.DOM元素的数量很容易测试,只需要在Firebug的控制台里输入: document.getElementsByTagName(‘*’).length 4.那么多少DOM元素才算是太多呢?可以参考其它类似的标记良好的页面,例如Yahoo!主页是一个相当繁忙的页面,但只有不到700个元素(HTML标签)。 ...

April 23, 2019 · 1 min · jiezi

小白学习web前端需要学习什么又该从何开始请看本文附教程

web前端开发的学习方法 在国内大学课程里面,几乎没有前端开发这门课程,无非就是一些网页设计之类的课程,但那些课程无论是老师讲还是学生听,都是敷衍了事,这个我深有体会,我相信大家一定也有同感!所以,目前前端开发主要是通过自学,和参加正规的培训最后,如果大家如果在自学遇到困难,想找一个前端的学习环境,可以加入我们的前端学习圈,点击我加入吧,会节约很多时间,减少很多在学习中遇到的难题。 然而更多的小伙伴喜欢自学,但是自学是很困难的,毕竟是一个人自己摸索,网上看上去有很多视频可以学习,但是那些视频很多都是过时的,像js和h5这些想要自学根本学不会,更何况以后深入学习还要掌握框架构造!很多小伙伴就根本找不到学习的方向,最后白白浪费了自己的时间和精力! Web前端的学习路线 第一阶段——HTML的学习 超文本标记语言(HyperText Mark-up Language 简称HTML)是一个网页的骨架,无论是静态网页还是动态网页,最终返回到浏览器端的都是HTML代码,浏览器将HTML代码解释渲染后呈现给用户。因此,我们必须掌握HTML的基本结构和常用标记及属性。 HTML的学习是一个记忆和理解的过程,在学习过程中可以借助Dreamweaver的“拆分”视图辅助学习。在“设计”视图中看效果,在“代码”视图中学本质,将各种视图的优势发挥到极致,这种对照学习的方法弥补了单纯识记HTML标签和属性的枯燥乏味,想必对各位初学的小盆友们来说必定是极好的! 在学习了HTML之后,我们只是掌握了各种“原材料”的制作方法,要想盖一幢楼房就还需要把这些“原材料”按照我们设计的方案组合布局在一起并进行一些样式的美化。第二个阶段——CSS的学习 CSS是英文Cascading Style Sheets的缩写,叫做层叠样式表,是能够真正做到网页表现与内容分离的一种样式设计语言。相对于传统HTML的表现而言其样式是可以复用的,这样就极大地提高了我们开发的速度,降低了维护的成本。 同时CSS中的盒子模型、相对布局、绝对布局等能够实现对网页中各对象的位置排版进行像素级的精确控制。通过此阶段的学习,我们就可以顺利完成“一幢楼房”的建设。 “楼房”建设完成之后,我们可以交给用户使用,但是如果想让用户获得更佳的体验,我们还可以对“楼房”进行更深一步的“装修”,让它看起来更“豪华”一些。 第三个阶段——JavaScript的学习 JavaScript是一种在客户端广泛使用的脚步语言,在JavaScript当中为我们提供了一些内置函数、对象和DOM操作,借助这些内容我们可以来实现一些客户端的特效、验证、交互等,使我们的页面看起来不那么呆板,屌丝瞬间逆袭高富帅!有么有? 此时,也许你还沉浸在JavaScript给你带来的惊喜之中,但你的项目经理却突然对你大吼道 “这个效果在××浏览器下不兼容,重新搞……” “不兼容?”瞬间石化了有木有? “我擦,坑爹啊!那可是花了我一个晚上写了几百行代码搞定的啊,吐血了都!” JavaScript的兼容性和复杂性有时候的确让我们头疼,还好有“大神”帮我们做了封装。 第四个阶段——jQUery的学习 jQuery是一个免费、开源的轻量级的JavaScript库,并且兼容各种浏览器(jQuery2.0及后续版本放弃了对IE6/7/8浏览器的支持),同时现在有很多基于jQuery的插件可供选择,这样在我们实现一些丰富的动态效果时更方便快捷,大大节省了我们开发的时间,提高了开发速度,这也充分体现了其write less,do more的核心宗旨。这个Feel倍儿爽!有么有? “豪华大楼”至此拔地而起,但是每天这样日复一日,年复一年的盖楼,好繁琐!能不能将大楼里面每一个单独部件模块化,当需要盖楼时就像堆积木一样组合在一起,这样岂不是爽歪歪?可以实现吗?答案是肯定的。 这种思想在Web前端开发中也是适合的,于是乎就出现了各种前端框架,在这里推荐给大家的是Bootstrap。 Bootstrap是Twitter推出的一个开源的用于前端开发的工具包,是一个CSS/HTML框架,并且支持响应式布局。一经推出后颇受欢迎,一直是GitHub上的热门开源项目。 在项目开发过程中,我们可以借助Bootstrap提供的CSS样式、组件、JavaScript插件等快速的完成页面布局和样式设置,然后再有针对性的微调样式,这样基于框架进行开发大大缩短了开发周期。站在巨人的肩膀上就是爽! Web前端的学习建议 小白学习web前端,需要学习什么?又该从何开始?请看本文附教程给大家聊聊在学习Web前端中的一些建议和方法。 在CSS布局时需要注意的一个问题是很多同学缺乏对页面布局进行整体分析,不能够从宏观上对页面中盒子间的嵌套关系进行把握,就急于动手去做,导致页面中各元素间的关系很混乱,容易出现盒子在浮动时错位等情况。建议大家在布局时采用“自顶向下,逐步细化”的思想,先用几个盒子将页面从整体上划分,然后逐步在盒子中继续嵌套盒子。 君子生非异也,善假于物也”,在学习的过程中还要多浏览一些优秀的网站,善于分析借鉴其设计思路和布局方法,见多方能识广,进而才可以融会贯通,取他人之长为我所用。 同时还要善于使用Firebug这个利器。Firebug一方面可以在我们学习过程中帮助我们调试自己的页面,另一方面我们可以使用Firebug方便地查看、分析别人网站的源代码,“偷”也是一种技能! 随着移动互联网热潮的到来,移动开发越来越受到大家的追捧,响应式布局、微网站等需求量不断增加,也是我们Web前端未来的发展方向之一,学有余力的同学可以多多关注。最后祝愿大家能在Web前端开发道路上走出一片更宽更广的天地!

April 23, 2019 · 1 min · jiezi

可能这些是你想要的H5软键盘兼容方案

前言最近一段时间在做 H5 聊天项目,踩过其中一大坑:输入框获取焦点,软键盘弹起,要求输入框吸附(或顶)在输入法框上。需求很明确,看似很简单,其实不然。从实验过一些机型上看,发现主要存在以下问题: 在 Android 和 IOS 上,获知软键盘弹起和收起状态存在差异,且页面 webview 表现不同。在IOS12 上,微信版本 v6.7.4 及以上,输入框获取焦点,键盘弹起,页面(webview)整体往上滚动,当键盘收起后,不回到原位,导致键盘原来所在位置是空白的。在 IOS 上,使用第三方输入法,高度计算存在偏差,导致在有些输入法弹起,将输入框挡住一部分。在有些浏览器上使用一些操作技巧,还是存在输入框被输入法遮挡。下面就上述发现的问题,逐个探索一下解决方案。 获知软键盘弹起和收起状态获知软键盘的弹起还是收起状态很重要,后面的兼容处理都要以此为前提。然而,H5 并没有直接监听软键盘的原生事件,只能通过软键盘弹起或收起,引发页面其他方面的表现间接监听,曲线救国。并且,在 IOS 和 Android 上的表现不尽相同。 IOS 软键盘弹起表现在 IOS 上,输入框(input、textarea 或 富文本)获取焦点,键盘弹起,页面(webview)并没有被压缩,或者说高度(height)没有改变,只是页面(webview)整体往上滚了,且最大滚动高度(scrollTop)为软键盘高度。 Android 软键盘弹起表现同样,在 Android 上,输入框获取焦点,键盘弹起,但是页面(webview)高度会发生改变,一般来说,高度为可视区高度(原高度减去软键盘高度),除了因为页面内容被撑开可以产生滚动,webview 本身不能滚动。 IOS 软键盘收起表现触发软键盘上的“收起”按钮键盘或者输入框以外的页面区域时,输入框失去焦点,软键盘收起。 Android 软键盘收起表现触发输入框以外的区域时,输入框失去焦点,软键盘收起。但是,触发键盘上的收起按钮键盘时,输入框并不会失去焦点,同样软键盘收起。 监听软键盘弹起和收起综合上面键盘弹起和收起在 IOS 和 Android 上的不同表现,我们可以分开进行如下处理来监听软键盘的弹起和收起: 在 IOS 上,监听输入框的 focus 事件来获知软键盘弹起,监听输入框的 blur 事件获知软键盘收起。在 Android 上,监听 webview 高度会变化,高度变小获知软键盘弹起,否则软键盘收起。// 判断设备类型var judgeDeviceType = function () { var ua = window.navigator.userAgent.toLocaleLowerCase(); var isIOS = /iphone|ipad|ipod/.test(ua); var isAndroid = /android/.test(ua); return { isIOS: isIOS, isAndroid: isAndroid }}()// 监听输入框的软键盘弹起和收起事件function listenKeybord($input) { if (judgeDeviceType.isIOS) { // IOS 键盘弹起:IOS 和 Android 输入框获取焦点键盘弹起 $input.addEventListener('focus', function () { console.log('IOS 键盘弹起啦!'); // IOS 键盘弹起后操作 }, false) // IOS 键盘收起:IOS 点击输入框以外区域或点击收起按钮,输入框都会失去焦点,键盘会收起, $input.addEventListener('blur', () => { console.log('IOS 键盘收起啦!'); // IOS 键盘收起后操作 }) } // Andriod 键盘收起:Andriod 键盘弹起或收起页面高度会发生变化,以此为依据获知键盘收起 if (judgeDeviceType.isAndroid) { var originHeight = document.documentElement.clientHeight || document.body.clientHeight; window.addEventListener('resize', function () { var resizeHeight = document.documentElement.clientHeight || document.body.clientHeight; if (originHeight < resizeHeight) { console.log('Android 键盘收起啦!'); // Android 键盘收起后操作 } else { console.log('Android 键盘弹起啦!'); // Android 键盘弹起后操作 } originHeight = resizeHeight; }, false) }}var $inputs = document.querySelectorAll('.input');for (var i = 0; i < $inputs.length; i++) { listenKeybord($inputs[i]);}弹起软键盘始终让输入框滚动到可视区有时我们会做一个输入表单,有很多输入项,输入框获取焦点,弹起软键盘。当输入框位于页面下部位置时,在 IOS 上,会将 webview 整体往上滚一段距离,使得该获取焦点的输入框自动处于可视区,而在 Android 则不会这样,它只会改变页面高度,而不会去滚动到当前焦点元素到可视区。由于上面已经实现监听 IOS 和 Android 键盘弹起和收起,在这里,只需在 Android 键盘弹起后,将焦点元素滚动(scrollIntoView())到可视区。查看效果,可以戳这里。 ...

April 23, 2019 · 3 min · jiezi

D2-日报-2019年4月23日

???? 新闻➡️ 疑似B站后端源码流出 juejin.im???? 开源项目➡️ gridsome/gridsome 非中文 watch 112 star 2835 fork 130 基于 Vue 的静态站点生成器,从 headless CMS、本地文件、API 构建支持 CDN 的站点 github.com➡️ nathancahill/split 非中文 watch 91 star 3903 fork 299 帮助实现可调整大小的分屏。基于 CSS,JS 只用于拖曳时重新计算 CSSy样式 github.com➡️ transloadit/uppy 非中文 watch 290 star 16380 fork 766 模块化的 JavaScript 文件上传器,可以和任何应用无缝集成 github.com➡️ Dawninest/jikeCalendar-macOS watch 2 star 46 fork 0 即刻黄历屏幕保护程序 github.com➡️ hzwer/LearningToPaint 非中文 watch 8 star 182 fork 17 绘画 AI github.com???? 分享➡️ Vue 的小奇技(第十三篇):在 Nuxt.js 中重定向 404 页面 juejin.im➡️ Web调试技术详解 juejin.im➡️ 前端时光机(神技) juejin.im???? 网站➡️ 秘迹搜索 一个不追踪你的搜索引擎,不会根据搜索关键词追踪用户,也不会通过历史搜索内容做广告推荐,它也没有在你的浏览器上种任何Cookie mijisou.com➡️ toolzl在线工具-让生活变得更有效率! 聚合了超过 150 个实用工具的在线工具资料箱 www.toolzl.com➡️ 非书资料管理系统 各类书籍光盘素材下载网站 202.38.93.29➡️ iData-知识检索 代替知网 www.cn-ki.net➡️ 小熊免费文件格式在线转换工具 免费在线转换Office文档,音视频文件,图像等各种文件格式 www.ofoct.com???? 工具➡️ ZhiMap 在线思维导图、电脑与手机微信里都能作图 zhimap.com☕️ 更优雅地阅读移至官网阅读我们精心排版之后的页面 《D2 日报 2019年4月23日》 ...

April 23, 2019 · 1 min · jiezi

dailyquestion02前端每日一题02

在这里记录着每天自己遇到的一道印象深刻的前端问题,以及一道生活中随处可见的小问题。 强迫自己形成积累的习惯,鞭挞自己不断前行,共同学习。 Github 地址 2019/04/15 - 2019/04/211. 写一个乱序函数 ?遍历数组元素,然后将当前元素与以后随机位置的元素进行交换。 function shuffle(a) { for (let i = a.length; i; i--) { let j = Math.floor(Math.random() * i); // es6语法 [a[i - 1], a[j]] = [a[j], a[i - 1]]; } return a; }2. 什么是惰性函数?惰性函数就是返回一个重写函数。For example: var foo = function() { var t = new Date(); foo = function() { return t; }; return foo(); }; foo();3. 静态作用域与动态作用域 ?静态作用域 —— 函数的作用域基于函数创建的位置。 ...

April 23, 2019 · 4 min · jiezi

txLive模块(直播类)试用分享

txLive 模块封装了腾讯云直播服务 https://docs.apicloud.com/Cli...经过试用,这个模块堪称最简单最快速能使用起来的直播模块。界面上的按钮,根据自己的需要,可以显示和隐藏。带有各种美颜功能(美白、瘦脸、V形脸)。推流的码率和清晰度可以设置。 使用流程: 注册腾讯云平台进行实名认证开通直播服务生成推流地址(https://cloud.tencent.com/doc...) 推流界面截图: <!DOCTYPE html><html><head> <meta charset="utf-8"> <meta name="viewport" content="maximum-scale=1.0,minimum-scale=1.0,user-scalable=0,width=device-width,initial-scale=1.0" /> <title>title</title> <link rel="stylesheet" type="text/css" href="../css/api.css" /> <style> body { padding-top: 160px; height: 1000px; } .content { margin-top: 350px; } button { margin: 10px; } </style></head><body> <div class="content"> <button tapmode type="button" onclick="openPusher()" name="button">openPusher</button> <button tapmode type="button" onclick="openPlayer()" name="button">openPlayer</button> <button tapmode type="button" onclick="setLiveBtnsVisibility()" name="button">setLiveBtnsVisibility</button> </div></body><script type="text/javascript" src="../script/api.js"></script><script type="text/javascript"> apiready = function() { }; function openPusher() { var txLive = api.require('txLive'); txLive.openPusher({ x: 0, y: 50, h: 350, w: api.winWidth, fixedOn: api.frameName, fixed: false, url: "" //填写腾讯云平台上生成的推流地址 }); }//播放接口,播放端使用 function openPlayer() { var txLive = api.require('txLive'); txLive.openPlayer({ x: 0, y: 0, url: "" //填写腾讯云平台上生成的播放地址 }); } function setLiveBtnsVisibility() { var txLive = api.require('txLive'); txLive.setLiveBtnsVisibility({ "btnid": "btnLog", "show": 0 }); }</script></html>复制代码 ...

April 22, 2019 · 1 min · jiezi

Vue render函数实战--实现tabs选项卡组件

用过Element ui库的童鞋肯定知道<el-tabs>组件,简单、好用、可以自定义标签页,不知道广大童鞋们在刚开始使用<el-tabs>组件的时候有没有想过它是如何实现的?我咋刚开始使用<el-tabs>组件的时候就有去想过,也想去实现一个超级简单的tabs选项卡组件,无奈当时功力不够,未能实现。最近的一个简单项目中正好要用到选项卡组件,由于项目简单也就没有使用任何第三方库,于是就自己动手写了个选项卡组件。1、实现tabs选项卡组件的思考<el-tabs v-model="activeName" @tab-click="handleClick"> <el-tab-pane label="用户管理" name="first">用户管理</el-tab-pane> <el-tab-pane label="配置管理" name="second">配置管理</el-tab-pane> <el-tab-pane label="角色管理" name="third">角色管理</el-tab-pane> <el-tab-pane label="定时任务补偿" name="fourth">定时任务补偿</el-tab-pane></el-tabs>问题: 如何根据<el-tab-pane>来生成标签页?如何过滤<el-tabs>组件中的子元素,使得在使用的时候只显示<el-tab-pane>,而不会显示其他组件或div之类的元素?2、实现思路想根据<el-tab-pane>来生成标签页就需要使用到<slot>,使用<slot>用<template>的形式肯定是不行的,因为无法获取到<slot>的数量;使用<template>的形式行不通,那就只有使用render函数了过滤<el-tabs>组件中的子元素也需要使用render函数3、代码实现 index.js import PTabs from './PTabs';import PTabPane from './PTabPane';export default function tabsInstall(Vue) { if(tabsInstall.installed){ return; } Vue.component('PTabs', PTabs); Vue.component('PTabPane', PTabPane);}PTabs.vue <script> import PTabNav from './PTabNav'; export default { name: "PTabs", props: { value: { type: [String, Number], default: '' }, beforeClick: { type: Function, default(){ return function () {}; } } }, components: { PTabNav }, data(){ return { pTabPanes: [], currentName: this.value || 0 } }, methods: { addPane(pane){ this.pTabPanes.push(pane); if(!this.currentName){ this.setCurrentName(this.pTabPanes[0].name); } }, removePane(pane){ let index = this.pTabPanes.indexOf(pane); if(index > -1){ this.pTabPanes.splice(index, 1); } }, setCurrentName(name){ if(this.currentName !== name){ this.currentName = name; this.$emit('input', name); } }, // 标签页点击事件 handTabNavClick(name, pane, e){ if(this.currentName === name || pane.disabled){ return; } let before = this.beforeClick(); if(before && before.then){ before.then(() => { this.setCurrentName(name); this.$emit('tabClick', pane, e); }) }else{ this.setCurrentName(name); this.$emit('tabClick', pane, e); } } }, watch: { value(newVal){ this.setCurrentName(newVal); }, currentName(){ this.$nextTick(() => { this.$refs.p_tab_nav.scrollToActiveTab(); }); } }, render(h) { let {$scopedSlots} = this; let $default = $scopedSlots.default(); let qTabPanes = $default.map(item => { /* 过滤<PTabs>xxx</PTabs>中传递的xxx内容。这里只接收<PTabPane>组件,因为我们需要根据<PTabPane>组件的数量来生成 * <PTabNav>组件,如果参差了其它节点则会导致不能正确生成<PTabNav>组件 */ if(item.componentOptions && item.componentOptions.tag === 'PTabPane'){ return item; } }); let qTab = h('PTabNav', { props: { // 将tab-pane传递给 <PTabNav>组件,<PTabNav>组件就知道要有多少个tab-item了 tabPanes: this.pTabPanes, handTabNavClick: this.handTabNavClick }, ref: 'p_tab_nav' }); let qTabBody = h('div', { staticClass: 'p-tabs_content' }, qTabPanes); console.log($default) return h('div', { staticClass: 'p-tabs' }, [qTab, qTabBody]); }, mounted() { //console.log(this) this.$nextTick(() => { this.$refs.p_tab_nav.scrollToActiveTab(); }); } }</script><style lang="stylus">.p-tabs{ .p-tabs_header{ position: relative; margin-bottom: 15px; &.is-scrollable{ padding-left: 20px; padding-right: 20px; } } .p-tabs_nav-prev, .p-tabs_nav-next{ position: absolute; top: 0; width: 20px; height: 100%; display: none; &::before{ position: absolute; content: ' '; font-size: 0; line-height: 0; width: 10px; height: 10px; top: 50%; left: 50%; border-top: 1px solid #eee; border-left: 1px solid #eee; margin: -5px 0 0 -5px; } cursor: pointer; &.disabled{ cursor: default; border-color: #aaa; } } .p-tabs_nav-prev{ left: 0; &:before{ transform: rotate(-45deg); } } .p-tabs_nav-next{ right: 0; &:before{ transform: rotate(135deg); } } .p-tabs_header{ &.is-scrollable{ .p-tabs_nav-prev, .p-tabs_nav-next{ display: block; } } } .p-tabs_nav-scroll{ overflow: hidden; } .p-tabs_nav-list{ position: relative; float: left; white-space: nowrap; transition: transform .3s; } .p-tabs_nav-item{ display: inline-block; height: 40px; line-height: 40px; padding: 0 20px; color: #fff; cursor: pointer; &.active, &:hover{ color: #ffb845; } &.disabled{ cursor: not-allowed; color: #aaa; &:hover{ color: #aaa; } } } .p-tabs_content{ position: relative; overflow: hidden; } .p-tabs-pane{ color: #fff; }}</style>PTabPane.vue ...

April 22, 2019 · 5 min · jiezi

分享数百个 HT 工业互联网 2D 3D 可视化应用案例

过去的 2018 年,我们认为是国内工业互联网可视化的元年,图扑软件作为在工业可视化领域的重度参与者,一线见证了众多 HTML5/Web 化、2D/3D 化的项目在工业界应用落地,我们觉得有必要在此分享下过去一年,基于 HT 实施的数百个工业互联网 2D 3D 可视化应用案例,希望能激发行业和学术工作者对可视化的深度思考,为推进国内工业互联网发展出份薄力。 数百个工业互联网2D/3D可视化案例集: http://www.hightopo.com/demos... 提到工业互联网往往会涉及:物联网、IoT、5G、数字孪生、边缘计算、PaaS平台、SaaS应用、产业互联网、互联网+、工业4.0、智慧城市、智慧园区、智慧楼宇、智能制造等概念,但本文将围绕可视化的话题,围绕更基础的 HTML5/WebGL/WebVR 等底层技术,我们觉得业界还没达到智能化、平台化的成熟阶段,走得太快即使是 GE Predix 也会从明星变流星,了解垂直行业需求,采集足够多有效数据,做好实时的、稳定的、美观的、Web 化的 2D 和 3D 数据可视化呈现,是工业互联网需要走好的第一步。 3D城市建筑群: http://www.hightopo.com/demo/...3D动车站: https://hightopo.com/demo/Bul...3D海上钻井平台: http://www.hightopo.com/demo/...3D水泥工厂工艺流程: http://www.hightopo.com/demo/...3D转油站管网设备监控系统: http://www.hightopo.cn/demo/t...3D高炉炼铁工业流程: http://www.hightopo.com/demo/...3D机房可视化:http://www.hightopo.com/demo/... 正如图扑软件合作伙伴研华科技董事长刘克振所言: 先要实现数据的可视化,生产和经营管理改善达到15%后再一点一滴的往前进。 研华科技 WISE-PaaS 工业物联网云平台,基于 HT 图形组件技术,集成边缘计算和 IoT 云平台,提供从边缘感知及设备到云的数据采集、分析、可视化软件服务,协助系统集成商和制造商快速开发各垂直产业的应用,形成新形态的 IIoT 云端商务模式。2018 年研华物联网共创峰会上,研华发布了基于 Hightopo/HT for Web 的最新物联网平台架构 WISE-PaaS 3.0,WISE-PaaS/SaaS Composer 实现了流程可视化云端组态工具;支援客制化绘图元件,可将应用场景导入 3D 建模绘制与互动,并以毫秒等级的画面刷新速度,搭配 WISE-PaaS/Dashboard 将关键管理数据以视觉直观呈现,协助萃取数据价值与提升运营效率。 3D园区能耗管理系统:2D污水处理工业流程:WISE-PaaS软件平台架构: 近年来,中国制造2025战略的提出为制造业转型升级指明了方向,先进制造业作为经济增长的新引擎正在逐步发力。最近图扑软件合作伙伴三一集团,登陆浙江卫视《智造将来》节目,三一无人挖掘机被赞“新制造”的开始,节目中三一重机董事长俞宏福向观众介绍,所有三一设备已实现互联,通过大屏幕可以看到,地图上每一个点,都代表一台挖掘机在工作,此 Powered by HT 的挖掘机运维大屏,是又一 HTML5 技术在工业制造领域的经典应用案例。 HT Inside《智造将来》第一季:三一重工实时运维大屏:3D挖掘机: http://www.hightopo.com/demo/... ...

April 22, 2019 · 2 min · jiezi

关于正则表达式的一些笔记整理

基础知识一 元字符 \b 单词分界空格\d 数字 [0-9]\w 英文 数字 下划线 [a-z0-9_]\s 空白字符反义\D [^0-9]\W [^a-z0-9_]\S 非空白字符. 任意字符 少用.* 任意数量的不包含换行的字符 贪婪匹配.? 懒惰 非贪婪匹配\u4e00-\u9fa5 中文二 量词 三 集合 字符类 [abc] 匹配a/b/c任意字符 [^abc] 匹配除了abc外的任意字符 [a-z] 匹配a到z任意字符 //注意:里面的-代表的是范围 例如'ahd-fj-k'.replace(/[a-z]/g,'A') //输出 》AAA-AA-A//如果我想把斜杠也替换了呢 有两个方法 1. 利用转义符\ 'ahd-fj-k'.replace(/[a-z\-]/g,'B') //输出BBBBBBBB 2. 后面加多一个- 'ahd-fj-k'.replace(/[a-z\-]/g,'B') //输出BBBBBBBB//() 在集合里面默认被转义了 like this //'(122)do('.replace(/[(\d)]/g,'A') 输出 AAAAAdoA //具体被转义范围不确定 欢迎普及补充 四 分支 123|34|567 //匹配123或34或567五 边界 开始结束 ^ //代表开始 在[]代表非$ //代表结束六 修饰符 g //全局匹配 不写的话匹配完第一个就停止i //忽略大小写m //忽略换行//上面3可叠加使用七 贪婪模式和非贪婪模式js默认贪婪模式 即最大可能的匹配想要改成非贪婪模式在后面加个? ...

April 22, 2019 · 2 min · jiezi

人工智能商业化全面解析,内含趋势解读

人工智能商业化是什么意思?它和商业智能有怎样的联系?本文从概念、重大发展事件、发展趋势这几个方面全面解读人工智能商业化。 121 一、概念人工智能商业化,是指人工智能走向商业化的历程,即人工智能实现商业场景的应用。人工智能的商业化进程正一步步通过各种形态渗透到社会的方方面面。 二、重大发展事件1、自2016年百度提出AI战略之后,2017年阿里巴巴成立了达摩院,腾讯也在全球合作伙伴大会上说要发展AI。BAT之间已经形成共识,人工智能这个未来战场已然开启。 2、国务院国务院于2017年7月8日印发并实施我国第一份人工智能发展规划——《新一代人工智能发展规划》,对人工智能的发展进行了战略性部署,到2030年,我国人工智能理论、技术与应用总体达到世界领先水平,成为世界主要人工智能创新中心。 3、第十六届中国互联网大会上,工业和信息化部部长苗圩曾表示,新兴科技产业应加强关键核心技术的攻关突破,加快人工智能、虚拟现实等技术的研发和商用。 4、在“2018全球智能+新商业峰会”上,亿欧公司发布“2018中国人工智能商业落地100强榜单”与研究报告。报告针对13个行业、61项人工智能技术应用进行了研究,涉及安防(16家)、医疗(10家)、金融(8家)等10个领域。一定程度上,该榜单反映了人工智能在中国各细分领域的商业化程度。 三、发展趋势如今,那些在线化程度高的行业,已经最先应用人工智能技术。最早期进入打进人工智能的行业,是拥有优质数据的行业。比如,在金融行业是现在人工智能应用最好的一个行业,因为互联网金融已经做好了使用AI的铺垫;美团等公司将餐饮服务和线上业务连接起来,滴滴等公司将交通出现与线上业务结合起来,AI在整理它们的数据和业务时也起到了非常主要的作用。 以后,成本的降低和技术进一步成熟,AI会蔓延到个人场景,全面自动化的时代终将到来。随着人工智能技术日趋成熟,智能产品价格也大幅下降,AI最终会从一个企业应用走进千家万户。 “人工智能”现在已成投资的热门方向。现阶段,在人工智能领域,百度、谷歌、苹果、微软、Facebook、IBM、英特尔等国内外互联网巨头纷纷加注资金,对应用更为广泛的人工智能产品进行开发。 同时,AI机器人引入多个市场,同时带动整个产业链。例如各类场景机器人解决方案、小米扫地机器人等等。机器人市场的爆发,同时带动了上游零部件、核心技术产品供应商的商业落地。 它和商业智能有怎样的联系?看权威解读人工智能的商业化与商业智能(BI)。

April 21, 2019 · 1 min · jiezi

权威解读人工智能的商业化与商业智能(BI)

本文就来深度剖析一下人工智能商业化跟商业智能(BI)间的关系。先介绍它们的概念,再说明它们之间联系。 timg 先简要介绍一下AI、AI商业化和BI。 AI是计算机科学的一个分支,它企图了解智能的实质并生产出一种智能机器。 AI商业化就是人工智能走向商业化的过程。人工智能的商业化进程正一步步通过各种形态渗透到我们生产、生活的方方面面,成为我国经济发展的又一驱动力。 BI的定义为:商业智能描述了一系列的概念和方法,通过应用基于事实的支持系统来辅助商业决策的制定。 如今,那些在线化程度高的行业,已经最先应用人工智能技术。比如,在金融行业是现在人工智能应用最好的一个行业,互联网金融已经做好了使用AI的铺垫。 人工智能商业化应用途径可以包含方方面面,在商业智能这一方面也可以。 声智科技副总裁李智勇认为,AI的应用现在有两个大的方向,一个是纯粹的偏数据的应用,比如与金融行业结合。“另一个就是软硬融合,直接形成一个感知的层面,进行决策,比如自动驾驶和智慧城市。 在过去几年的投资版图中,AI+BI领域占据了线性资本投资历史的一大板块,这个领域可以归于线性资本聚焦的业务性数据智能(Applied Data Intelligence)。 在AI+BI领域中,重要的是AI能不能进一步提供增值服务,比如能够准确反映出企业健康状态来。就像互联网广告投放,AI算法对于数据挖掘技术的提升,能实现广告的精准投放。 现在看来,是有希望的。AI作为类似“中间介质”的角色,帮助产品的其他环节实现商业变现。例如,对于智能音箱、教育机器人等智能设备,语音交互技术优化了人机交互模式,提升了用户体验。然而,智能设备的使用价值不在于其本身,而是在于借助语音交互为用户提供的内容和服务。由于AI技术对于用户体验的优化,使得内容和服务的分发流量增加,从而实现商业价值。 读者也应了解更多人工智能(AI)和商业智能(BI)的区别与联系。

April 21, 2019 · 1 min · jiezi

jQuery 实现支持分级标题标签的文章目录

背景首个版本https://www.ouorz.com/366 修改意见鉴于单个 H 标签设置比较麻烦纠结,而且有主题用户反馈,索性改成可以分级的啦 代码var count_ti = count_in = count_ar = count_sc = count_hr = count_e = 1;var offset = new Array;$('.article-content h3').each(function () { //each获取h3内容 $('#article-index').html($('#article-index').html() + '<li id="ti' + (count_ti++) + '"><a onclick="$(\'body\').animate({ scrollTop: $(\'#in' + (count_hr++) + '\').offset().top - 100 }, 500);"><i class="czs-circle-l"></i> ' + $(this).eq(0).html() + '</a></li>'); $(this).eq(0).attr('id', 'in' + (count_in++)); //h3添加id offset[0] = 0; offset[count_ar++] = $(this).eq(0).offset().top; //h3位置存入数组 count_e++});if (count_e !== 1) { //若存在h3标签 $(window).scroll(function () { //滑动窗口时 var scroH = $(this).scrollTop() + 130; var navH = offset[count_sc]; //从1开始获取当前h3位置 var navH_prev = offset[count_sc - 1]; //获取上一个h3位置(以备回滑) if (scroH >= navH) { //滑过当前h3位置 $('#ti' + (count_sc - 1)).attr('class', ''); $('#ti' + count_sc).attr('class', 'active'); count_sc++; //调至下一个h3位置 } if (scroH <= navH_prev) { //滑回上一个h3位置,调至上一个h3位置 $('#ti' + (count_sc - 2)).attr('class', 'active'); count_sc--; $('#ti' + count_sc).attr('class', ''); } });} else { $('.index-div').css('display', 'none')}↑ JavaScript 代码 ...

April 21, 2019 · 1 min · jiezi

jQuery 实现一个文章阅读进度条功能

背景阅读进度虽然没啥具体的用处,但是我突然想起来了,随便做做也是极好的 ????获取元素 offset 高度、元素高度、滑动距离就能实现了 代码var content_offtop = $('.article-content').offset().top;var content_height = $('.article-content').innerHeight();$(window).scroll(function () { if (($(this).scrollTop() > content_offtop)) { //滑动到内容部分 if (($(this).scrollTop() - content_offtop) <= content_height) { //在内容部分内滑动 this.reading_p = Math.round(($(this).scrollTop() - content_offtop) / content_height * 100); } else { //滑出内容部分 this.reading_p = 100; //确保进度条铺满 } } else { //未滑到内容部分 this.reading_p = 0; //确保进度条不显示 } $('.reading-bar').css('width', this.reading_p + '%');});↑ JavaScript 代码

April 21, 2019 · 1 min · jiezi

HTML5原生拖放事件的学习与实践

前言之前学习了HTML5的拖放事件,开发中也用到了拖拽组件。为了厘清整体的逻辑,专门做了一个小例子。具体实现的效果也很简单:元素可以在容器中任意拖动,元素被移入容器的时候,还会有相关样式的改变已达到更好的展示效果。例子基本运用了拖放事件的全部事件,并且尽量简洁的展示了出来。特此记录。????阅读更多系列文章 / 阅读原文????拖放事件介绍由名字可以看出来,拖放事件由2部分组成:拖动和释放。而拖动又由2部分组成,分别是被拖动元素的相关事件和元素容器的相关事件。1、被拖动元素的相关事件 :事件名称说明dragstart在元素开始被拖动时候触发drag在元素被拖动时反复触发dragend在拖动操作完成时触发2、容器的相关事件 :事件名称说明dragenter当被拖动元素进入目的地元素所占据的屏幕空间时触发,一般需要取消浏览器的默认行为。dragover当被拖动元素在目的地元素内时触发,一般需要取消浏览器的默认行为。dragleave当被拖动元素没有放下就离开目的地元素时触发3、释放事件 :事件名称说明drop当被拖动元素在目的地元素里放下时触发,一般需要取消浏览器的默认行为。效果展示为了方便说明,先看代码实现的效果。请前往 Github仓库 下载 demo.html 和 demo.js 到本地,然后用Chrome打开html文件,初始效果如下图:将图中的可拖拽元素,拖放到下面的容器中,这个过程的效果如下所示。箭头表示拖拽方向,方框代表动态改变的容器样式。最后,松开鼠标,将元素放入到下面的容器中,整个过程完成。代码实现首先,先编写html代码。因为元素可以在两个容器之间任意拖动,因此这两个容器都需要监听drapenter、dragover、dragleave、drop这四个事件。被拖拽元素的 draggable 属性需要指明为 true ,才可以被拖拽。同时为了记录一些信息,需要监听dragstart事件。<body> <script src="./demo.js"></script> <div class=“container” ondragenter=“onDragEnter(event)” ondragover=“onDragOver(event)” ondragleave=“onDragLeave(event)” ondrop=“onDrop(event)” > <div id=“target” draggable=“true” ondragstart=“onDragStart(event)"> 被拖拽元素 </div> </div> <div class=“container” ondragenter=“onDragEnter(event)” ondragover=“onDragOver(event)” ondragleave=“onDragLeave(event)” ondrop=“onDrop(event)” ></div></body>为了让拖拽效果更明显,实现效果展示->第二部分的,拖拽元素进入一个新的容器的时候,新容器展示阴影效果。编写阴影效果样式:<style> .container { width: 200px; height: 200px; padding: 10px; border: 1px solid #aaaaaa; margin-bottom: 10px; transition: box-shadow .3s ease; } #target { width: 50px; height: 50px; border: 1px solid black; margin: 0 auto; } .container.active { border-bottom-width: 0; box-shadow: 0 10px 6px -6px #777; }</style>最后,编写 demo.js 代码。具体逻辑请看代码中的注释信息:let target = null, container = null// 寻找拖拽元素的容器类function findParentContainer(node) { if(!node || node === document) { return null } if(node.classList.contains(‘container’)) { return node } return findParentContainer(node.parentNode)}// 元素开始被拖拽时, 标记元素原生的容器类function onDragStart(event) { target = event.target container = findParentContainer(target)}// 元素进入目的容器时, 如果不是原来的容器, 则可以放置// 此时更改样式, 以更好向用户展示function onDragEnter(event) { event.preventDefault() if(event.target !== container) { event.target.classList.add(‘active’) }}// 元素在目的容器内时触发function onDragOver(event) { event.preventDefault()}// 元素离开目的容器, 需要移除相关样式function onDragLeave(event) { event.preventDefault() event.target.classList.remove(‘active’)}// 元素被放置在目的容器, 添加DOM节点, 移除相关样式function onDrop(event) { event.preventDefault() event.target.appendChild(target) event.target.classList.remove(‘active’) target = null container = null}参考链接代码地址: Github 《HTML5拖放》 《HTML5原生拖拽/拖放》 更多系列文章⭐在GitHub上收藏/订阅⭐《前端知识体系》JavaScript基础知识梳理(上)JavaScript基础知识梳理(下)ES6重难点整理谈谈promise/async/await的执行顺序与V8引擎的BUG前端面试中常考的源码实现Flex上手与实战……《设计模式手册》单例模式策略模式代理模式迭代器模式订阅-发布模式桥接模式备忘录模式模板模式抽象工厂模式……《Webpack4渐进式教程》webpack4 系列教程(二): 编译 ES6webpack4 系列教程(三): 多页面解决方案–提取公共代码webpack4 系列教程(四): 单页面解决方案–代码分割和懒加载webpack4 系列教程(五): 处理 CSSwebpack4 系列教程(八): JS Tree Shakingwebpack4 系列教程(十二):处理第三方 JavaScript 库webpack4 系列教程(十五):开发模式与 webpack-dev-server……⭐在GitHub上收藏/订阅⭐ ...

April 20, 2019 · 1 min · jiezi

html5 video标签无法播放格式已兼容的视频

偶然发现html5的video标签不能播放MP4格式的视频,但是文档明确表明video标签是兼容MP4格式的。又多试几次发现,并不是所有的MP4格式都不能播放,很明显是视频的问题。在查了相关资料,原来是视频的格式虽然相同,但是需要的codec是不一样的。在pc端的播放程序,一般会加载很多解析程序,所以看起来MP4格式是没有什么区别的。但是video标签提供的解析方式单一,虽然都是MP4格式,但有些依然是不能播放的。问题找到了,解决方法就好办了。video标签我们是没办法改的,只能改视频源。用工具转换视频,一般工具都会支持转换成支持html5 video标签的类型,虽然扩展名可能是一样的,但是,video能播放了。还可以在保存视频的时候转换,存放视频的服务器是我们自己的,在接视频上传接口的时候,为了保护视频的播放,我们可以在视频流保存成文件之前先进行转换,网上有很多转换的代码!晚安!

April 20, 2019 · 1 min · jiezi

第二集: 从零开始实现一套pc端vue的ui组件库(icon组件)

第二集: 从零开始实现(icon组件)本集定位: 这套ui组件我本来是先从button做的, 但是我发现每个组件都要用到icon这个组件, 如果没有他, 很多组件没法扩展, 而且icon本身不依赖其他组件, 所以还是先把它作为本篇文章的重点吧.icon组件 读过element-ui源码的同学都知道, 他们选择的是字体图标的方式来做icon组件的, 而我的这套ui在写法与用法上参考了他们的做法, 但组件本身是靠svg来书写的,其中的区别还是简单阐述一下把.icon font 与 svg1.icon font做为字体无法支持多色图形,这就很尴尬了.2.icon font主要在页面用Unicode符号调用对应的图标,这种方式不管是浏览器,搜索引擎和对无障碍方面的能力都没有SVG好.3.icon font采用的是字体渲染,icon font在一倍屏幕下渲染效果并不好,在细节部分锯齿还是很明显的,SVG上面我说过它是图形所以在浏览器中使用的是图形渲染,所以SVG却没有这种问题.4.兼容性较差,支持 ie9+,及现代浏览器.5.浏览器渲染svg的性能一般,还不如png。行动起来 上一集基本环境已经搭建好了, 这里我们采用’bem’的思想, 来构建组件的样式, 所有的样式抽离在一个文件夹里面, 做到组件本身没有样式代码,我们来先书写组件的代码.结构如下:index.js文件里面是导出这个组件:import Icon from ‘./main/icon.vue’// 明白vue.use方法原理的同学都能明白这段代码的意义// 当被use的时候, 进行icon组件的渲染Icon.install = function(Vue) { Vue.component(Icon.name, Icon);};export default Icon这样单抽出来做一个文件的好处是,更好的工程化, 保证职能的单一性.main文件夹为什么main文件夹里面只有一个文件还要单独抽成一个文件夹??, 原因是有的组件可能要配合自己独有的容器组件一起使用, 比如一个button的包裹容器, 他可以让内部的每个button有相同的上下左右距离, 相同的圆角等等…icon.vue文件第一步: 使用svg, 当然要去下载svg图片了, 本篇推荐使用大家都在用的阿里巴巴矢量图标库,选择自己喜欢的图标放入购物车选项.第二步: 放入工程,点击添加入项目, 如果没有项目要点击新建项目来完成此操作.第三步: 复制链接到你的script标签里面引入, 在index.html里面就可以, 下面会讲遇到的问题与优化.// 使用方法如下:<svg class=“icon”>// 把名字写在下面的’xxx’处,就可以正常显示图标了; <use xlink:href="#icon-xxx"></use></svg>第四步: 开始正式书写组件.1:先定义一个最简单的组件模板, 他仅仅支持颜色的调整, 与icon的调整2:svg的颜色控制, 需要通过fill属性, 我经常面试遇到说自己用过svg图片, 但是没听说过fill属性的尴尬场面????3:不传颜色的时候,svg默认是原色<template> <div class=‘cc-icon’ }"> <svg :style="{fill:color}"> <use :xlink:href=’#icon-${name}’></use> </svg> </div></template><script>export default {name: “ccIcon”, props: { color: String, name: { type: String, required: true } }};</script>第五步: 基本的结构已经有了, 现在要考虑的就是我们的组件还需要什么功能? .1:控制图标的大小, 这个还是需要的props: {// 接受一个size属性 size: { // 因为用户可能传带单位的与不带单位的 type: [Number, String], default: “1em” } },computed: { // 计算属性里面对这个值进行操作, 类型如果是数字, 就我们来给他加上单位吧,也就是默认单位是’px’ iconSize() { if (typeof this.size === “number”) return this.size + “px”; else return this.size; } }<template> <div class=‘cc-icon’ height: iconSize, // 在此使用 width: iconSize, // 在此使用 }"> <svg :style="{fill:color}"> <use :xlink:href=’#icon-${name}’></use> </svg> </div></template>2:如果是加载的icon, 我们需要让他旋转一下, 这里我是这么做的, 所有的加载图标, 我的命名都是load加数字, 所以检测字符串里面是否有这个关键词就好了<svg :style="{fill:color}" :class="[ ‘cc-icon-’+name, { //icon-loading这个class名, 只有在icon的name属性里面有load字段的时候加上, 这个属性名里面的属性就是旋转.’~‘位运算符是很高效的书写方式, 也就是对位求反,1变0,0变1,也就是求二进制的反码, 这里不懂的话, 先看犀牛书, 简单的说就是把-1转成0了, 变成了布尔中的false; ‘icon-loading’:~name.indexOf(’load’) } ]"> <use :xlink:href=’#icon-${name}’></use> </svg>3:实际使用的时候我发现, 不给div加上 display: ‘inline-flex’,属性, icon有时候对不整齐, 所以还是加上为妙,这个地方以后应该还会弄一弄, 感觉还会有一段故事.<div class=‘cc-icon’ :style="{ display: ‘inline-flex’, height: iconSize, width: iconSize, }">4: 接下来就是为了配合其他组件的 disabled 状态 把图标本身也置为灰色, 这样写很方便<svg :style="{fill:color}" :class="[ ‘cc-icon-’+name, { ‘icon-loading’:~name.indexOf(’load’), ‘is-disabled’:disabled // 在这里进行了定义 } ]"> <use :xlink:href=’#icon-${name}’></use> </svg> props: { disabled: Boolean // 当然是布尔类型 },小知识点: props里面定义了默认类型是布尔,则用户可以直接在标签上写属性名, 不给属性值也是可以代表true的, 但是默认不是布尔, 不给属性值的话, 组件里面得到的就是undefined;第六步: 书写样式吧icon.scss文件1:disabled状态时禁止点击2:icon-loading 时旋转@import ‘./common/mixin.scss’;@import “./common/animation.scss”;@include b(icon) { .#{$state-prefix}disabled { cursor: not-allowed; fill: $–color-disabled; } .icon-loading { animation: rotating 1s infinite linear; }}mixin.scss文件里面的b方法抽象出$namespace方便管理@mixin b($block) { $B: $namespace+’-’+$block !global; .#{$B} { @content; }}animation.scss文件@keyframes rotating { 0% { transform: rotateZ(0deg); } 100% { transform: rotateZ(360deg); } }var.scss文件// lulu的美工不好, 只是想做出点不同样子的东西玩玩// 基本色$–color-black:#000000 !default;$–color-white:#FFFFFF !default;// 基本色鲜艳$–color-nomal:#409EFF !default;$–color-success:#7CCD7C !default;$–color-warning:#FFB90F !default;$–color-danger: #FF0000 !default;$–color-disabled: #bbbbbb !default;$–color-difference: #F5F7FA !default;// 字体$–size-big: 16px;$–size-nomal: 15px;$–size-small: 14px;// 输入框$–color-input-placeholder:#aaa第六步: 上面说的svg文件引用的改良, 可以把svg文件下载到本地, 在别人因为这个ui组件的时候不会引用index.html文件, 而且大部分组件都引用了icon,我们可以去阿里巴巴矢量图标库进行操作点击下载到本地取出js文件, 让在本地用index.js文件引用这个js文件就完成了!!结束icon组件是最小的组件, 其他组件的代码量与难道都大的多, 详细code与用法可以访问下面的地址, npm同步更新!下一期是关于button的,我们一起交流吧github:项目地址个人博客:个人博客 ...

April 20, 2019 · 2 min · jiezi

前端错误监控以及上报方法总结

捕获错误的常见的几种方法GlobalEventHandlers.onerrorwindows下面的全局error事件程序,当有javaSript脚本运行错误或者资源<img>、<script>加载失败时,都会触发Event接口的error事件,也能被window.addEventListener捕获到两种写法window.onerror = function(message, source, lineno, colno, error) { console.log(message)//字符串错误信息 console.log(source)//发生错误的脚本 console.log(lineno)//发生错误的行号 console.log(colno)//发生错误的列号 console.log(error)//Erroe对象 return true//将代码错误定格在捕获阶段}window.addEventListener(’error’, (msg, url, row, col, error) => { console.log( msg, url, row, col, error ); return true;}, true);注意window.onerror只有在返回true时,异常才不会向上抛出,原理是冒泡机制。而且window.onerror是无法捕获到网络异常的,因为网络请求异常不会事件冒泡,虽然能在捕获阶段捕获到,但是无法判断HTTP的状态码,需要配合服务端才能排查。我们平时写window.onerror的时候,最好写在最顶端,以免前面的错误脚本阻断了。同时在vue或者react框架中,他们有自身的错误捕获机制,所以会掩盖window.onerror,比如vue的Vue.config.errorHandler。想详细了解看官网文档即可。try…catch…finally这种方式应该是我们平时用的最多的,具体功能想必大家也应该都很清楚,将我们需要检测的代码包裹在try和catch中,当发生语法错误或者其他错误时,就会从catch里捕获到,而不管前端发生了什么,最后finally里的代码总会执行。下面的代码会怎么执行,大家可以思考一下try { try { throw new Error(“oops”); } catch (ex) { console.error(“inner”, ex.message); throw ex; } finally { console.log(“finally”); return; }}catch (ex) { console.error(“outer”, ex.message);}特别注意try…catch只能捕获到运行时的非异步错误,而语法错误和异步错误就捕捉不到。还有一点就是try..catch比较消耗性能,能少用的最好。unhandledrejection有些错误try..catch和windows.onerror也是无能为力的,比如说Promise实例从pending转变为rejected时,如果加了catch就会被捕获到,但要是没有加,那么继续抛出就会Uncaught(in promise) Error比如下面代码就捕获不到错误window.onerror = function(message, source, lineno, colno, error) { console.log(message)//字符串错误信息 console.log(source)//发生错误的脚本 console.log(lineno)//发生错误的行号 console.log(colno)//发生错误的列号 console.log(error)//Erroe对象 return true//将代码错误定格在捕获阶段} // 调用Promise.reject类方法 Promise.reject(‘promise error’); // 在工厂方法中调用reject方法 new Promise((resolve, reject) => { reject(‘promise error’); }); // 在工厂方法或then回调函数中抛异常 new Promise((resolve) => { resolve(); }).then(() => { throw ‘promise error’ });我们可以通过下面的方法监听到window.addEventListener(‘unhandledrejection’, function (event) { // …your code here to handle the unhandled rejection… // Prevent the default handling (such as outputting the // error to the console event.preventDefault();});但是这方法的兼容性有点失望What the heck is “Script error”?‘Script error’ 这个错误是比较常见的,一般通过windows.onerror捕获到后基本确实就是哪个script文件有问题,而且这个文件还是跨域的,既然是跨域导致信息不全,所以首先要解决的就是跨域问题,关于跨域方面的前端解决方案可以看我这篇文章《前端常见跨域方案汇总)》;对于script标签,我们还需要额外配置一个参数crossOrigin<script src=‘www.example.com’ crossorigin></script>至于服务端,常用的就是了解sourceMap对于这个功能的讲解,看阮大神的讲解)是最适合不过的了,当然了解其基本设计思路也是很重要的,SourceMap其实就是一个信息文件,存储着源文件的信息及源文件与处理后文件的映射关系。我们平时vue或者react项目开发中,通过webpack配置在测试环境中默认开启生成SourceMap,出现错误能够及时重现原代码,但是正式环境我们一般是不会将SourceMap文件发布上去的,但是正式环境的代码一般都是压缩过的,所以如果报错了,一般是很难 定位到原代码的位置,这时候优秀的错误上传功能,以及平台处理错误分析就显得尤为重要了。下图就是大概的设计思路。Navigator.sendBeacon()存在的意义平时我们很常见网页卡顿或者直接崩溃,一般是通过window 对象的 load 和 beforeunload 事件实现了网页崩溃的监控;具体看这篇文章,Logging Information on Browser Crashes实现代码 window.addEventListener(’load’, function () { sessionStorage.setItem(‘good_exit’, ‘pending’); setInterval(function () { sessionStorage.setItem(’time_before_crash’, new Date().toString()); }, 1000); }); window.addEventListener(‘beforeunload’, function () { sessionStorage.setItem(‘good_exit’, ’true’); }); if(sessionStorage.getItem(‘good_exit’) && sessionStorage.getItem(‘good_exit’) !== ’true’) { /* insert crash logging code here */ alert(‘Hey, welcome back from your crash, looks like you crashed on: ’ + sessionStorage.getItem(’time_before_crash’)); }但是上面的编码模式存在不友好的问题,当我们尝试在卸载页面前通过上传服务器数据,为了延迟页面卸载,需要通过同步XMLHttpRequest 发送数据或者创建一个几秒的循环来延迟卸载。这样的处理可想而知不是很友好,这时候sendBeacon()就横空出世了,很简单的实现向服务器发送数据,同时又不会影响下一个页面的加载,具体如下面简单的代码实现。window.addEventListener(‘unload’, logData, false);function logData() { navigator.sendBeacon(“www.youAddress.com”, analyticsData);}扩展阅读7 天打造前端性能监控系统成熟解决方案badjs、 sentry、raven-jsFunDebug)如果大神您想继续探讨或者学习更多知识,欢迎加入QQ或者微信一起探讨:854280588 ...

April 20, 2019 · 1 min · jiezi

运用clip-path的纯CSS形状变换

在之前所提到绘制正多边形的方法,算是纯粹利用伪元素来完成,不过坦白说还有另外一种方法,可以将单一div做更多形状的变换,这种方法就是CSS3的“clip-path”,这个“clip-path”看起来有点眼熟,因为它原本就存在于SVG里头,利用掩码(剪裁)的方法,连接坐标绘制掩码区域,就可以做出许多不同的形状,让底色或底图显现,随着浏览器对于CSS3的支持度大幅提升,自然而然的就可以用它来做些与众不同的变化。运用clip-path超强的网站最先看到这个属性的应用,是从这个网站看到的:http://species-in-pieces.com/,不得不说这个网站做得实在太神了,一开始看到还真以为是用SVG做的,没想到竟然是用CSS刻出来的…真是太惊人啦!接着在找数据的过程中,又发现一个很强的网站:http://bennettfeely.com/clippy/,专门介绍「clip-path」这个CSS3的属性,你可以直接在上面拖拉或修改,除了贝兹曲线外,几乎任何形状都做得出来(中空的部分要用组合的)使用clip-path绘制多边形如果不考虑一些浏览器支持度的问题,使用clip-path来绘制多边形,还比利用伪元素还制作多边形来得简单许多,而且也可以做到单一div绘制超过八边形,使用伪元素的绘制是直接从长宽着手,而利用clip-path则是要由每个点的坐标着手,因为是座标点的缘故,要做出正多边形就也同样要用到许多基本的三角函式来计算坐标,以下就利用clip-path来绘制圆形、椭圆和正多边形给大家看看。开始绘制之前,有两点注意事项:使用clip-path要从同一个方向绘制,如果顺时针绘制就一律顺时针,逆时针就一律逆时针,因为polygon是一个连续的线段,若线段彼此有交集,面积区域就会有相减的状况发生(当然如果这是你要的效果就无妨了)。如果绘制时采用「比例」的方式绘制,长宽就必须要先行设定,不然有可能绘制出来的长宽和我们想像的就会有落差,使用「像素」绘制就没有这种问题。圆形circle(半径at圆心坐标).circle{ width:100px; height:100px; background:#0cc; -webkit-clip-path:circle(50% at 50% 50%); }椭圆形ellipse(长、短轴半径at圆心坐标) .ellipse{ width:100px; height:100px; background:#aaa; -webkit-clip-path:ellipse(25% 50% at 50% 50%); }内置矩形inset(上右下左的边距round上右下左圆角).inset{ width:100px; height:100px; background:#99f; -webkit-clip-path:inset(10px 20px 30px 10px round 20px 5px 50px 0); }正三角形 .a{ width:100px; height:87px; background:#c00; -webkit-clip-path:polygon(0% 100%, 50% 0%,100% 100%); }正方形.b{ width:100px; height:100px; background:#069; -webkit-clip-path:polygon(0% 0%, 0% 100%,100% 100%,100% 0%); }正五边形正五边形就要计算一下了,59/(59+95)=38.31%,31/(81*2)=19.14%.c{ width:162px; height:154px; background:#095; -webkit-clip-path:polygon(0% 38.31%, 50% 0%,100% 38.31%,80.86% 100%,19.14% 100%); }正六边形正六边形的计算比较简单,50/(100+502)=25%,150/(100+502)=75%.d{ width:200px; height:174px; background:#f80; -webkit-clip-path:polygon(25% 0%, 75% 0%,100% 50%,75% 100%,25% 100%,0% 50%); }正七边形正七边形是这里头需要计算最多的形状,22/(100+622)=10.09%,202/(100+622)=90.18%,43/(43+97+78)=19.72%,(43+97)/(43+97+78)=64.22%,62/(100+622)=27.68%,(100+62)/(100+622)=72.32%.e{ width:224px; height:218px; background:#09c; -webkit-clip-path:polygon(50% 0%, 90.18% 19.72%,100% 64.22%,72.32% 100%,27.68% 100%,0% 64.22%,10.09% 19.72%); }正八边形正八边形的计算如下,71/(100+712)=29.34%,(71+100)/(100+712)=70.66%.f{ width:242px; height:242px; background:#f69; -webkit-clip-path:polygon(29.34% 0%, 70.66% 0%,100% 29.34%,100% 70.66%,70.66% 100%,29.34% 100%,0% 70.66%,0% 29.34%); }搭配clip-path做动画熟练了clip-path之后,当然就要用它来做点动画,下面提供两个示例,第一个是正多边形的变换,第二个则是三角形的变换组合,虽然看起来很简单,但实际制作起来却要考虑每个点的坐标,为了让形状不要有「翻转」的错觉,形状里头每个点在进行移动的时候,尽可能的不要交错,因为只要一交错,就会有交集的空白产生,就会有不自然或是翻转的现象喔!当然同样的,如果你希望有翻转的效果,应该就要让他们交错啰!正多边形的变换三角形的变换组合需要以上两个动画的代码可以加我: ...

April 19, 2019 · 1 min · jiezi

CSS技巧之'text-justify'

CSS中,当text-align属性被赋值为justify时,text-justify属性经常被用来和text-align属性一起设置文本两端对齐的方式。p { text-align: justify; text-justify: inter-word;}Valuesinter-word: 表示当前文本是通过调整单词(word)之间的间隔来实现两端对齐的,实际上是增加了多余的单词间距.这个属性值其实是word-spacing 属性的变形.inter-character: 表示当前文本是通过调整字符(character)之间的间隔来实现两端对齐的,实际上是增加了多余的字符间距.这个属性值其实是letter-spacing 属性的变形.auto: 允许浏览器从inter-word 和inter-character中挑选合适的值作为两端对齐的对齐方式.多语言情景下,文本渲染之前无法得知这是哪一国的语言.这个时候,(auto)就会允许浏览器用户代理来根据当前文本的语言来选择适合的两端对齐方式.none: 禁用两端对齐规则,也就是移除任何可能通过(样式)层叠生效的两端对齐方式的设置或者重写.到底什么是两端对齐?两端对齐文本是一个很富有想象力的说法,它用来描述文本是如何填充满包含它的父容器的方式.实际上,你可以已经很熟悉两端对齐的文本了,但是你却不认识它.如果你曾经使用过文本编辑软件,比如Word和Google Docs的话,你就可能非常熟悉下面的这些图标了(icons):前面三个是用来设置文本对齐的,就好像CSS的text-align属性, 可以设置文本左对齐、右对齐、和居中对齐.第四个icon就是两端对齐选项.它让文本内容填充满文档的整个宽度,不管有没有影响到单词间距,每一行文字都会紧靠边界右对齐.Google Docs中的两端对齐文本每一行都会扩大单词间距来占据整篇文档的宽度.text-justify 属性允许我们实现同样的效果,但是它可以灵活变通来决定是通过单词(words)间距还是字符(characters)间距来调整文本两端对齐方式.浏览器兼容性text-justify 属性已经被收入了CSS Text Module Level 3 文档。由于可能会在候选推荐期间就被废弃掉,当前text-justify属性已经被列为"at risk"(危险)级别.在不远的将来,它不太可能被纳入各浏览器通用标准,因此并不建议在项目生产中使用这个属性.当前完全支持它的只有Firefox 55+. Internet Explorer 11 和 Edge 14+也支持此属性,但是只有inter-word值有效,而且因为是非正式的属性值,W3C规范也未收录它.浏览器支持数据来自 Caniuse, 点击浏览更多. 有数据表明浏览器版本支持该特性.

April 19, 2019 · 1 min · jiezi

自己鼓捣一个Promise

源码very-simple-promise,包含了不完善的单元测试❤️.感谢代码君的自白这篇的文章主要参考了上面的博客,谢谢他的帮助????。Promise/A+规范Promises/A+规范, 下面????是对规范的内容的部分翻译。英文比较烂,不喜欢的可以不看。承诺必须满足三种状态, pending(等处理), fulfilled(履行), rejected(拒绝)Promises的状态promise处于pending时可以过渡到fulfilled或者rejected状态promise处于fulfilled时不能向其他状态过渡promise处于rejected时不能向其他状态过渡thenpromise的then方法接受两个参数promise.then(onFulfilled, onRejected)onFulfilled和onRejected都是可选参数onFulfilled不是函数需要忽略onRejected不是函数需要忽略onFulfilled如果是一个函数onFulfilled在promise状态为fulfilled时被调用onFulfilled只能被调用一次onFulfilled不能在fulfilled之前不能调用onRejected如果是一个函数onRejected在promise状态为rejected时被调用在rejected之前不能调用它onRejected只能被调用一次onFulfilled or onRejected must not be called until the execution context stack contains only platform code. (原文不太懂什么意思,但是规范给出了注解)onFulfilled和onRejected必须作为函数调用then可以在同一个promise多次调用如果promise被履行, 则onFulfilled回调必须按照then的顺序执行如果promise被拒绝, 则onRejected回调必须按照then的顺序执行promise2 = promise1.then(onFulfilled, onRejected);then必须返回promise如果onFulfilled或者onRejected返回一个值,则运行处理Promise的过程[[Resolve]](promise2, x)(这里处理的Resolve(promise2, x), onFulfilled或者onRejected的返回值会被resolve处理, resolve的第一个参数是then返回的新的promise)如果onFulfilled, onRejected抛出错误error, 则promise2必须为rejected如果onFulfilled不是一个函数, 而promise1的状态为fulfilled, promise2必须与promise1具有相同的值被履行如果onRejected不是一个函数, 而promise1的状态为rejected, promise2必须与promise1具有相同的值被拒绝处理Promise[[Resolve]](promise, x)需要遵循以下规范如果promise与x相等, 抛出TypeError的错误, 并以错误为理由拒绝promise如果x是Promise如果x处于pending,promise也需要保持pending,直到x接受pending如果x处于fulfilled,promise需要使用相同值执行promise如果x处于rejected,promise需要使用相同的值拒绝promise如果x是对象或者函数将x.then赋于then如果获取x.then时抛出错误,则使用错误作为理由拒绝promise如果then是函数????️使用x作为then函数的作用域中的this, 传入两个参数作为回调,分别是resolvePromise, 和rejectPromise如果resolvePromise如果以y为参数运行,则运行[[Resolve]](promise, y), 履行promise。resolve(promise,y)如果rejectPromise以r为参数运行,则以r为原因拒绝promise。reject(promise, r)如果then抛出了错误如果resolvePromise,rejectPromise已经调用对错误忽略如果没有调用,用错误作为原因拒绝promise如果then不是函数,使用x作为参数执行promise如果x不是对象也不是函数,则使用x作为参数执行promise注解onFulfilled和onRejected方法应当是异步执行,且应该在then方法被调用的那一轮事件循环之后的微任务执行栈中执行。可以使用宏任务macrotask和微任务microtask机制实现。也就是说宏任务完成后(Promise的then调用后),会清空微任务队列(执行onFulfilled或者onRejected)。macrotask包含:script(整体代码)、setTimeout、setInterval、I/O、UI交互事件、postMessage 、requestAnimationFrame 、MessageChannel、etImmediate(Node.js 环境)microtask包含:Promise.then、setImmediate、MutaionObserver、process.nextTick(Node.js 环境)事件循环下面????是一个关于事件循环的例子????Promise中的参数函数,应当是立即调用的。我们这时先执行了resolve(1), 这会将外层的Promise的状态置为fulfilled态。但是这时外层的then还没有执行。我们接下来执行了Promise.resolve().then(() => console.log(2)), 我们将then的onFulfilled,push到了macrotask队列中,会在宏任务执行完成后清空微任务。执行外层Promise的then, onFulfilled, push到了macrotask队列中。接着执行console.log(3), 然后清空macrotask队列,执行2,1(队列先进先出)Promise构造函数const pending = 0const fulfilled = 1const rejected = 2function reject (promise, result) {}function resolve (promise, reason) {}export default class Promise { constructor (fn) { this.fn = fn // Promise的状态, 初始状态为pending this._state = pending // Promise的fulfilled态的原因,或者Promise的rejected态的理由 this._value = null // 存储then的队列 this._tasks = [] // 创建Promise对象后,立即执行fn this.init() } init () { try { // 执行fn, 传入包装后的resolve,reject // reject,resolve会修改promise的状态 this.fn( (result) => resolve(this, result), (reason) => reject(this, reason) ) } catch (error) { reject(this) } }}根据规范2.2.6: then may be called multiple times on the same promisethen可以在同一个promise中多次调用。所以我们用一个数组存储then的结果。Promise.prototype.then根据规范2.2.1: A promise’s then method accepts two arguments. Both onFulfilled and onRejected are optional arguments。then接受两个参数, 两个参数可选。根据规范2.2.1.1, 2.2.1.2: If onFulfilled is not a function, it must be ignored. If onRejected is not a function, it must be ignored.。onFulfilled, onRejected必须是函数负责会被忽略。根据规范2.2.2, 2.2.3, onFulfilled必须在状态为fulfilled调用, onRejected必须在状态为rejected调用根据规范2.2.7: then must return a promise。then必须返回一个promise。????️ 为什么不能返回当前的promise?因为根据规范2.1.2, 2.1.3, promise被修改状态后,不能再次修改状态。我们如果需要执行then的callback需要修改promise的状态。我们使用task封装????then的回调以及then返回的promise。class Task { constructor (onFulfilled, onRejected, promise) { if (typeof onFulfilled !== ‘function’) { onFulfilled = null } if (typeof onRejected !== ‘function’) { onRejected = null } this.onFulfilled = onFulfilled this.onRejected = onRejected this.promise = promise }}class Promise { // … then (onFulfilled, onRejected) { let nextPromise = new Promise(function () {}) let task = new Task(onFulfilled, onRejected, nextPromise) if (this._state === pending) { this._tasks.push(task) } else { handlePromise(this, task) } // 返回新的promise return nextPromise }}Promise.prototype.catchcatch函数同样会返回新的promise, 但是在创建task时,我们不会传入onFulfilled参数。所以当promise当为fulfilled态,虽然catch的回调同样存放_task中,但是由于callback为null, 在handlePromise中会向下穿透。class Promise { // … catch (onRejected) { let nextPromise = new Promise(function () {}) // onFulfilled设置为null let task = new Task(null, onRejected, nextPromise) if (this.state === pending) { this.tasks.push(task) } else { handlePromise(this, task) } // 返回新的promise return nextPromise }}Promise.prototype.finallyfinally方法用于指定不管Promise对象最后状态如何,都会执行的操作。我们无论promise的状态如何,都在promise的最后面添加then,并传入了onFulfilled, onRejected两个回调。在回调中,我们执行finally的callback参数。这样无论之前的promise是fulfilled态,还是rejected态,都会执行finally添加的参数。class Promise { // … finally (callback) { // this指向调用finally的对象 const self = this // 向Promise链中添加then,无论,promise是resolve态还是reject态,都会执行callback // 并且会通过then,继续将result或reason向下传递 return self.then( result => Promise.resolve(callback()).then( => result), reason => Promise.resolve(callback()).then( => { throw reason }) ) }}resolveresolve用来修改promise状态,将promise状态设置为fulfilled态, 并执行then的onFulfilled回调根据规范2.3.1: If promise and x refer to the same object, reject promise with a TypeError as the reason.如果promise与x相等,我们使用TypeError的错误拒绝promise根据规范2.3.2。如果result是promise,并且处于pending态,promise需要保持pending态,直到result被执行和拒绝后,我们使用result的状态履行或者拒绝promise。如果result是promise,并且处于fulfilled或rejected态,我们使用result的状态拒绝或者履行promise。根据规范2.3.3, 我们判断result是否为一个Object。如果result为Object, 我们则取出它的then的属性, 判断then属性是否为Function, 如果then为Function, 我们设置then的作用域的this指向result, 我们传入resolvePromise, rejectPromise作为参数。根据规范2.3.4: If x is not an object or function, fulfill promise with x, 如果x不是函数或者对象,我们用result结果作为参数执行promise。function resolve (promise, result) { if (promise === result) { throw reject(promise, new TypeError(‘promise and x refer to the same object’)) } if (isPromise(result)) { if (result._state === pending) { result._tasks.concat(promise._tasks) } else if (result._state === fulfilled || result._state === rejected) { let task while (task = promise._tasks.shift()) { handlePromise(result, task) } } return } if (isObject(result)) { let then = null try { then = result.then } catch (error) { reject(promise, error) } if (isFunction(then)) { try { let resolvePromise = function (y) { resolve(promise, y) } let rejectPromise = function (r) { reject(promise, r) } then.call(result, resolvePromise, rejectPromise) } catch (error) { reject(promise, error) } return } } promise._state = fulfilled promise._value = result if (promise._tasks && promise._tasks.length) { let task = null while (task = promise._tasks.shift()) { handlePromise(promise, task) } }}rejectreject将promise的状态设置为rejected, 并以当前的promise的状态,执行promise中通过then注册的onRejected回调。function reject (promise, reason) { if (promise._state !== pending) { return } promise._state = rejected promise._value = reason let task while (task = promise._tasks.shift()) { handlePromise(promise, task) }}handlePromisehandlePromise函数主要根据当前的promise的状态, 以及内容(resolve或者reject的参数)。处理通过then注册的回调。并且会链式的调用,注册在then返回的新promise的上的then的回调// 将回调的结果,传入第二个then中fn().then().then()根据规范2.2.4, 以及规范给出的注解。当promise的状态改变,onFulfilled, onRejected并不会立即执行,而且在本次的宏任务完成后,才会执行onFulfilled或者onRejected。而setImmediate则是将代码push到微任务队列中。在宏任务中会清空微任务队列。function handlePromise (prevPromise, task) { // 需要在宏任务完后的微任务队列中执行 setImmediate(() => { // nextPromise是then返回的promise const { onFulfilled, onRejected, promise: nextPromise } = task let callback = null let value = prevPromise._value let state = prevPromise.state if (state === fulfilled) { callback = onFulfilled } else if (state === rejected) { callback = onRejected } if (!callback) { // 如果在promise中没有注册callback if (state === fulfilled) { resolve(nextPromise, value) } else if (state === rejected) { reject(nextPromise, value) } } else { try { const result = callback(value) // 对then中返回promise处理 // 将callback返回的结果,带入到新的promise中 resolve(nextPromise, result) } catch (error) { reject(nextPromise, error) } } })}Promise.resolve & Promise.rejectPromise.resolve方法返回一个新的Promise对象,状态为resolved。Promise.reject(reason)方法也会返回一个新的 Promise实例,该实例的状态为rejected。class Promise { // … static resolve (result) { return new Promise((resolve) => { resolve(result) }) } static reject (reason) { return new Promise((, reject) => { reject(reason) }) }}Promise.all && Promise.racePromise.all和Promise.race必须接受一个数组为参数,数组中为多个Promise的实例。Promise.all和Promise.race的使用我就不再这里赘述了。Promise.all会使用计数器,记录Promise数组中的所有Promise实例的状态是否都变为fulfilled态,如果计数器的长度和数组长度一致,我们则会将Promise.all的状态设置为fulfilled态。class Promise { static race (promises) { if (isArray(promises)) { let promisesLength = promises.length return new Promise((resolve, reject) => { for (let i = 0; i < promisesLength; i++) { promises[i].then((result) => { resolve(result) }).catch((error) => { reject(error) }) } }) } else { throw new TypeError(‘The arguments must be arrays’) } } static all (promises) { if (isArray(promises)) { let promisesLength = promises.length let counter = 0 let resultList = [] return new Promise((resolve, reject) => { for (let i = 0; i < promisesLength; i++) { promises[i].then((result) => { counter += 1 resultList.push(result) if (counter === promisesLength) { resolve(resultList) } }).catch((error) => { reject(error) }) } }) } else { throw new TypeError(‘The arguments must be arrays’) } }}其他VueRouter源码分析Preact源码分析 ...

April 18, 2019 · 4 min · jiezi

记录一波video.js的使用及问题

最近的项目中需要播放视频,鉴于html5元素<video>的一些坑及不想自己造轮子,于是就找到了web端播放视频使用量最多的插件video.js,video.js是国外开发者开发的,英语本身就不好的我看英文文档简直是折磨,国内又没有中文文档,能搜的到的基本是简单的使用及最基本的api的介绍,想要实现一些自定义功能无从下手,所以我在这里整理一份我所遇到的问题及解决方法1、视频初始化video.js有两种初始化方式,一种是在video的html标签之中,一种是使用js来进行初始化1.1、在video中进行初始化<video id=“my-player” class=“video-js” controls preload=“auto” poster="//vjs.zencdn.net/v/oceans.png" width=“600” height=“400” data-setup=’{}’> <source src="//vjs.zencdn.net/v/oceans.mp4" type=“video/mp4”></source> <source src="//vjs.zencdn.net/v/oceans.webm" type=“video/webm”></source> <source src="//vjs.zencdn.net/v/oceans.ogv" type=“video/ogg”></source> <p class=“vjs-no-js”> To view this video please enable JavaScript, and consider upgrading to a web browser that <a href=“https://videojs.com/html5-video-support/" target="_blank”> supports HTML5 video </a> </p></video>效果1.2、使用js进行初始化<!– vjs-big-play-centered可使大的播放按钮居住,vjs-fluid可使视频占满容器 –><video id=“myVideo” class=“video-js vjs-big-play-centered vjs-fluid”> <p class=“vjs-no-js”> To view this video please enable JavaScript, and consider upgrading to a web browser that <a href=“https://videojs.com/html5-video-support/" target="_blank”> supports HTML5 video </a> </p></video><script>var player = videojs(document.getElementById(‘myVideo’), { controls: true, // 是否显示控制条 poster: ‘xxx’, // 视频封面图地址 preload: ‘auto’, autoplay: false, fluid: true, // 自适应宽高 language: ‘zh-CN’, // 设置语言 muted: false, // 是否静音 inactivityTimeout: false, controlBar: { // 设置控制条组件 /* 设置控制条里面组件的相关属性及显示与否 ‘currentTimeDisplay’:true, ’timeDivider’:true, ‘durationDisplay’:true, ‘remainingTimeDisplay’:false, volumePanel: { inline: false, } / / 使用children的形式可以控制每一个控件的位置,以及显示与否 / children: [ {name: ‘playToggle’}, // 播放按钮 {name: ‘currentTimeDisplay’}, // 当前已播放时间 {name: ‘progressControl’}, // 播放进度条 {name: ‘durationDisplay’}, // 总时间 { // 倍数播放 name: ‘playbackRateMenuButton’, ‘playbackRates’: [0.5, 1, 1.5, 2, 2.5] }, { name: ‘volumePanel’, // 音量控制 inline: false, // 不使用水平方式 }, {name: ‘FullscreenToggle’} // 全屏 ] }, sources:[ // 视频源 { src: ‘//vjs.zencdn.net/v/oceans.mp4’, type: ‘video/mp4’, poster: ‘//vjs.zencdn.net/v/oceans.png’ } ]}, function (){ console.log(‘视频可以播放了’,this);});</script>2、controlBar组件的说明playToggle, //播放暂停按钮volumeMenuButton,//音量控制currentTimeDisplay,//当前播放时间timeDivider, // ‘/’ 分隔符durationDisplay, //总时间progressControl, //点播流时,播放进度条,seek控制liveDisplay, //直播流时,显示LIVEremainingTimeDisplay, //当前播放时间playbackRateMenuButton, //播放速率,当前只有html5模式下才支持设置播放速率fullscreenToggle //全屏控制currentTimeDisplay,timeDivider,durationDisplay是相对于 remainingTimeDisplay的另一套组件,后者只显示当前播放时间,前者还显示总时间。若要显示成前者这种模式,即 ‘当前时间/总时间’,可以在初始化播放器选项中配置:var myPlayer = neplayer(‘my-video’, {controlBar:{ ‘currentTimeDisplay’:true, ’timeDivider’:true, ‘durationDisplay’:true, ‘remainingTimeDisplay’:false}}, function() { console.log(‘播放器初始化完成’);});3、video.js样式修改.video-js{ / 给.video-js设置字体大小以统一各浏览器样式表现,因为video.js采用的是em单位 / font-size: 14px;}.video-js button{ outline: none;}.video-js.vjs-fluid,.video-js.vjs-16-9,.video-js.vjs-4-3{ / 视频占满容器高度 / height: 100%; background-color: #161616;}.vjs-poster{ background-color: #161616;}.video-js .vjs-big-play-button{ / 中间大的播放按钮 / font-size: 2.5em; line-height: 2.3em; height: 2.5em; width: 2.5em; -webkit-border-radius: 2.5em; -moz-border-radius: 2.5em; border-radius: 2.5em; background-color: rgba(115,133,159,.5); border-width: 0.12em; margin-top: -1.25em; margin-left: -1.75em;}.video-js.vjs-paused .vjs-big-play-button{ / 视频暂停时显示播放按钮 / display: block;}.video-js.vjs-error .vjs-big-play-button{ / 视频加载出错时隐藏播放按钮 / display: none;}.vjs-loading-spinner { / 加载圆圈 / font-size: 2.5em; width: 2em; height: 2em; border-radius: 1em; margin-top: -1em; margin-left: -1.5em;}.video-js .vjs-control-bar{ / 控制条默认显示 / display: flex;}.video-js .vjs-time-control{display:block;}.video-js .vjs-remaining-time{display: none;}.vjs-button > .vjs-icon-placeholder:before{ / 控制条所有图标,图标字体大小最好使用px单位,如果使用em,各浏览器表现可能会不大一样 / font-size: 22px; line-height: 1.9;}.video-js .vjs-playback-rate .vjs-playback-rate-value{ line-height: 2.4; font-size: 18px;}/ 进度条背景色 /.video-js .vjs-play-progress{ color: #ffb845; background-color: #ffb845;}.video-js .vjs-progress-control .vjs-mouse-display{ background-color: #ffb845;}.vjs-mouse-display .vjs-time-tooltip{ padding-bottom: 6px; background-color: #ffb845;}.video-js .vjs-play-progress .vjs-time-tooltip{ display: none!important;}4、动态切换视频<script> var data = { src: ‘xxx.mp4’, type: ‘video/mp4’ }; var player = videojs(‘myVideo’, {…}); player.pause(); player.src(data); player.load(data); // 动态切换poster player.posterImage.setSrc(‘xxx.jpg’); player.play(); // 销毁videojs //player.dispose();</script>5、设置语言5.1传统形式开发对于使用<script>标签形式的方式引入video.js,只需要在页面中引入你需要的语言包即可<script src="//example.com/path/to/lang/es.js"></script><script src="//example.com/path/to/lang/zh-CN.js"></script><script src="//example.com/path/to/lang/zh-TW.js"></script><script>var player = videojs(‘myVideo’, { language: ‘zh-CN’ // 初始化时设置语言,立即生效});/ 动态切换语言 使用这种方式进行动态切换不会立即生效,必须有所操作后才会生效。如播放按钮,必须点击一次播放按钮后播放按钮的提示文字才会改变 ///player.language(‘zh-TW’);</script>5.2、vue开发import Video from ‘video.js’/ 不能直接引入js,否则会报错:videojs is not defined import ‘video.js/dist/lang/zh-CN.js’ */import video_zhCN from ‘video.js/dist/lang/zh-CN.json’import video_en from ‘video.js/dist/lang/en.json’import ‘video.js/dist/video-js.css’Video.addLanguage(‘zh-CN’, video_zhCN);Video.addLanguage(’en’, video_en);6、未解决的问题控制条的高级自定义,如图中的进度条及时间在上面,播放按钮、上一个视频、下一个视频,设置及音量在下面这种控件该如何实现?如有知道实现这种高级自定义控制条方式的大神请在评论区留下您的代码7、参考文章视频云web播放器样式和组件自定义Video.js 踩坑简单入门免费视频播放器videojs中文教程 ...

April 18, 2019 · 2 min · jiezi

2019年前端趋势分析

2018年TypeScript 全面开花,GraphQL 蠢蠢欲动,WebAssembly 更是打开了浏览器上多语言的大门。所有这一切跟现在的前端有哪些关系呢?下面小编来分享一下1.三大框架标准化有朋友吐槽:“Vue 的特点就是上手快,初期相当好用,但如果接手一个别人写的 Vue 项目,再和 React 对比一下,你会感谢 React 的”。但当 Vue 3.0 发布之后,估计他就不会这样说了。因为 Vue 3 的 Class API 和 React 的写法几乎是一模一样的,这个改动不是 Proxy 和 TypeScript,而是支持原生 Class 的写法。你用 Class 来写,那代码和 React 写法几乎是一模一样的!import Vue from ‘vue’class App extends Vue.Component { count = 0 up() { this.count++ } down() { this.count– } render() { return ( <div> <h1>{this.count}</h1> <button onClick={() => this.up()}>+</button> <button onClick={() => this.down()}>-</button> </div> ) }}Vue.render(<App />, document.body as HTMLElement)从上面的讨论可以看出,前端三大框架已经趋于平稳化、标准化,在我看来未来是 二.新技术和新概念1、GraphQL 、PWA 、WebAssemblyGraphQL已被GitHub等技术领导者采用。然而,它并没有像一些预测的那样快速地起飞。据JS状态调查显示,只有1/5的前端开发人员使用过GraphQL,但是有惊人的62.5%的开发人员已经听说过它并希望使用它。PWA和 WebAssembly这两个东西,如果你们现在还不懂或者没接触没关系,我会出一系列教程,我们一起学,持续关注北妈就好。因为这个以后,会越来越流行,只不过现在还不重要。2、各种CLI工具封装众所周知,要跟上最新的库,正确配置应用程序并做出正确的架构决策,这可能会让人感到筋疲力尽。这种痛苦催生了管理工具的CLI包的创建,允许开发人员专注于应用程序和业务逻辑。大家熟知和不熟知的 流行的框架包括 Next.js(SSR for React),Create-React-App(客户端React),Nuxt.js(SSR for Vue),Vue CLI(客户端) -side Vue),React Native的Expo CLI,默认情况下使用Angular3、静态站点话题 重新兴起随着JavaScript革命的发生,每个人都喜欢学习最新最好的图书馆,但现在事情已经解决,我们已经意识到并非每个网站都需要是一个复杂的单页面应用程序(SPA)。这导致了静态站点生成器的增长。三.TypeScript可能是JavaScript的未来JavaScript因没有静态类型变量而受到批评。试图纠正这个问题的两个主要库是TypeScript和Flow,但TypeScript看起来是最受欢迎的。事实上,在Stack Overflow调查中,TypeScript的评分高于JavaScript本身,为67%,而最受喜爱的语言为61.9%。根据JS的状态调查,超过80%的开发人员希望使用TS或已经使用它并享受它。对于Flow,只有34%的开发人员正在使用它或想要使用它。根据所有迹象,TypeScript是JS中静态类型的首选解决方案,许多人选择使用普通的JavaScript。在2018年,TS的npm下载数量大幅增长,而Flow保持不变。 四.移动端Flutter 是 Google 推出的帮助开发者在 Android 和 iOS 两个平台,同时开发高质量原生应用的全新移动 UI 框架,和 React-native/Weex 一样支持热更新。Flutter 使用 Google 自己家的 Dart 语言编写,刚好今年 Dart 2 也正式发布,不知道二者之间是否有关联。目前 Dart 主攻 Flutter 和 Web 两块,同时提供了 pub 包管理器,俨然是一门全新的语言,学习成本有些高。反观 TypeScript 就非常容易被接受,基于 npm 生态,兼容 ES 语法,因此,2019 年对 Dart 我还是会持观望态度。除了不喜欢 Dart 外,Flutter 的其他方面都很好,在移动端现在强运营的背景下,支持热更新是必备能力。关于 Weex,一边骂一边用,很无奈的一种状态。Weex 本身是好东西,捐给了 Apache,目前在孵化中,会有一个不错的未来。但社区维护的非常差,问题 issue 不及时,文档不更新。如果公司没有架构组,还是比较难搞定的。不过也有很多不错的案例,比如 2018 年优酷双十一活动就是使用 Weex 开发的,效果非常不错。通过自建的可视化活动搭建平台,能够非常高效的完成开发,结合 App 内的缓存,整体效果比 H5 好的多。我对 Weex 的看法是,以前 Weex 只是解决 H5 渲染效率的问题,但如今强运营的背景,使得 Weex 承载了非常多的内容,比如动画、游戏甚至是图形图像处理等。可以看到,未来 Weex 还会战略性的增加。更多精彩资讯或者获取1000集前端视频可以加我 3252897743 ...

April 18, 2019 · 1 min · jiezi

css animation 常用的动画效果

最近项目需要,需要写一些动画效果,然后对animation的知识巩固了一下。animationanimation-name 需要绑定到选择器的 keyframe 名称animation-duration 完成动画所需要的时间animation-delay 设置延长时间animation-timing-function 动画的运动速度linear 动画从头到尾的速度是相同的。 ease 默认。动画以低速开始,然后加快,在结束前变慢。 ease-in 动画以低速开始。ease-out 动画以低速结束。ease-in-out 动画以低速开始和结束。cubic-bezier(n,n,n,n) 在 cubic-bezier 函数中自己的值。可能的值是从 0 到 1 的数值。animation-iteration-count 动画播放的次数infinite 规定动画应该无限次播放。animation-direction 轮流反向播放动画normal 默认值。动画应该正常播放。alternate 动画应该轮流反向播放。— 好吧 这个就介绍到这里吧 如果还有什么疑问可以自己去了解一下1.animation1<div class=“spinner”> <div class=“rect1”></div> <div class=“rect2”></div> <div class=“rect3”></div> <div class=“rect4”></div> <div class=“rect5”></div></div><style>.spinner { margin: 100px auto; width: 50px; height: 60px; text-align: center; font-size: 10px;} .spinner > div { background-color: #67CF22; height: 100%; width: 6px; display: inline-block; -webkit-animation: stretchdelay 1.2s infinite ease-in-out; animation: stretchdelay 1.2s infinite ease-in-out;} .spinner .rect2 { -webkit-animation-delay: -1.1s; animation-delay: -1.1s;} .spinner .rect3 { -webkit-animation-delay: -1.0s; animation-delay: -1.0s;} .spinner .rect4 { -webkit-animation-delay: -0.9s; animation-delay: -0.9s;} .spinner .rect5 { -webkit-animation-delay: -0.8s; animation-delay: -0.8s;} @-webkit-keyframes stretchdelay { 0%, 40%, 100% { -webkit-transform: scaleY(0.4) } 20% { -webkit-transform: scaleY(1.0) }} @keyframes stretchdelay { 0%, 40%, 100% { transform: scaleY(0.4); -webkit-transform: scaleY(0.4); } 20% { transform: scaleY(1.0); -webkit-transform: scaleY(1.0); }}</style>2.animation2<div class=“spinner”></div><style>.spinner { width: 60px; height: 60px; background-color: #67CF22; margin: 100px auto; -webkit-animation: rotateplane 1.2s infinite ease-in-out; animation: rotateplane 1.2s infinite ease-in-out;} @-webkit-keyframes rotateplane { 0% { -webkit-transform: perspective(120px) } 50% { -webkit-transform: perspective(120px) rotateY(180deg) } 100% { -webkit-transform: perspective(120px) rotateY(180deg) rotateX(180deg) }} @keyframes rotateplane { 0% { transform: perspective(120px) rotateX(0deg) rotateY(0deg); -webkit-transform: perspective(120px) rotateX(0deg) rotateY(0deg) } 50% { transform: perspective(120px) rotateX(-180.1deg) rotateY(0deg); -webkit-transform: perspective(120px) rotateX(-180.1deg) rotateY(0deg) } 100% { transform: perspective(120px) rotateX(-180deg) rotateY(-179.9deg); -webkit-transform: perspective(120px) rotateX(-180deg) rotateY(-179.9deg); }}</style>3.animation3<div class=“spinner”> <div class=“double-bounce1”></div> <div class=“double-bounce2”></div></div><style>.spinner { width: 60px; height: 60px; position: relative; margin: 100px auto;} .double-bounce1, .double-bounce2 { width: 100%; height: 100%; border-radius: 50%; background-color: #67CF22; opacity: 0.6; position: absolute; top: 0; left: 0; -webkit-animation: bounce 2.0s infinite ease-in-out; animation: bounce 2.0s infinite ease-in-out;} .double-bounce2 { -webkit-animation-delay: -1.0s; animation-delay: -1.0s;} @-webkit-keyframes bounce { 0%, 100% { -webkit-transform: scale(0.0) } 50% { -webkit-transform: scale(1.0) }} @keyframes bounce { 0%, 100% { transform: scale(0.0); -webkit-transform: scale(0.0); } 50% { transform: scale(1.0); -webkit-transform: scale(1.0); }}</style>4.animation4<div class=“spinner”> <div class=“dot1”></div> <div class=“dot2”></div></div><style>.spinner { margin: 100px auto; width: 90px; height: 90px; position: relative; text-align: center; -webkit-animation: rotate 2.0s infinite linear; animation: rotate 2.0s infinite linear;} .dot1, .dot2 { width: 60%; height: 60%; display: inline-block; position: absolute; top: 0; background-color: #67CF22; border-radius: 100%; -webkit-animation: bounce 2.0s infinite ease-in-out; animation: bounce 2.0s infinite ease-in-out;} .dot2 { top: auto; bottom: 0px; -webkit-animation-delay: -1.0s; animation-delay: -1.0s;} @-webkit-keyframes rotate { 100% { -webkit-transform: rotate(360deg) }}@keyframes rotate { 100% { transform: rotate(360deg); -webkit-transform: rotate(360deg) }} @-webkit-keyframes bounce { 0%, 100% { -webkit-transform: scale(0.0) } 50% { -webkit-transform: scale(1.0) }} @keyframes bounce { 0%, 100% { transform: scale(0.0); -webkit-transform: scale(0.0); } 50% { transform: scale(1.0); -webkit-transform: scale(1.0); }}</style>5.animation5<div class=“spinner”> <div class=“bounce1”></div> <div class=“bounce2”></div> <div class=“bounce3”></div></div><style>.spinner { margin: 100px auto 0; width: 150px; text-align: center;} .spinner > div { width: 30px; height: 30px; background-color: #67CF22; border-radius: 100%; display: inline-block; -webkit-animation: bouncedelay 1.4s infinite ease-in-out; animation: bouncedelay 1.4s infinite ease-in-out; /* Prevent first frame from flickering when animation starts */ -webkit-animation-fill-mode: both; animation-fill-mode: both;} .spinner .bounce1 { -webkit-animation-delay: -0.32s; animation-delay: -0.32s;} .spinner .bounce2 { -webkit-animation-delay: -0.16s; animation-delay: -0.16s;} @-webkit-keyframes bouncedelay { 0%, 80%, 100% { -webkit-transform: scale(0.0) } 40% { -webkit-transform: scale(1.0) }} @keyframes bouncedelay { 0%, 80%, 100% { transform: scale(0.0); -webkit-transform: scale(0.0); } 40% { transform: scale(1.0); -webkit-transform: scale(1.0); }}</style> ...

April 18, 2019 · 3 min · jiezi

匹配手机号码及运营商校验

最新手机号正则,(无法保证时效性,注意 及时更新)移动:134、135、136、137、138、139、147、148、 150、151、152、157、158、159、172、178、182、183、184、187、188、198,联通:130、131、132、145、146、155、156、166、171、175、176、185、186,电信:133、149、153、173、174、177、180、181、189、199,全球星:1349,虚拟运营商电信:1700、1701、1702移动:1703、1705、1706联通:1704、1707、1708、1709匹配手机号码的正则表达式:^((13[0-9])|(14[5,7])|(15[0-3,5-9])|(17[0,1,3,5-8])|(18[0-9])|166|198|199|(147))\d{8}$^(13[0-9]|14[579]|15[0-3,5-9]|16[6]|17[0135678]|18[0-9]|19[89])\d{8}$^1([38][0-9]|4[579]|5[0-3,5-9]|6[6]|7[0135678]|9[89])\d{8}$ 区分运营商(摘自:原文:https://blog.csdn.net/qq_3571… )//移动:134(0 - 8) 、135、136、137、138、139、147、150、151、152、157、158、159、178、182、183、184、187、188、198 //联通:130、131、132、145、155、156、175、176、185、186、166//电信:133、153、173、177、180、181、189、199 /^((134)|(135)|(136)|(137)|(138)|(139)|(147)|(150)|(151)|(152)|(157)|(158)|(159)|(178)|(182)|(183)|(184)|(187)|(188)|(198))\d{8}$/g;/^((130)|(131)|(132)|(155)|(156)|(145)|(185)|(186)|(176)|(175)|(170)|(171)|(166))\d{8}$/g;/^((133)|(153)|(173)|(177)|(180)|(181)|(189)|(199))\d{8}$/g;简写:/^((13[456789])|(147)|(15[012589])|(178)|(18[2348])|(198))\d{8}$/g;/^((13[012])|(145])|(15[56])|(166])|(17[0156])|(18[56]))\d{8}$/g;/^((133)|(153)|(17[37])|(18[019])|(199))\d{8}$/g;

April 18, 2019 · 1 min · jiezi

靓号检测

靓号检测:(无法保证时效性,注意 及时更新)主要可以检测连号(正连 12345、倒连65432)、AABB号、手机号码、日期号(生日号、年度号)、ABBCABB号,3位以上重复号。更多类型号码检测可以根据以下表达式改造。匹配6位顺增 regex.Pattern = “(?:0(?=1)|1(?=2)|2(?=3)|3(?=4)|4(?=5)|5(?=6)|6(?=7)|7(?=8)|8(?=9)){5}d"匹配3位以上顺增 regex.Pattern = “(?:0(?=1)|1(?=2)|2(?=3)|3(?=4)|4(?=5)|5(?=6)|6(?=7)|7(?=8)|8(?=9)){3,}+d匹配6位顺降 regex.Pattern = “(?:9(?=8)|8(?=7)|7(?=6)|6(?=5)|5(?=4)|4(?=3)|3(?=2)|2(?=1)|1(?=0)){5}d"匹配6位顺增或顺降 regex.Pattern = “(?:(?:0(?=1)|1(?=2)|2(?=3)|3(?=4)|4(?=5)|5(?=6)|6(?=7)|7(?=8)|8(?=9)){5}|(?:9(?=8)|8(?=7)|7(?=6)|6(?=5)|5(?=4)|4(?=3)|3(?=2)|2(?=1)|1(?=0)){5})d"匹配4-9位连续的数字 (?:(?:0(?=1)|1(?=2)|2(?=3)|3(?=4)|4(?=5)|5(?=6)|6(?=7)|7(?=8)|8(?=9)){3,}|(?:9(?=8)|8(?=7)|7(?=6)|6(?=5)|5(?=4)|4(?=3)|3(?=2)|2(?=1)|1(?=0)){3,})d匹配3位以上的重复数字 ([d])1{2,}匹配日期类型的数字 (19|20)[d]{2}(1[0-2]|0?[1-9])(31|2[0-9]|1[0-9]|0?[0-9])手机号码类 (13[0-9]|15[0-9]|18[0-9])([d]{2,4}){2}匹配33111类型的 ([d])1{1,}([d])2{2,}匹配5331533类型的 (([d]){1,}([d]){1,})1{1,}匹配22334,123355类型的 ([d])1{1,}([d])2{1,}部分摘自 https://segmentfault.com/q/1010000018046739?utm_source=tag-newest https://www.cnblogs.com/hdl217/p/3503409.html

April 18, 2019 · 1 min · jiezi

CSS 实现三角形,非 Hack

写过 HTML upvote arrow(向上箭头),speech bubble(对话气泡)或其他类似的尖角元素的人都知道,为了创建一个纯 CSS 实现的三角形,必须使用某些 Hack。最流行的两种方式是通过 边框实现,或 Unicode 字符。不得不说,这些 CSS Hack 都非常聪明,但它们却算不上好的解决方案,代码不优雅且不够灵活。例如,我们无法在三角形上使用背景图片,因为边框和字符只能使用颜色。译注: speech bubble(对话气泡)如下图:使用 Clip-pathClip-path 是 CSS 规范中新属性中的一个,它能让我们只显示元素的一部分并隐藏其余部分。其工作原理如下:假设我们有一个普通的矩形 div 元素。你可以在下面的编辑器中单击 Run 运行并查看渲染后的 HTML。(译注:原文内有在线代码编辑器,此处仅贴出代码,可自行 copy 测试。)div { width: 200px; height: 200px; background: url(https://goo.gl/BeSyyD);}<div></div>为了实现三角形,我们需要使用 polygon() 函数。其参数为以逗号分隔的平面坐标点,这些坐标点定义了我们的剪切遮罩的形状。三角形 = 3个点。可以试着更改值并查看形状是如何变化的。div { width: 200px; height: 200px; background: url(https://goo.gl/BeSyyD); /* 三个点分别为:中上的点,左下的点,右下的点 */ clip-path: polygon(50% 0, 0 100%, 100% 100%);}<div></div>创建的路径中的所有内容都会保留,而路径外内容会被隐藏。通过这种方式,我们不仅可以制作三角形,还可以制作出各种不规则的形状,且这些形状可像普通的 CSS 块一样。(译注:即可以正常运用 CSS 属性在这些形状上)这种方法唯一的缺点就是是我们需要自行计算点的坐标来得到一个好看的三角形。不过,它比使用边框或▲(译注:正三角的 Unicode 字符)更好。浏览器支持如果你查看 clip-path 的 caniuse 页面,一开始你发现貌似兼容性非常不好,但事实上,该属性在 Chrome 中能正常工作,且不需要前缀,在 Safari 中需要加 -webkit- 前缀。Firefox 53 版本以上可用。IE / Edge 一贯的不支持,未来也许会支持。关于 clip-path 属性有很多小技巧,包括 SVG 的“奇幻”用法。了解更多,请查看下面的链接。MDN 上的 clip-path - 链接Codrops 上的深入 clip-path 教程 - 链接Clippy, 一个 clip-path 生成器 - 链接 ...

April 18, 2019 · 1 min · jiezi

vue项目history模式下,发布在服务器上404的问题

有些公司部署项目会有同一个域名部署多个项目的情况,故在服务器上建立多个文件夹。一般放在根目录下router的mode使用history,多个项目时要用一般模式。1、去掉history,2、修改publicPath详细见项目:https://github.com/bailichen/…

April 18, 2019 · 1 min · jiezi

JavaScript检查颜色冲突

注意:本文非原创,而是翻译国外大师文章,布赖恩苏达。布赖恩苏达是一位信息大师,每天都在努力使网络变得更加美好。自从90年代中期发现互联网以来,Brian Suda已经花了很多时间与之相关联。他自己的一小部分互联网是http://suda.co.uk,他的许多过去的项目和疯狂的想法都可以找到。原文题目是:计算颜色对比度,但是我想业余的说法比较通俗易懂,也方便搜索引擎收录。废话少说,进入正题。问题出现的背景某些网站和服务允许您通过上传图片,更改背景颜色或设计的其他方面来自定义您的个人资料。作为客户,此个性化将Web应用程序转换为您存储数据的小窝。作为设计师,让您的客户自由地控制布局和设计是一个可怕的前景。那么设计用于漂亮的白色背景的所有股票文本和图像会发生什么?即便是Mac也只允许您选择OS,蓝色或石墨两种颜色!除非您灵活并了解如何找到最大色彩对比,否则开放自定义网站配色方案的能力可能会导致灾难。在本文中,我将向您介绍两个简单的公式,以确定您是否应该使用白色或黑色文本,具体取决于背景的颜色。方程式易于实现并产生类似的结果。这不是一个更好的问题,而是你使用一个更好的事实!这样,即使您的客户选择了最疯狂的Geocities配色方案,至少您的文本仍然可读。让我们来看看各种可能的颜色。也许这些是预先制作的配色方案,公司颜色或从图像中提取。现在我们有了这些潜在的背景颜色及其十六进制值,我们需要找出相应的文本是白色还是黑色,基于哪个具有更高的对比度,因此提供最佳的可读性。这可以在运行时使用JavaScript完成,也可以在HTML服务之前在后端完成。我想要比较两个函数。首先,我称之为“50%”。它取十六进制值并将其与纯黑色和纯白色之间的值进行比较。如果十六进制值小于一半,意味着它位于光谱的较暗侧,则返回白色作为文本颜色。如果结果大于一半,则它位于光谱较轻的一侧,并返回黑色作为文本值。在PHP中:function getContrast50($hexcolor){ return (hexdec($hexcolor) > 0xffffff/2) ? ‘black’:‘white’;}在JavaScript中:function getContrast50(hexcolor){ return (parseInt(hexcolor, 16) > 0xffffff/2) ? ‘black’:‘white’;}它没有那么简单!该函数将六字符十六进制颜色转换为整数,并将其与纯白色的整数值的一半进行比较。该功能易于记忆,但在理解我们如何感知频谱的某些部分时却很幼稚。不同的波长对对比度有更大或更小的影响。第二个等式称为’ YIQ ‘,因为它将RGB颜色空间转换为YIQ,这考虑了其组成部分的不同影响。同样,等式返回白色或黑色,并且它也很容易实现。在PHP中:function getContrastYIQ($hexcolor){ $r = hexdec(substr($hexcolor,0,2)); $g = hexdec(substr($hexcolor,2,2)); $b = hexdec(substr($hexcolor,4,2)); $yiq = (($r299)+($g587)+($b114))/1000; return ($yiq >= 128) ? ‘black’ : ‘white’;}在JavaScript中:function getContrastYIQ(hexcolor){ var r = parseInt(hexcolor.substr(0,2),16); var g = parseInt(hexcolor.substr(2,2),16); var b = parseInt(hexcolor.substr(4,2),16); var yiq = ((r299)+(g587)+(b114))/1000; return (yiq >= 128) ? ‘black’ : ‘white’;}您首先会注意到我们已将十六进制值分解为单独的RGB值。这很重要,因为这些通道中的每一个都根据其视觉影响进行缩放。一旦所有内容都被缩放和标准化,它将在0到255之间的范围内。就像之前的“50%”函数一样,我们现在需要检查输入是在中途还是在中途。根据该值的位置,我们将返回相应的最高对比色。就是这样:两个简单的对比度方程式,可以很好地确定最佳可读性。如果您有兴趣了解更多,W3C有一些关于颜色对比的文档,以及如何确定任何两种颜色之间是否有足够的对比度。这对于可访问性非常重要,以确保文本和链接颜色与背景之间有足够的对比度。Kevin Hale在Particletree上也有一篇很棒的文章,讲述了他选择光明或黑暗主题的经历。为了完善它,Jonathan Snook创建了一个颜色对比度选择器,允许您使用RGB滑块来获取YIQ,对比度和其他值。这样你就可以快速摆弄旋钮,找到合适的平衡点。比较结果让我们重温一下我们的颜色方案,看看基于这两个方程推荐哪种文本颜色可以获得最大对比度。如果我们使用简单的'50%‘对比度函数,我们可以看到它建议黑色除了第二行上的深绿色和紫色之外的所有颜色。一般来说,等式感觉颜色很浅,黑色是文本的更好选择。更复杂的’ YIQ ‘功能,加权颜色,建议略有不同。对于非常暗的颜色,仍然建议使用白色文字,但有一些惊喜。红色和粉红色值显示白色文本而不是黑色。该等式考虑了红色值的权重,并确定色调足够暗以使白色文本显示最大对比度。如您所见,两种对比度算法在大多数情况下都是一致的。在某些情况下,它们会发生冲突,但总的来说,您可以使用您喜欢的等式。我不认为这是一个主要问题,如果一些边缘情况颜色与另一种颜色形成对比,它们仍然非常易读。现在让我们看一些常见的颜色,然后看看这两个函数如何比较。您可以很快发现它们在整个范围内都做得非常好。在前几种灰色阴影中,白色和黑色的对比是有意义的,但是当我们测试光谱中的其他颜色时,我们确实会出现意想不到的偏差。纯红色#FF0000有一个触发器。这是由于’ YIQ ‘功能如何对RGB部分进行加权。虽然你可能个人喜欢一种风格而不是另一种风格,但两者都是合理的。在第二轮的颜色中,我们更深入地了解光谱,走出人迹罕至的轨道。同样,大多数情况下,对比算法是同步的,但每隔一段时间他们就不同意了。您可以选择自己喜欢的内容,但两者都不可读。结论颜色对比很重要,特别是如果你放弃所有控制并采取不干涉的设计方法。通过使颜色之间的对比度尽可能高来选择智能默认值非常重要。这使您的客户更容易阅读,增加可访问性,通常只是更容易看到。当然,还有很多其他的方程来确定对比度; 最重要的是你选择一个并将其实施到你的系统中。所以,继续在你的设计中试验颜色。您现在知道保证您的文本在任何情况下都是最易读的是多么容易。原文链接:https://24ways.org/2010/calcu… ...

April 18, 2019 · 1 min · jiezi

Web前端工程师需要掌握的8个方面

Web前端开发工程师一直都是热门的很受人们欢迎的岗位,因此参加HTML5培训学习Web前端开发的人一直都不少,本篇文章小编和喜欢HTML5开发技术的小伙伴们分享一下Web前端工程师需要掌握的8个方面,对此感兴趣的小伙伴就随小编来了解一下吧。如果大家如果在自学遇到困难,想找一个前端的学习环境,可以加入我们的前端学习圈,点击我加入吧,会节约很多时间,减少很多在学习中遇到的难题。Web前端工程师需要掌握的8个方面扣丁学堂HTML5培训Web前端工程师任职需要掌握的8个方面:1、网页的基本结构(HTML + CSS)HTML是一种标记语言,而不是编程语言,最基本是标签是和,CSS是用来定义如何显示HTML元素的。对 HTML+CSS很容易入门,但很多人不够深入,举几个例子: 标签是作什么用的?margin-left与left有什么区别,应该在什么情况下使用?再出个DIV+CSS布局问题:一个宽度不确定的DIV里面放三个水平对齐的DIV,左右两个DIV宽度固定为150px,中间那个DIV充满剩余的宽度。如果这些问题你目前还不知道,对那个布局问题几分钟内不能解决,说明你对HTML+CSS还不够深入。2、浏览器是怎么展现网页的不同内核的浏览器对网页的渲染是不一样的,目前浏览器都有客户端调试工具,在做web性能优化时,对浏览器渲染及细节要进一步了解。说个比较有用的知识点:目前浏览器并行加载的上限是6,老版本的浏览器会有所不同。3、网页的生命周期不同的web框架下,页面的生命周期会有所不同,大体还是一样:客户端发送GET请求,服务器返回相应页面,客户端完成操作及数据,然后POST给服务器。一定要对数据的传递(前台与后台,页面之间)的细节了然于心。4、DHTML DOM BOM Javascript AJAX这是Web前端开发的重中之中,大多数时候我们都在和他们打交道。说几个注意点:javascript是单线程编程,所谓的javascript异步编程只不过是计划在未来的某个时间上执行相应事件而已;详细了解DOM事件机制;客户端存储(HTML5中增加了localStorage和 sessionStorage);javascript不像服务器端语言那样严谨,调试不是很方便,所以一开始要养成严谨的javascript编辑习惯;javascript很强大很灵活,不要幻想短时间内熟练(更别说精通)它,并写些框架、类库,初始阶段还是先用熟练已成熟的框架(比如 jquery)当入门;一定要熟练使用客户端调试工具。5、服务器端语言开发经验,PS切图技术Web前端开发介于设计与开发中间,所以两端的东西都得懂点。编辑语言是相通的,之前编写过服务器语言,对学习javascript是十分有益的,从图片转成静态HTML页面,少不了PS切图技术。6、浏览器的兼容性由于历史原因 ,浏览器的兼容性一直都折磨web前端工程师的地方,虽然有W3组织,并制定了一些规范,虽然浏览器产商都正在努力改进并接近其规范,但现实网络环境中各种内核、各种版本的浏览器都有一席之地。解决浏览器兼容性靠经验积累。7、快速学习能力和主动学习意愿web前端的发展很快,从事这一行业一定要有快速学习能力和主动学习意愿,这样才能适应web产品的要求。在web前端领域没有绝对的是与非,解决一个问题的方法有很多,但我们要找到一个更合适的方法,找到一个更合适的方法需要经验作积累,总之web前端入门容易,想熟练很难,需要更多的主动学习意愿。据扣丁学堂web前端开发讲师经验,优秀的web前端工程师同时也应该具备快速学习能力,推动Web发展的技术并不是静止不动的。如果没有快速学习能力,你就跟不上Web发展的步伐。你必须不断提升自己,不断学习新技术、新模式。Web的明天与今天必将有天壤之别,而你的工作就是要搞清楚如何通过自己的Web应用程序来体现这种翻天覆地的变化,既然踏上了web前端开发之路,那就坚强地走下去。以上就是扣丁学堂HTML5在线学习小编给大家分享的Web前端工程师需要掌握的8个方面,希望对小伙伴们有所帮助,想要了解更多内容的小伙伴可以登录扣丁学堂官网咨询。想要学好HTML5开发小编给大家推荐口碑良好的扣丁学堂,扣丁学堂有专业老师制定的HTML5学习路线图辅助学员学习,此外还有与时俱进的HTML5课程体系和HTML5视频教程供大家学习,想要学好HTML5开发技术的小伙伴快快行动吧。H5进阶课程:https://ke.qq.com/course/3873…【扫码进入前端H5架构师进阶VIP体验课】H5基础课程:https://ke.qq.com/course/3205…【扫码进入HTML5前端开发VIP免费公开课】

April 18, 2019 · 1 min · jiezi

不常用但很好用的标签

虽然 html5 出了很多新标签,但是自己工作中用到的除了 nav,header 等跟 div 类似的标签以外,其他的并没怎么用过,所以看了下菜鸟教程里面,大体浏览的一下已有的标签,发现很多有趣的标签,现在总结一下,部分支持性比较差的就不介绍了,比如 <details> 标签,看起来很不错,但是显示只有 Chrome 支持,所以就不介绍了,有兴趣的可以去看看。因为不知道怎么在文章里展示代码效果,所以点这里看看链接描述标识类abbr<abbr>标签指示简称或缩写,比如 “WWW” 或 “NATO”。通过对缩写进行标记,您能够为浏览器、拼写检查和搜索引擎提供有用的信息。全称写在 title 属性里,在悬浮时即可显示内容。title 是 html 的全局属性,这意味着你用别的标签,然后添加 title 属性,也会有同样效果,不过既然出了此标签,并且浏览器和搜索引擎对此进行处理,所以遇到时,用它还是不错的。<p> <abbr title=“投币,点赞,转发”>素质三连</abbr> 是每位读者应有的态度</p>area 和 map当初在 DW 里看到过这个功能,不过自己没用过,可以设置图片可点击区域,然后进行链接。比如点击下图的中间区域。会跳转新的图片。<img src=“https://s2.ax1x.com/2019/04/17/AzwvnK.png" width=“500px” alt=“AzwvnK.png” border=“0” usemap="#eye”/><map name=“eye” id=“eye”><area shape=“circle” target="_blank" coords=“250,150,50” href =“https://s2.ax1x.com/2019/04/17/Azwz7D.jpg" alt=“Venus” /></map>bdo<bdo>标签用来指示文本的顺序,从左到右 dir=“ltr”)还是右往左(dir=“rtl”),这样就不用去处理字符串颠倒了。<bdo dir=“ltr”>上海自来</bdo>,水,<bdo dir=“rtl”>上海自来</bdo>hr<hr> 标签在 HTML 页面中创建一条水平线。这没什么可说的,不过现在都不怎么推荐了,但是各浏览器还都是支持的,比用 div 的边框还是能省不少代码的mark<mark> 标签定义带有记号的文本。五千六百万啊,四舍五入就是 <mark>一个亿</mark>啊meter 和 progress<meter> 标签定义已知范围或分数值内的标量测量。也被称为 gauge(尺度)。例子:磁盘用量、查询结果的相关性,等等。<progress> 标签不适合用来表示度量衡(例如,磁盘空间使用情况或查询结果)。我的理解就是<meter>用来表示那些有计量单位的,比如温度,剩余空间。而<progress>是用来那些任务的进度,比如下载上传等。value 属性如果不设置 max 值得话,则最大值为 1c:盘<meter value=“10” max=“50”>10G</meter><br />迅雷下载<progress value=“0.999”>99.9%</progress>ruby rt rpruby 元素由一个或多个字符(需要一个解释/发音)和一个提供该信息的 rt 元素组成,还包括可选的 rp 元素,定义当浏览器不支持 “ruby” 元素时显示的内容。我的理解是 ruby 是字,rt 是注音,rp 是浏览器不支持时显示的内容。<ruby>福<rt>hu</rt></ruby>建人sub 和 sup包含在 <sub>和 <sup>标签和其结束标签中的内容将会以当前文本流中字符高度的一半来显示,但是与当前文本流中文字的字体和字号都是一样的。在数学等式、科学符号、化学公式和脚注等比较好用,sup 也可以用来写通知的小红点。H<sub>2</sub>O是水,log<sub>5</sub><sup>25</sup>=2<span style=“border:1px solid “>赞<sup style=“background:red;">22</sup></span>wbr如果单词太长,或者您担心浏览器会在错误的位置换行,那么您可以使用 <wbr> 元素来添加 Word Break Opportunity(单词换行时机)。可以看到有 wbr 标签包围的 http 会换行。<p style=“width:100px;border:1px solid”>ssssssssssssssss<wbr />Http<wbr /></p><p style=“width:100px;border:1px solid”>ssssssssssssssssHttp</p>表格类表格里面不常用但好用的应该数 col 和 colgroun 标签,他们可以用来定义对应列的属性。再此我把表格相关的元素写在一起。col 的 align 属性支持比较差,所以推荐用 css 处理thead、tfoot 以及 tbody 元素使您有能力对表格中的行进行分组。当您创建某个表格时,您也许希望拥有一个标题行,一些带有数据的行,以及位于底部的一个总计行。这种划分使浏览器有能力支持独立于表格标题和页脚的表格正文滚动。当长的表格被打印时,表格的表头和页脚可被打印在包含表格数据的每张页面上。caption、col、colgroup、thead、tbody、tfoot 和 table<table> <caption>九宫</caption> <colgroup> <col></col> <col span=“2” width=“100px”></col> </colgroup> <thead> <tr><th>1</th><th>2</th><th>3</th></tr> </thead> <tbody> <tr><td>4</td><td>5</td><td>6</td></tr> </tbody> <tfoot> <tr><td>7</td><td>8</td><td>9</td> </tr> </tfoot></table>表单类表单这也有许多标签,但是项目中应该多数都不会用浏览器所展示的样式,不过有个 output 标签比较有趣,下面只做一些简单的结构展示<form oninput=“x.value=parseInt(a.value)*10000/(parseInt(b.value)*parseInt(b.value))"> <figure> <figcaption>莫得感情莫得钱的杀手</figcaption> <img src=“https://s2.ax1x.com/2019/04/17/Azl7Y8.jpg" width=“350” height=“234” /> </figure> <fieldset> <legend>健康信息</legend> 体重(kg):0<input type=“range” id=“a” value=“75” max=“250” />250 <br /> 身高(cm):<input type=“number” id=“b” value=“160” max=“250” /><br /> 体重指数:<output name=“x” for=“a b”></output> </fieldset></form>结语还有一些标签没写里面,比如 iframe 相关的,个人感觉用的不是特别多,可能以后会加上吧。 ...

April 18, 2019 · 1 min · jiezi

前端面试必问题答疑(1)

一,前端性能优化有哪些?a) 页面优化方面:1,减少HTTP请求数–设计简化页面–合理设置缓存–资源合并与压缩–css sprites–图片嵌入–Lazy Load Images2,将外部脚本置底3,异步执行inline脚本4,Lazy Load Javascript5,将外链CSS放在HEAD中6,异步请求Callback7,减少不必要的 HTTP跳转8,避免重复的资源请求b)代码优化方面:javascript1,DOM操作–转为数组后再访问–减少Reflow和Repaint2,慎用 with–增加了作用域链长度3,避免使用 eval和 Function–需要将源代码转换成可执行代码4,减少作用域链查找–全局变量在遍历之前用局部变量缓存该变量5,数据访问–将数据放入局部变量–减少对对象以及数组深度查找6,字符串拼接–使用数组的 join方法,少用+号CSS选择符1,实际上浏览器对选择符的解析是从右往左进行的HTML1,了解详细:[https://www.cnblogs.com/xy-milu/p/6091234.html][1]Image压缩1,找找压缩工具:[https://tinypng.com][2]二,关于原型链

April 17, 2019 · 1 min · jiezi

MyBatis 映射器

ps 一个用于生成MyBatis配置文件的插件 mybatis-generator使用方法呢, 是加入maven插件中 然后执行相关命令可以实现自动生成MyBatis配置文件自动映射首先编写无参的javabeanpackage com.ming.MyBatis.POJO;/** * @author ming /public class Role { private int id; private String roleName; private String note; public Role(){ } /* * @param id / public void setId(int id) { this.id = id; } /* * @param roleName / public void setRole_name(String roleName) { this.roleName = roleName; } /* * @param note / public void setNote(String note) { this.note = note; } /* * @return / public int getId() { return id; } /* * @return / public String getRoleName() { return roleName; } /* * @return / public String getNote() { return note; }}然后创建数据库这次使用的是开发环境创建的数据库数据库类型如下编写映射文件<mapper namespace=“com.ming.MyBatis.POJO.RoleMapper”> <select id=“getRole” parameterType=“int” resultType=“com.ming.MyBatis.POJO.Role”> SELECT id, role_name as roleName, note FROM t_role WHERE id = #{id} </select> </mapper>此时结果会自动映射到VO对象中,根据VO对象自动调用set方法,然后进行赋值操作此时DAO层接口 /* * @param id * @return / public Role getRole(int id);传递多个参数如果需要传递多个参数,使用MyBatis提供的Map接口首先新增加DAO层接口 /* * 查询Map * @param params * @return / public List<Role> findRoleByteMap(Map<String, String> params);接着,书写映射文件,传递参数 <select id=“findRoleByteMap” parameterType=“map” resultMap=“roleMap”> SELECT id, role_name, note FROM t_role WHERE role_name LIKE CONCAT(’%’, #{roleName}, ‘%’) AND note LIKE CONCAT(’%’, #{note}, ‘%’) </select>这里呢,定义了一个结果集对于返回的数据,使用typehand进行拦截,将会调用自定义别名的role类 <resultMap type=“role” id=“roleMap”> <!– id为主键映射关系 其中数据库中的id为主键 –> <id column=“id” property=“id” javaType=“int” jdbcType=“INTEGER”/> <!– result为其他基本数据类型和实体类之间的映射 映射关系为role_name 到 roleName之间的映射 数据类型为string到VARCHAR之间的映射关系 –> <result column=“role_name” property=“roleName” javaType=“string” jdbcType=“VARCHAR”/> <!– 这里使用typeHandler表示遇到此处理集的时候,将会执行com.ming.MyBatis.StringTypeHandler –> <result column=“note” property=“note” typeHandler=“com.ming.MyBatis.StringTypeHandler”/> </resultMap>现在的完整文件<?xml version=“1.0” encoding=“UTF-8” ?><!DOCTYPE mapper PUBLIC “-//mybatis.org//DTD Mapper 3.0//EN” “http://mybatis.org/dtd/mybatis-3-mapper.dtd"><!-- 定义接口类 –><mapper namespace=“com.ming.MyBatis.POJO.RoleMapper”> <resultMap type=“role” id=“roleMap”> <!– id为主键映射关系 其中数据库中的id为主键 –> <id column=“id” property=“id” javaType=“int” jdbcType=“INTEGER”/> <!– result为其他基本数据类型和实体类之间的映射 映射关系为role_name 到 roleName之间的映射 数据类型为string到VARCHAR之间的映射关系 –> <result column=“role_name” property=“roleName” javaType=“string” jdbcType=“VARCHAR”/> <!– 这里使用typeHandler表示遇到此处理集的时候,将会执行com.ming.MyBatis.StringTypeHandler –> <result column=“note” property=“note” typeHandler=“com.ming.MyBatis.StringTypeHandler”/> </resultMap> <select id=“getRole” parameterType=“int” resultType=“com.ming.MyBatis.POJO.Role”> SELECT id, role_name as roleName, note FROM t_role WHERE id = #{id} </select> <select id=“findRoleByteMap” parameterType=“map” resultMap=“roleMap”> SELECT id, role_name, note FROM t_role WHERE role_name LIKE CONCAT(’%’, #{roleName}, ‘%’) AND note LIKE CONCAT(’%’, #{note}, ‘%’) </select></mapper><?xml version=“1.0” encoding=“UTF-8” ?><!DOCTYPE configuration PUBLIC “-//mybatis.org//DTD Config 3.0//EN” “http://mybatis.org/dtd/mybatis-3-config.dtd"><configuration> <!– 读取数据库配置文件 –> <properties resource=“db.properties”/> <!– 定义别名 –> <typeAliases> <typeAlias type=“com.ming.MyBatis.POJO.Role” alias=“role”/> </typeAliases> <!– 自定义数据处理 –> <typeHandlers> <typeHandler jdbcType=“VARCHAR” javaType=“string” handler=“com.ming.MyBatis.StringTypeHandler”/> </typeHandlers> <!– 定义数据库信息 –> <environments default=“development”> <environment id=“development”> <!– jdbc事物管理 –> <transactionManager type=“JDBC”/> <!– 数据库链接信息 –> <dataSource type=“POOLED”> <property name=“driver” value="${driver}”/> <property name=“url” value="${url}”/> <property name=“username” value="${username}"/> <property name=“password” value="${password}"/> </dataSource> </environment> </environments> <mappers> <mapper resource=“RoleMapper.xml”/> </mappers></configuration>书写结果展示<%@ page import=“org.apache.ibatis.session.SqlSession” %><%@ page import=“com.ming.Util.SqlSessionFactoryUtil” %><%@ page import=“com.ming.MyBatis.POJO.RoleMapper” %><%@ page import=“com.ming.MyBatis.POJO.Role” %><%@ page import=“java.util.Map” %><%@ page import=“java.util.HashMap” %><%@ page import=“java.util.List” %><%@ page import=“javax.swing.text.html.HTMLDocument” %><%@ page import=“java.util.Iterator” %><html><body><h2>Hello World!</h2><% long startTime = System.currentTimeMillis(); //获取开始时间 SqlSession sqlSession = null; List<Role> role = null; for(int i = 0; i < 10; i++) { try { sqlSession = SqlSessionFactoryUtil.openSqlSesion(); RoleMapper roleMapper = sqlSession.getMapper(RoleMapper.class); Map<String, String> paramsMap = new HashMap<String, String>(); paramsMap.put(“roleName”, “name”); paramsMap.put(“note”, “note”); role = roleMapper.findRoleByteMap(paramsMap); sqlSession.commit(); } catch (Exception e) { e.printStackTrace(); sqlSession.rollback(); } finally { if (sqlSession != null) { sqlSession.close(); } } } long endTime = System.currentTimeMillis(); //获取结束时间%><% Iterator iterator = role.iterator(); while(iterator.hasNext()){ %> <%=((Role)iterator.next()).getNote()%> <% }%></body></html>数据库中大概有一万多条记录,时间较长ps 一万多条list担心内存此时可以在此处输出查询日志,用于进行分析注解传递参数使用param注解传递参数新建一个DAO接口 /* * @param roleName * @param note * @return */ public List<Role> findRoleByteMap1(@Param(“roleName”) String roleName, @Param(“note”) String note);再次编写映射文件,对DAO层和SQL语句进行映射配置 <select id=“findRoleByteMap1” resultMap=“roleMap”> SELECT id, role_name, note FROM t_role WHERE role_name LIKE CONCAT(’%’, #{roleName}, ‘%’) AND note LIKE CONCAT(’%’, #{note}, ‘%’) </select>再次编写展示层<%@ page import=“org.apache.ibatis.session.SqlSession” %><%@ page import=“com.ming.Util.SqlSessionFactoryUtil” %><%@ page import=“com.ming.MyBatis.POJO.RoleMapper” %><%@ page import=“com.ming.MyBatis.POJO.Role” %><%@ page import=“java.util.Map” %><%@ page import=“java.util.HashMap” %><%@ page import=“java.util.List” %><%@ page import=“javax.swing.text.html.HTMLDocument” %><%@ page import=“java.util.Iterator” %><html><body><h2>Hello World!</h2><% long startTime = System.currentTimeMillis(); //获取开始时间 SqlSession sqlSession = null; List<Role> role = null; for(int i = 0; i < 10; i++) { try { sqlSession = SqlSessionFactoryUtil.openSqlSesion(); RoleMapper roleMapper = sqlSession.getMapper(RoleMapper.class); Map<String, String> paramsMap = new HashMap<String, String>(); paramsMap.put(“roleName”, “name”); paramsMap.put(“note”, “note”); role = roleMapper.findRoleByteMap1(“name”, “note”); sqlSession.commit(); } catch (Exception e) { e.printStackTrace(); sqlSession.rollback(); } finally { if (sqlSession != null) { sqlSession.close(); } } } long endTime = System.currentTimeMillis(); //获取结束时间%><% Iterator iterator = role.iterator(); while(iterator.hasNext()){ %> <%=((Role)iterator.next()).getNote()%> <% }%></body></html>运行结果 ...

April 17, 2019 · 3 min · jiezi

关于程序员写好 ppt 的几点总结 - 前端张大胖

背景程序员日常工作中最多的应该是接收需求、编码实现需求。但也有些时候需要做一些非代码的文字工作。比如做述职报告、工作总结等,这些一般的都是通过 ppt 的形式进行展示。近一年我做了几次 ppt,刚开始写 ppt 简直不要太痛苦,真的不如写代码来的简单,每晚熬到深夜但也是收效甚微。后来又写了几次,慢慢的找到了一些感觉,现在就赶紧把这个灵感进行总结并记录下来。(仅个人理解哈)概论当写过几次 ppt 后,现在感觉写 ppt 也不是那么难(可能我想的有点简单)。ppt 其实就包含两个需要我们深度思考的东西,一个是内容,一个是形式。内容即文字-你要表达的东西,另外一个就是形式,形式就是展示形式,也就是我们应该以怎样的美感去展示我们的内容。为什么要美感?其实不是为了自己,而是为了体贴你的观众,用心组织你的内容,用心让内容变得更好看就是对观众的体贴和负责,同时也可以锻炼自己的ppt能力。记得《马原》里我们学过内容和形式的辩证关系(下面这段可以不看哈)。内容是事物存在的基础。同一种内容在不同条件下可以采取不同的形式,同一种形式在不同条件下可以体现不同的内容。内容与形式互相联系、互相制约,在一定条件下可以互相转化。内容决定形式,形式依赖于内容,并随内容的发展而发展。形式对内容的发展起着促进或阻碍的作用。内容活跃,形式相对稳定,两者既相适合又不绝对适合。————马克思主义基本原理那应该怎样确定内容和丰富内容的表现形式呢? 下面就说说我的理解1、结构化内容,切记长篇大论(切记堆字)内容其实就是我们日常工作的一些总结,如果是写成文章的话我们倒是可以把要表达的细节都写上去。但是如果是写 ppt,就要把细节隐藏,简洁明了,突出主题。把自己的内容进行结构化的整理,梳理成大纲。文字太多会丧失美感,降低专业度( 忍住,不要喷)。细节的文字是要在讲ppt的时候说的,倒是可以写到备注里,想不起来了偷偷的瞄几眼。比如完成了什么业绩,学习了哪些技术,个人思考有哪些等,然后把这些再细化一层后就是具体的模块了。最后形成一个简单的树形结构。是否还有下一级模块就看个人的需要了。比如在某个业绩里有一些特别突出的亮点,就可以单独的列出来,在演讲的时候着重的介绍下。2、确定色调网站的UI有基调和配色,PPT也有,为了视觉的舒适和ppt的整体性,配色是必须的。不然后面内容美化的颜色就没有了参考。相信一会儿蓝色一会儿绿色一会儿红色的谁看着都不会舒服。举个栗子整体蓝色整体灰色整体深灰能看到突出的颜色和基调的搭配都是比较自然的,没有冲突。3、美化内容(丰富表现形式,积累素材)这个阶段就好比我们做前端开发,需要用css 来美化页面,其实是一个道理。然而这个展示形式我觉得是最难的,最繁琐的。因为没有现成的素材,总不能把每张 ppt 都搞成双胞胎吧。这个时候我们已经有了结构化的内容和基本色调,现在就要开始写 ppt 了。 这个阶段主要是美化和优化之前的内容,让内容和图形结合展示,同时也是对内容斟酌优化的一个过程。这里的图形指的是形状和图片,形状就是 ppt 里自带的一些形状,图片就是根据我们要表达的内容而确定的。我也只做到了图形搭配阶段,配图就比较麻烦,如果要是能确定关键词也可以,百度搜索即可。具体的展示图形可以用系统自带的或者参考网上模板,主要就是一个打磨和积累素材的过程,用合适的图形组合来展示你的内容。举几个栗子业绩项目的展示自带图形以下是网上的模板完成进度展示自带图形图文结合!表现形式虽然看上去有很多种,但按照每个人的喜好和风格来说其实并不多,主要是自己习惯和喜欢那种风格。然而网上的大部分模板也都是使用图形结合展示,配图的也不多。而配图就要看是否能提炼出关键字或者能够找个一张和当前内容和谐共存的图片。4、ppt 展示形式体验这段可以不看。如果你不是很了解ppt的展示形式,可以多看看网上的模板,对展示形式有个印象。那么自己在丰富自己的ppt 的时候就会有一些感觉了。具体的网站百度找下就可以了,就不发地址了。5、ppt 资源、素材参考网上的模板基本上都是收费的,很早之前我在淘宝买过一堆。里面有很多模板,有需要可以存一下。(我主要是用来找素材,最好不要直接套用,一个怕过时,一个是会影响你原有思路)链接: https://pan.baidu.com/s/189K0… 提取码: ghs5总结写ppt主要有3步:1、结构化内容(确定内容,突出主题,不要堆字)2、确定ppt风格(也就是配色,黄色、蓝色还是什么,突出ppt的整体性)3、美化展示(根据配色进行美化,具体使用什么图形展示)第一次写ppt确实挺麻烦的,但是当自己完整的写完一个后,并且做了大量的优化后,后面你会觉得很简单,但是ppt这个展示形式没有最好只有更好,这个打磨的过程才是最累人的,这个速度也快不了,一两天能搞定一个ppt算是比较快的了,后面做的多了就会提升了。好的内容和表现形式还是通过自己的深度思考得来的,这里做好了还不算完,还有后面的演讲阶段,演讲前需要做几次预演,尽可能的准备充分,把自己要表达的内容表达出来,就更完美了。(本文是大胖自己的理解,大胖用着还行,希望对你有用,也仅仅供参考,肯定还有其他的方法和见解,欢迎留言学习交流。)另外和大家说下我的公众号“重度前端“要改名了,改成“前端张大胖”,感觉这个名字更生动和可爱一些,从一个名字变成了一个人,目前已经提交申请了,过两天就变更了。更多精彩内容欢迎关注,前端张大胖-公众号用通俗的语言记录自己的观点和理解

April 17, 2019 · 1 min · jiezi

前端人员必须知道的三个问题

第一个问题:前端都做哪些事呢,前端都需要哪些技术呢前端发展的三个阶段:初级阶段:(入门)html:常见标签,html5新增的,语义化标签等等css:选择器,背景,文本,链接,列表,盒模型,定位,浮动,css3新增的属性bootstrap:栅格化系统,按钮,表单,导航….javascript: 数据类型,对象,函数,运算符,语句,DOM,选择器,操作,事件…jQuery: 选择器,dom,链式调用,事件,动画进阶阶段:(独当一面)入门:js的面向对象编程, zepto,移动端,响应式,css3d,bootstrap组件,jqueryUI高级数据:面向对象进阶,ajax,json,(后端语言:php)新兴的技术:html5: socket, 离线存储,多媒体,canvas,图像处理,web works,数据存储,跨域。技术拓展:地图开发,微信开发,大数据可视化…后端服务:nodejs:文件系统,路由,mongodb, express….高级阶段:(统筹全局)架构基础:设计模式,MVC, MVVM模块化开发:amd,cmd, commonjs,systemjscss预编译:less, sass,stylus前沿规范:ES5, ES6, ES2016, ES2017, typescript新型框架:backbone, vue, vuex, angular, react, redux, reflux, flux, angular5工程化:打包,编译,校验,资源定位,模块化,指纹,发布… gulp,webpack, fis3….等等第二个问题:前端都有哪些方向,从事哪个方向呢? pc端:基础技术,一些框架移动端:基础,移动端框架nodejs服务器端:了解服务器,以及node的框架游戏端:html5游戏,cavnas大数据可视化:highcharts等等前端架构:设计模式,架构,开发工程化工具,通用组件,通用插件全栈工程师,会前端也会后端,其他语言可能是伪全栈(只能写后台管理系统)混合开发:react nativereact团队,提出了一个理念:多端适配: 前端开发的代码,可以运行在服务器端,pc端,移动端,iso上,android上等等,这样以后所有的端,只需要前端工程师开发了nodejs实现的操作系统总结前端工程师还需要什么切页面:使用photoshop,html,css开发工具:sublime编程语言:javascript,html,css, node…调试工具:firebug,chome, fiddler…兼容性:IE,标准的,移动端android系统浏览器移动终端:html5, css3, 手机,平板等,ios, android等前端框架:vue,angular, react等等web服务器 nodejs, ajax安全:xss,nodejs性能:工程化:打包,编译,压缩,指纹等等,时间…规范:ES5、ES6等等,commonjs规范等,http编程相关知识:数据结构,架构,面向对象,设计模式计算机相关知识:编译原理,操作系统,网络,软件工程。开发流程:语法校验jsLint,项目部署软技能:如何交流,如何开发,哪些角色关注一些前沿社区:html5小组,ECMA…. 第三个问题:怎么算是一位高级前端工程师呢1 前端职位相对于其他行业,有很多岗位2 前端相对于其他行业,工资要高分析这些招聘案例,我们发现,一个合格的高级工程师,应该懂得更多的高级知识点。在工作中,我们都是在写项目,所以学习我们不能仅仅学习某个点,更重要的是多写项目,20多个项目实战,跟企业中一模一样的开发方式去完成项目 这里我推荐一下张容铭的爱创课堂的前端,大家可以加我发你看看 不懂感恩心态的朋友,就不要找我索取了,谢谢。想要的就加我q3252897743

April 17, 2019 · 1 min · jiezi

Flexbox 很棒,但有些情况不适用

对大部分的人来说(如果你写过CSS),Flexbox 可以说是完美,但它是否适合所有场景呢?简而言之,我会给出几种可用的场景,需要你重新思考 Flexbox 模型的使用。顺便说一句,本人是 Flexbox 的忠实粉丝,曾写过一篇 Flexbox 详解 ,可以算得上最全面的文章了。当然,我们应该了解该如何使用 Flexbox,哪些情况不应该使用,以及用在哪些地方最好。以下是我选出的最不应该是使用 Flexbox 的3种场景,并附带原因。1. 把Flexbox当作一个网格系统使用长久以来,很多人(包括我自己)都在滥用 CSS 盒模型。从复选框点击 hack 到“纯 CSS 图形”,我们似乎沉浸在各种奇淫巧技中 —— 各种让人觉得高大上或精通的技巧。我并不反对这样做,但其实我们曲解了 CSS 规范,不是吗?我们并没有将它们用在应该用的地方 —— 主要原因之一是可以做,之二是不得不做。有时候仅仅是出于兴趣(我觉得我属于这种)。也就是说,如果你选择在布局中将 Flexbox 模型当作网格系统使用,那么就算曲解了规范。还能不能开心的玩耍了?你当然可以用,但就像滥用 CSS 盒模型。其设计初衷并不是完备的网格系统。尽管你可以任意使用 Flexbox 模型,当然本人也曾瞎用,但其初衷不改。网格布局 —— 在 2017 年火了,因为所有主流浏览器都开始支持。可以在布局中将 Flexbox 作为唯一的网格系统使用吗?额!当然不可以。为什么?如果仅仅是为了一个怎么复杂的布局,或简单的为了移动端而重构布局,确实有这种可能。其实你可以摆脱这种想法的,虽然曾经我试过只用 Flexbox 就可以完成复杂的布局 —— 仅仅是因为可以做,并探索 Flexbox 的可能性。有什么注意事项吗?有一点你一定要记住。如果你不得不兼容老版本的 IE 浏览器(它们还能支持些什么好功能么?),那会有一个大问题,因为用户什么都看不到 —— 任何东西都不会显示。但是,如果你在这些浏览器上使用 Flexbox 模型作为渐进增强,你的备用方案可能是表格布局,那么老版本 IE 用户能正常使用。Flexbox 也支持一些真正的 网格系统 才有的标准特性 —— 那些特性真的很棒。尽管它还不太“标准”。此处的标准指的是就像圣杯布局那样的常用。所以禁止将其作为一个完整的网格系统使用。后面会继续讨论。2. 完全控制其视觉位置能力越大责任越大 …然后滥用! (我加的).网格布局最棒的特点之一就是无需考虑 html 源码的顺序而可以自由的指定内容的显示位置。难道 Flexbox 模型没有顺序属性么?其实是有的。但猫有四条腿,而人类只有两条。PS:此处的意思是,毕竟还是有区别,不能同等对待不同的事物,即使外观类似.上面的猫星人很帅,但即使套上了西装,也还不是人类!毫无疑问,只有人才能算人类。这就跟通过顺序属性实现“排序”的 Flexbox 一样。仅适用于简单的重排场景,如下:flexbox重排之前flexbox重排之后但是,它仍是基于元素的 html 源码顺序的。所以,其实还是没有脱离“猫人”的本质。其对源码顺序的处理与 CSS 网格布局完全不同。网格布局是另一个话题,这里不会详细讨论。3. 多列布局我觉得应该不会有很多人会将 Flexbox 模型用来干这个,值得一提的是,除了Flexbox之外,CSS3 还提供其他增强布局方式 —— Flexbox 只是恰巧也能用来完成类似的功能。如果你想这样做,那么请考虑优先使用 CSS3 已提供的合适的布局方式。i. 排除特定形状如果你需要构建复杂的布局,并想要让内容按自定义区域排版或要特定几何形状来包裹内容,请使用正确的方法。虽然你可以将其包裹在 flex-item(弹性项)中,但还是要使用正确的方法处理排除和内容包裹。ii. 实现多列多列布局是 Indesign 等传统桌面排版软件的核心功能,当某列调整大小或不能包含所有内容时,列内的文本会自动流入另一列。如果你需要在你项目中实现这个功能,CSS3 多列布局方式可以直接实现。所以,啰嗦一句,请使用正确的方式来实现此功能。可以让多列布局的某列也同时具有 flex-item(弹性项)特性么?我没有玩过 —— 不确定。总而言之,Flexbox 还是很棒的!真的很有用。非常有必要深入了解它,了解他们应该在何时何处使用。对于 Flexbox,其最大的优势是可在整体页面中为独立部分的自由布局。觉得不错? ...

April 17, 2019 · 1 min · jiezi

Vertical-Align,你应该知道的一切

好,我们聊聊vertical-align。这个属性主要目的用于将相邻的文本与元素对齐。而实际上,verticle-algin可以在不同上下文中灵活地对齐元素,以及进行细粒度的控制,不必知道元素的大小。元素仍然在文档流中,因而其他元素可以根据它们大小的变化进行相应的调整。一个有用的例子就是居中图标与旁边的文本。Vertical-Align是个怪物可是,vertical-align有时候也很难搞,经常导致困惑。好像有什么神秘的规则在起作用。比如,我们改变了某个元素的vertical-align而它的对齐方式却并未改变,反倒是同一行的其他元素的对齐方式变了!我时不时地仍然会掉到vertical-align的坑里,绝望无助。遗憾的是,关于这方面的资料大都讲得很肤浅。尤其是针对布局的情况。很多文章概念错乱,试图把元素中的一切都垂直对齐。它们介绍了这个属性的基本概念,解释了简单情况下元素的对齐,却没涉及真正棘手的部分。因此,我给自己设定了一个目标:彻底摸清vertical-align的行为。然后我就死啃W3C的CSS规范,同时也尝试了一些例子。最终写出了这篇文章。好,下面我们就开始吧。对哪些元素可以使用Vertical-Alignvertical-align用于对齐行内元素。所谓行内元素,即display属性值为下列之一的元素:inlineinline-blockinline-table (本文未涉及)其中,行内元素(inline element)就是包含文本的标签。而行内块元素(inline-block element),顾名思义,就是位于行内的块元素。可以有宽度和高度(可以由其内容决定),也可以有内边距、边框和外边距。行内级元素会相互挨着排成行。如果一行排不下,就会在下方再建一行。所有行都会创建所谓的行盒子,行盒子装着自己行中的所有内容。内容的高度不同,行盒子的高度也不同。在下面的示意图中,行盒子的顶部和底部用红色点线表示。这些行盒子限定了我们可以影响的范围。在行盒子内部,可以通过vertical-align来对齐个别元素。那么,相对于什么来对齐元素呢?基线与外边界垂直对齐最重要的参考点,就是相关元素基线。某些情况下,行盒子的上下外边界也会成为参考点。下面我们就来看一看相关元素类型的基线和外边界。行内元素这里有三行文本紧挨着。红线表示行高的顶边和底边,绿线表示字体高度,蓝线表示基线。左边这一行,行高与字体高度相同,因此上下方的红色和绿线重叠在了一起。中间一行,行高是font-size的两倍。右边一行,行高为font-size的一半。行内元素的外边界与自己行高的上、下边对齐。行高比font-size小不小并不重要。因此上图中红线同时也就表示外边界。行内元素的基线是字符恰好位于其上的那条线,也就是图中的蓝线。大致来说,基线总是穿过字体高度一半以下的某一点。可以参考W3C规范中详细的定义。行内块元素从左到右:包含流内内容(“c”)的行内块、包含流内内容且设置了溢出(overflow: hidden)的行内块和未包含流内内容(但内容区有高度)的行内块。红线表示外边距的边界,黄色是边框,绿色的内边距,蓝色是内容区,蓝线是每个行内块元素的基线。行内块元素的外边界即其外边距盒子的上、下两边,也就是图中的红线。行内块元素的基线取决于元素是否包含流内内容:有流内内容的行内块元素,基线就是正常流中最后内容元素的基线(左)。这个最后元素的基线是按照它自己的规则找到的。有流内内容但overflow属性值不是visible的行内块元素,基线就是外边距盒子的底边(中)。也就是与行内块元素的下外边界重合。没有流内内容的行内块元素,基线同样是外边距盒子的底边(右)。行盒子这张图前面出现过。但这次我们画出了行盒子的文本盒子的上、下边(绿色,下面详细介绍)还有基线(蓝色)。同时,还用灰色背景表示了文本元素的区域。行盒子的顶边与该行中最顶部元素的顶边重合,底边与该行中最底部元素的底边重合。因此图中的红线表示的就是行盒子。行盒子的基线是个变量:CSS 2.1没有定义行盒子的基线。在使用vertical-align时这一块应该是最令人困惑的了。也就是说,基线画在哪里需要满足很多条件,比如要符合vertical-align指定的条件,同时还要保证行盒子高度最小。这是个自由变量。因为行盒子的基线并不可见,所以有时候不容易确定它的位置。但实际上有个简单的办法可以令其可见。只要在相关行的开头加上一个字母,比如上图中开头的“x”即可。如果这个字母没有被设置对齐,那么它默认就位于基线之上。围绕基线的是行盒子中的文本盒子。可以简单地把文本盒子看成行盒子内部未经对齐的行内元素。文本盒子的高度等于其父元素的font-size。因此,文本盒子只是用来盛放未经格式化的文本的。上图中的绿线表示的就是文本盒子。由于文本盒子与基线关联,所以基线移动它也会跟着移动。(W3C规范里称这个文本盒子为strut。)终于把最难的部分讲完了。现在,我们已经知道了对齐相关的一切要素。下面简单总结一下最重要的两点。有一个区域叫行盒子。行盒子中的内容可以垂直对齐。行盒子有基线、文本盒子,还有上边和下边。还有行内元素,也就是可以被对齐的对象。行内元素有基线,以及上边和下边。Vertical-Align的值使用vertical-align,前面提到的参考点就会按照某种关系被设置好。对齐行内元素的基线和行盒子的基线baseline:元素基线与行盒子基线重合。sub:元素基线移动至行盒子基线下方。super:元素基线移动至行盒子基线上方。<百分比值>:元素基线相对于行盒子基线向上或向下移动,移动距离等于line-height的百分比。<长度值>:元素基线相对于行盒子基线向上或向下移动指定的距离。相对于行盒子的基线对齐元素的外边界middle:元素上、下边的中点与行盒子基线加上x-height的一半对齐。相对于行盒子的文本盒子对齐元素的外边界还有两种情况是相对于行盒子的基线对齐,因为文本盒子的位置由行盒子的基线决定。text-top:元素的顶边与行盒子的文本盒子的顶边对齐。text-bottom:元素的底边与行盒子的文本盒子的底边对齐。相对于行盒子的外边界对齐元素的外边界top:元素的顶边与行盒子的顶边对齐。bottom:元素的底边与行盒子的底边对齐。为何Vertical-Align的行为如此乖张下面我们看看在某些情况下的垂直对齐。特别是一些容易出错的情况。居中图标有一个问题一直困扰着我。有一个图标,我想让它与一行文本垂直居中。如果只应用vertical-align: middle好像不行,比如这个例子:<span class=“icon middle”></span>Centered?<span class=“icon middle”></span><span class=“middle”>Centered!</span><style type=“text/css”> .icon { display: inline-block; /* size, color, etc. / } .middle { vertical-align: middle; }</style>还是同一个例子,只不过这次多了一些辅助线:这次可以看清问题所在了。因为左侧的情况是文本没对齐,而是仍然位于基线之上。应用vertical-align: middle,实际上会导致图标中心与不出头小写字母的中心(x-height的一半)对齐,所以出头的字母会在上方突出出来。右侧,仍然是对齐整个字体区的垂直中点。结果文本基线稍稍向下移动了一点,于是就实现了文本与图标完美对齐。行盒子基线的移动这是使用vertical-align时一个常见的坑:行盒子基线的位置会受到其中所有元素的影响。假设一个元素采用的对齐方式会导致行盒子移动。由于大多数垂直对齐(除top和bottom外),都相对于基线计算,因此这会导致该行所有其他元素重新调整位置。下面是几个例子。如果行内有一个很高的元素,这个元素上方和下方都没有空间了,此时要与行盒子的基线对齐,就必须让它移动。矮盒子是vertical-align:baseline。左侧的高盒子是vertical-align: text-bottom,而右侧的高盒子是vertical-algin:text-top。可以看到,基线带着矮盒子移动到了上方。<!– left mark-up –> <span class=“tall-box text-bottom”></span> <span class=“short-box”></span> <!– right mark-up –> <span class=“tall-box text-top”></span> <span class=“short-box”></span> <style type=“text/css”> .tall-box, .short-box { display: inline-block; / size, color, etc. / } .text-bottom { vertical-align: text-bottom; } .text-top { vertical-align: text-top; } </style>在通过vertical-align的其他值对齐一个较高的元素时,也会出现同样的现象。即使设置vertical-align为bottom(左)和top(右),也会导致基线移动。这就很奇怪了,因为此时根本不关基线什么事。<!– left mark-up –><span class=“tall-box bottom”></span><span class=“short-box”></span><!– right mark-up –><span class=“tall-box top”></span><span class=“short-box”></span><style type=“text/css”> .tall-box, .short-box { display: inline-block; / size, color, etc. / } .bottom { vertical-align: bottom; } .top { vertical-align: top; }</style>把两个较大的元素放在一行并垂直对齐它们,基线也会移动以匹配两种对齐。然后,行的高度会调整(左)。再增加一个元素,但该元素对齐方式决定了它不会超出行盒子的边界,所以行盒子不会调整(中)。如果新增的元素会超出行盒子的边界,那么行盒子的高度和基线就会再次调整。在这例子中,前两个盒子向下移动了(右)。<!– left mark-up –><span class=“tall-box text-bottom”></span><span class=“tall-box text-top”></span><!– middle mark-up –><span class=“tall-box text-bottom”></span><span class=“tall-box text-top”></span><span class=“tall-box middle”></span><!– right mark-up –><span class=“tall-box text-bottom”></span><span class=“tall-box text-top”></span><span class=“tall-box text-100up”></span><style type=“text/css”> .tall-box { display: inline-block; / size, color, etc. / } .middle { vertical-align: middle; } .text-top { vertical-align: text-top; } .text-bottom { vertical-align: text-bottom; } .text-100up { vertical-align: 100%; }</style>行内元素下面可能会有一个小间隙看看这个例子:对列表元素的li应用vertical-align。<ul> <li class=“box”></li> <li class=“box”></li> <li class=“box”></li></ul><style type=“text/css”> .box { display: inline-block; / size, color, etc. / }</style>我们看到,列表项位于基线上。基线下面有一个小间隙,用于文本的下伸部分。怎么办?只要把基线向上移开一点就行了,比如用vertical-align: middle:<ul> <li class=“box middle”></li> <li class=“box middle”></li> <li class=“box middle”></li></ul><style type=“text/css”> .box { display: inline-block; / size, color, etc. */ } .middle { vertical-align: middle; }</style>有文本内容的行内块不会出现这种情况,因为内容已经把基线向上移了。行内元素间的间隙会破坏布局这主要是行内元素本身的问题。由于vertical-align必然会遇到行内元素,所以有必要了解一下。在前面列表项的例子中也可以看到这个间隙。这个间隙来自你的标记中行内元素间的空白。行内元素间的所有空白会折叠为一个。如果我们要通过width: 50%实现并排放两个行内元素,那这个空白就会成为障碍。因为一行放不下两个50%再加一个空白,结果就会折行(左)。要删除这个间隙,需要在HTML中通过注释删除空白(右)。<!– left mark-up –><div class=“half”>50% wide</div><div class=“half”>50% wide… and in next line</div><!– right mark-up –> <div class=“half”>50% wide</div><!—-><div class=“half”>50% wide</div><style type=“text/css”> .half { display: inline-block; width: 50%; }</style>Vertical-Align揭秘好了,就这些。一旦了解了规则,就没有那么复杂了。如果vertical-align没有达到效果,只要问下面的问题就能找到症结所在:行盒子的基线和上、下边界在哪儿?行内元素的基线和上、下边界在哪儿?据此就可以找到问题的解决方案。 ...

April 17, 2019 · 2 min · jiezi

一次搞懂CSS字体单位:px、em、rem和%

对于绘图和印刷而言,“单位”相当重要,然而在网页排版里,单位也是同样具有重要性,在CSS3普及以来,更支持了一些方便好用的单位(px、em、rem…等),这篇文章将整理这些常用的CSS单位,也帮助自己未来在使用上能更加得心应手。“网页”和“印刷”的单位若要把单位做区隔,最简单可以分为“网页”和“印刷”两大类,通常对于CSS来说只会应用到网页的样式,毕竟真正要做印刷,还是会倾向透过排版软件来进行设计。网页(单位)px:绝对单位,代表屏幕中每个「点」(pixel)。em:相对单位,每个子元素透过「倍数」乘以父元素的px值。rem:相对单位,每个元素透过「倍数」乘以根元素的px值。%:相对单位,每个子元素透过「百分比」乘以父元素的px值。网页(属性名称)medium:预设值,等于16px(h4预设值)xx-small:medium的0.6倍(h6预设值)x-small:medium的0.75倍small:medium的0.8倍(h5预设值,W3C定义为0.89,实测约为0.8)large:medium的1.1倍(h3预设值,W3C定义为1.2,实测约为1.1)x-large:medium的1.5倍(h2预设值)xx-large:medium的2倍(h1预设值)smaller:约为父层的80%larger:约为父层的120%印刷pt:打印机的每个「点」,定义为1 pt=1/72 in,如果在72 dpi的系统上1 px = 1 pt,但如果在96dpi的系统上1 px = 0.75 pt(72/96 = 0.75)。in:英寸,在96 dpi的系统上1 in = 96 px。cm:厘米,在96 dpi的系统上1 cm = 37.795275593333 px。mm:毫米,在96 dpi的系统上1 cm = 3.7795275593333 px。示例展示以下将展示四种不同单位的示例,为公平起见,四个示例都套用预设的div格式,纯粹改变font-size看看有何不同,由于子元素若没有设定font-size,会自动继承父元素的font-size,使用上就应该要预先初始化字体大小,下面这两段CSS可以将所有的元素字体大小预设为16px,然后可个别进行调整。html{ font-size:16px;}html * { font-size: 1rem;}1. pxpx是绝对单位,因此只要设定多少px,就会精确的呈现,对于一些讲求精准位置的排版而言十分有用,如示例表示的,指定多大px字体就会多大。<div style=“font-size:16px;">16px <div style=“font-size:20px;">20px <div style=“font-size:24px;">24px <div style=“font-size:16px;">16px <div style=“font-size:32px;">32px</div> </div> </div> </div></div>2. emem是相对单位,为每个子元素透过“倍数”乘以父元素的px值,如果我们每一层div都使用1.2em,最内层就会是16px x 1.2 x 1.2 x 1.2 x 1.2 x 1.2 = 39.8px。(浏览器预设字体大小为16px,若无特别指定则会直接继承父元素字体大小)<div style=“font-size:1.2em;">1.2em <div style=“font-size:1.2em;">1.2em <div style=“font-size:1.2em;">1.2em <div style=“font-size:1.2em;">1.2em <div style=“font-size:1.2em;">1.2em</div> </div> </div> </div></div>3. remrem是相对单位,为每个元素透过“倍数”乘以根元素的px值,如果我们每一层div都使用1.2rem,最内层就会是16px x 1.2 = 19.2px。(根元素指的是html的font-size,预设为16px)<div style=“font-size:1.2rem;">1.2rem <div style=“font-size:1.2rem;">1.2rem <div style=“font-size:1.2rem;">1.2rem <div style=“font-size:1.2rem;">1.2rem <div style=“font-size:1.2rem;">1.2rem</div> </div> </div> </div></div>4. %%百分比是相对单位,和em大同小异,简单来说em就是百分比除以一百,如果我们每一层div都使用120%,就等同于1.2em,最内层就会是16px x 1.2 x 1.2 x 1.2 x 1.2 x 1.2 = 39.8px。<div style=“font-size:120%;">120% <div style=“font-size:120%;">120% <div style=“font-size:120%;">120% <div style=“font-size:120%;">120% <div style=“font-size:120%;">120%</div> </div> </div> </div></div>5.small、medium、large…等字体大小的属性有七种,分别是xx-small、x-small、small、medium、large、x-large和xx-large,除了x-small,其余六种分别对应h6~h1的标签文字大小,根据W3C的规范,以medium预设16px为基础(若html字体预设大小改变,medium也会跟着变),使用固定的百分比乘以medium的大小,例如ss-small预设为16px x 0.6 = 9.6px(浏览器显示为12px)。<div style=“font-size:xx-small;">xx-small <div style=“font-size:x-small;">x-small <div style=“font-size:small;">small <div style=“font-size:medium;">medium <div style=“font-size:large;">large <div style=“font-size:x-large;">x-large <div style=“font-size:xx-large;">xx-large</div> </div> </div> </div> </div> </div></div>6. larger、smallerlarger和smaller就是固定百分比为单位,larger为父层的120%,smaller为父层的80%。<div style=“font-size:medium;">medium <div style=“font-size:larger;">larger <div style=“font-size:larger;">larger <div style=“font-size:larger;">larger <div style=“font-size:smaller;">smaller <div style=“font-size:smaller;">smaller <div style=“font-size:smaller;">smaller</div> </div> </div> </div> </div> </div></div>小结熟悉了字体大小单位之后,就更能有系统的设计整个网站的CSS构架,不过font-size本身和font-family有着一些复杂的关系,不同的font-family有时也会影响font-size的设定,因此使用上还是得稍微注意一下啰! ...

April 17, 2019 · 1 min · jiezi

css元素(before与after)

最近因为一些网页的需要,比较深入的使用了CSS的“伪元素”(Pseudo Element),发现原来不只是用用before或after而已,可以玩的东西还真是不少,所以就来篇文章,把这些比较不常玩的用法纪录一下。什么是“伪元素”?“伪元素”之所以称作“伪”,除了英文从“Pseudo”翻译过来之外,就是因为它并不是真正网页里的元素,但行为与表现又和真正网页元素一样,也可以对其使用CSS操控。跟伪元素类似的还有“伪类”(Pseudo classes),在W3C的定义里总共有五个伪元素(其他仍在测试阶段),分别是::before、::after、::first-line、::first-letter和::selection,为了和伪类区分,伪元素使用两个冒号“::”开头,而伪类使用一个冒号“:”开头(像是:hover、:target…等)。虽然现在的浏览器就算写一个冒号也可以正常运作,不过为了方便区分,用两个冒号还是比较好的,而且不论浏览器是什么,::selection必须是两个冒号才能正常运作。认识::before与::after::before、::after大概是最常使用的伪元素,两者都是以display:inline-block的属性存在,::before是在原本的元素“之前”加入内容,::after则是在原本的元素“之后”加入内容,同时伪元素也会“继承”原本元素的属性,如果原本文字是黑色,伪元素的文字也会是黑色。举例来说,下面这段代码,有一个div内容是“大家好,我是div”,使用::before、::after之后,会在原本div的前后各添加一段文字,并且让这两段文字都呈现红色。div::before{ content:“我是 before”; color:red;}div::after{ content:“我是 after”; color:red;}实用的content上述的内容乍看之下很容易理解,比较需要注意的是一定要具备content的属性,就算是只有content:“”;都可以,因为没有content的伪元素是不会出现在画面上的,然而content是个很特别的属性,它可以使用attr直接获取内容元素的属性值(attribute),举例来说,在HTML里有一个超链接,点击后会弹出新视窗并连接至Google:<a href=“https://www.google.com” target="_blank">google</a>使用下列的代码用法,将会把超链接的href内容与target内容,透过伪元素一前一后的显示出来。a::before{ content: attr(href); color:red;}a::after{ content: attr(target); color:green;}此外content内容是可以“相加”的,不过用法不像JavaScript使用+号来相连,而是直接用一个空格键就可以不断的累加下去,以下面的代码来说,可以在刚刚撷取的超链接文字后方和target属性前方,加入标点符号。a::before{ content: “( " attr(href) " ) < “; color:red;}a::after{ content: " > ( " attr(target) " ) “; color:green;}content甚至可以使用url放入图片图片的功能,下列的代码会呈现出三张图片。div::before{ content:url(图片网址) url(图片网址) url(图片网址);}content搭配quotes使用在CSS里有个不常用的属性就是quotes,这是做为定义“括号格式”的属性,也就是如果在一段文字被<q></q>包住,这段文字的前后就会出现自定义的括号,而且quotes支持巢状的结构,也就是你可以一层层的写下去,以下面这段HTML文字举例:最外层<q>第一层<q>第二层</q><q>第二层<q>第三层</q></q></q>quotes的属性如果只写一层,就会看到只出现一种括号,前后括号使用空白区隔,两组为一个单位,前后可以不同符号。q{ quotes: ’ < ’ ’ > ‘;}如果写了三层,就会看到出现三种括号,支持把文字当作括号使用。q{ quotes: ’ < ’ ’ > ’ ’ ya ’ ’ ya ’ ’ ( ’ ’ ) ’ ;}同样的道理,我们可以应用在content里面,而且透过伪元素已::before和::after已经处于前后的预设位置,甚至不用<q></q>就实现前后括号的效果,以下面这段HTML文字举例,把刚刚的q全部换成span:最外层<span>第一层<span>第二层</span><span>第二层<span>第三层</span></span></span>CSS的部分比较特别,在伪元素content里使用了open-quote(启始括号)和close-quote(结束括号)这两个有趣的值,换句话说open-quote对应到<q>,close-quote对应到</q>,此外也由于括号是在伪元素内,就可以指定不同的颜色或样式了。span{ quotes: ’ < ’ ’ > ’ ’ ya ’ ’ ya ’ ’ ( ’ ’ ) ’ ;}span::before{ content:open-quote; color:red;}span::after{ content:close-quote; color:#aaa;}小结虽然说伪元素很好用,但伪元素的内容实际上不存在网页里(如果打开浏览器的开发者工具,是看不到内容的),所以如果在里头塞了太多的重要的内容,反而会影响到SEO的效果,因此对于使用伪元素的定位,还是当作“辅助”性质会比较恰当。 ...

April 17, 2019 · 1 min · jiezi

前端未来之路在何方?

近期学到一个词:Digital Twin(数字孪生),简单来讲就是在计算机世界给现实世界的物体(飞船/城市)、系统(电力/交通)建立数字化镜像,让数字世界和物理世界更好地交互,数字大屏也可以算这种技术一种应用场景。这个概念由 Dr.Michael Grieves 于 2002 年提出,随着 IOT、AI、图形技术、工业 4.0 的飞速发展,应用前景越来越广阔。Google 一下 就会发现:NASA、GE、Microsoft、SAP、IBM 等巨头早已布局和应用这项技术,它还是 Gartner Top 10 Strategic Technology Trends for 2019 中的一项。最后,如果大家如果在自学遇到困难,想找一个前端的学习环境,可以加入我们的前端学习圈,点击我加入吧,会节约很多时间,减少很多在学习中遇到的难题。前端未来之路在何方?图片来自:How the visualization has changed by Digital Twin Technology前端为应用而生,人机交互技术是我们的生存之本,以应用为桥连接用户和数字世界是我们的使命。但长期以来前端的生存空间被压缩在 Web 领域,Digital Twin 这种新形态无疑将为我们打开一片新天地。Gartner 这份报告中还有两项技术和前端紧密相关:Immersive technologies:Augmented Reality(AR)、Virtual Reality(VR)、Mixed Reality(MR) 等Smart Spaces:智慧城市、智能汽车、智能商店等看到未来有三项战略性技术居然和前端有关,着实让人兴奋不已。不过莫急,既然是战略,也就意味着三五年内未必能开花结果。再仔细分析会发现:当下的前端技术远不足以胜任这些领域,不由得让人心忧。远方的风景很美,但要成功抵达就需要早做准备。站在 201X 的末尾、互联网下半场的开始,不妨先结合 Gartner 这份报告一起分析下:下一个 10 年前端技术的变革在哪里、有哪些值得大力投入的方向?回顾过去“以史为鉴,可以知兴替”,如果历史是一组波,它过去的相位所形成的轨迹已足以预见未来。回顾 Web 技术的发展历程,可以清晰地看到三类促使变革发生的关键因子:引擎:有四大引擎显得尤为重要:V8 :不仅提升了 JS 的执行效率,助力 ES 规范落地,而且催生了 Node.js浏览器引擎:以 Webkit、Blink、Chromium 为典型代表,浏览器的高速发展为 Web 的繁荣奠定了基础Node.js :大大拓展了前端的生存空间,以至于“Any application that can be written in JavaScript, will eventually be written in JavaScript.”Hybrid 容器:让被 App 统治的移动互联网时代也给 Web 开发留下了一席之地,小程序是典型代表开发套件:语法、框架、工具、类库在社区的推动下一直在蓬勃发展,优秀的开源项目灿若星河,前端生态也成为技术圈中最活跃的。虽然以 React 为核心的主流技术栈上手成本还比较高,也做不到让开发人员只关心业务逻辑,但不可否认应用开发正在变简单。有些类型的应用甚至做到了无需 Coding 通过专门的可视化搭建平台就可以完成,比如:门户网站、营销活动、问卷调查等。分工模式:前后端分离、BFF(Backend For Frontend)、全栈、全端、大前端等分工模式的创新不仅提高了前端和其它工种的协作效率,也让前端有机会承担应用研发。由“前端 + 设计”组合形成的“体验技术部”也成为很多业务的标配,部分前端团队甚至发展为应用研发团队并且拥有了自研产品。前端的影响圈已经从应用开发延展到了用户体验甚至产品设计,以人机交互为本的 体验科技 也开始崭露头角。这些变革因子的背后是两条主线:让现有研发工作做得更好:开发套件是主要推手,一些分工模式(比如:前后端分离)的创新也归属这条线开辟新战场:引擎是主要推手,一些分工模式(比如:全栈)的创新也归属这条线上这些变革之所以会发生,是因为有一个刚需:客户端软件的生产力水平满足不了飞速增长的互联网应用诉求,而前端技术恰好能提升应用研发的生产力水平。虽然移动互联网的崛起曾一度让前端缺少发力之处,但寄生于超级 App 上的 Hybrid 容器又让前端焕发了生机,小程序更是将之推向了和 PC 时代同样重要的地位。应用虽然琳琅满目,但其形态演化也是有迹可循的,要讲清楚得专门写一篇文档,这里不过多展开,简单介绍几个我认为最重要的:UGC 内容的主流载体在变:文本 -> 图片 -> 短视频/直播,用户创作内容的成本越来越低了终端的主流交互方式在变:PC(键盘/鼠标) -> 手机/PAD(触屏/摄像头/语音),交互越来越自然、简单了信息获取的主流方式在变:主动获取 -> 被动推送 -> 智能推荐,异步 -> 实时,信息已触手可得这一个刚需、两条主线、三类因子也是我们预判未来的重要依据。立足当下在当下可实践的新技术中,前端相关的有:AI、Serverless/FaaS、Blockchain、IOT、AR/VR/MR、智能硬件、可视化应用开发。不可否认,它们都是能在一些领域带来颠覆性革命的技术,但是否会给前端带来变革呢?让我们详细分析一下:AI:核心是云,而且 AI 应用的典型特点是“重引擎轻 UI”,所以前端不在主赛道,只能在应用开发中使用它。目前市面上的 AI 应用,多数是大数据技术的延伸,离 Intelligence 还太远。作为人类技术的巅峰之作,AI 应该在人类最难解决的问题上发挥价值,比如:语言文字、医疗、科研、教育、环境等。个人看好机器翻译,打破语言界限将会是人类文明一次划时代的变革。作为前端,我们也应该去关注这些基础领域,并学习和掌握 AI 技术。Serverless/FaaS: 核心是云,前端能做的是基于这种技术优化 Node.js 在服务端的 Runtime 和运维方式,把服务端复杂的技术细节屏蔽掉,让 Node.js 开辟出来的服务端战场可以延续,让端上所需的数据能以简洁、低成本的方式存储和获取。当然,也可以基于它优化现有的工具体系,让开发越来越简单。Blockchain:核心还是云,和前端最相关的是 Decentralized Application(DApp)、IPFS(the InterPlanetary File System)。但 DApp 是一种新的应用形态,IPFS 改变的是网络协议。这两者还处于非常早起的阶段,发展形势还不明朗,最好是静观其变,在合适的时候基于它们开发应用。IOT:核心是端,但关键技术是硬件及嵌入式系统,和前端交集较少,发挥空间很有限。除了在之上开发应用外,能看到的还有两个潜在方向:把 Node.js、浏览器内核移植到 IOT 设备,打造一个可运行前端代码的Runtime;部分设备需要展示数据,可以基于图形技术打造专属渲染引擎。AR/VR/MR:核心是硬件及交互方式的变化,前端能参与到类库及应用开发中。但受设备所限,目前还不是应用的主流,需要结合业务特点寻找切入点。智能硬件:非常酷的一项技术,智能音箱算是当下最成功的应用,机器人则是这项技术的终极形态。其核心在 AI 、自动化控制及硬件上,给前端带来的更多是应用形态和交互方式的升级。可视化应用开发:不写/少写代码就完成开发,这是前端的一个夙愿,不可能完全达成,但在特定场景下是可以做到的。MFC、Dreamweaver、Flash、Microsoft 是该领域的先驱,Wix、Webflow、Bubble、Node-RED、FrameX、PowerApps 是当下值得关注的。其本质上仍是通过更好的开发套件提升应用生产效率,其最大竞品是成品 SaaS,毕竟拿来就用比搭建更简单,这就如同当需要一台电脑时多数人会选择买成品而不是买配件组装。综上来看,这些新技术的关键路径和核心技术多数都不在前端,但我们能以使用者的身份参与进去,结合业务特点进行实践,让现有研发工作做得更好,让应用的交互体验更好。不过,还是有两个前端强相关的技术有望带来变革:IOT 上的 App Runtime :其背后就是一个引擎,能让前端应用运行在越来越多的新型终端上可视化应用开发:有望把部分功能和应用的开发成本降到最小一窥未来应用形态日新月异,新技术风起云涌,未来扑朔迷离…作为前端,我们究竟该往那些方向进行技术储备呢?要找到有指导意义的技术路线图,除了前文这些分析外,还得回到前端的本质中去探寻变革背后那些不变的东西,只有它们才能让我们以不变应万变,把技术转换为生产力。前端技术发展变化虽然很快,但从程序的视角来看,有两个东西一直未变:终端的形态和交互方式一直在变,其本质未变:渲染数据:把数字世界的数据转换成可被人感知的声音或图像,图形技术、音频技术、排版技术是核心采集数据:把物理世界的数据、人脑中的知识转换到数字世界,传感器技术、编辑器技术是核心应用的类别和交互方式在变,但应用研发始终可以分解为四大部分:云:提供应用运行所需的数据,托管资源及可执行代码端:依托某个 App Runtime 提供 UI 给最终用户专项技术:业务是技术之本,脱离了业务,前端将是无根之萍,而每个业务都有其专业属性和专项技术App Development Engine:也即“开发套件”,在普通工程师完全自主可控的范围内提升生产力结合以上分析以及语雀所属业务的特点,整理了下边这幅前端技术大图以抛转引玉:前端未来之路在何方?图中的每个区域都是一个不小的技术领域,要完全讲清楚得专门写文章,再加不少领域我只是略知一二,就不过多展开了,只简单介绍几个我认为比较重要的方向。App Development Engine当下的 Web 应用开发真的让人揪心,学习曲线非常陡峭、新概念层出不穷、技术更新换代太快…应用复杂度并不比十年前高多少,但要学习和掌握的东西是之前的很多倍。身处产品研发这个战场的前线,我们的装备一点都不精良,大把精力耗在作战无关的地方。生产力虽然在提升,但完全赶不上业务增长速度,App Developement Engine 这个提升生产力的关键因子在当下显得尤为重要。这个领域是创新最活跃的地方,从过去的发展历程中能看到一些演进脉络:从 Engine 的角度看,演进的背后有两种理念:Coding Less:通过强大的 SDK、框架和工具让工程师更好地 Coding,专注在实现业务上No Coding:通过可视化 IDE 达成不写代码,通过拖拽、编写配置文件就能完成应用开发从开发者角度看,对 Engine 有三个期待:Productivity:必须能提升生产力,让工程师可以高效地写出健壮、易维护的代码Simple & Stupid:KISS 原则 的核心,让开发变简单不仅能提升效率,还能让更多人成为前端工程师Business More:研发资源非常宝贵,让工程师专注在业务上是提升效能的关键未来的演化也会遵循这些脉络,Coding Less、No Coding 各有其应用场景,需要结合业务特点选择侧重点进行投入。但有一点我觉得是必然的:要开发优质应用,还得靠 Coding,不过写的代码会越来越少。No Coding 过于完美,应用场景有限,再加上有成品 SaaS 作为更好的替代品,我更倾向于用 Coding Less 模式去实现业务主线,把一些机械性、重复性、一次性的开发工作通过 No Coing 模式搞定。不过 No Coding 的一个分支 Visual Programming 非常值得关注,它在编程教育领域应用前景非常好,Scratch 、Blockly 是典型代表,而编程教育不仅蕴藏着巨大的商机,而且还会给我们带来源源不断的生力军。语雀专项技术语雀致力于打通「知识」和「大脑」之间的双向通道,背后是两大关键技术:编辑器:知识从大脑到数字世界的关键,语雀当下的文本编辑器、目录编辑器还很初级知识可视化:知识被人脑感知和理解的关键,给知识最佳的呈现形态有助于知识的理解和传播“数据可视化”和“数字孪生”在当下和语雀的关联并不大,但在未来一定会和语雀紧密相关:数据不仅是科学研究的基础,其背后本身就蕴藏着知识,数据可视化可以让这些知识更好地呈现给人们数字孪生和知识结合蛮有想象空间的,比如:数字博物馆、虚拟天文馆、仿真生态系统App Runtime为什么 App Rutime 会是变革的生力军呢?因为历史告诉我们:引擎的革新是开辟新战场的核心驱动力,而 App Rutime 的核心恰好就是引擎及其之上的 SDK。在很长一段时间里,前端技术得益并受限于浏览器引擎,广大前端工程师只能在 App Development Engine 层发力。但时至今日,终端、应用形态的多样性越来越强,移动互联网已经打破浏览器一统天下的局面,不难看出浏览器技术的进化速度已不能满足越来越多的新型终端和应用形态了。可以大胆地预测在这个领域必然会有一场变革,变革有可能由浏览器进化产生,也有可能是一些新的引擎。已经能看到一些苗头了:Office 以惊人的速度和 UI 一致性覆盖了所有终端,猜测其背后有一套跨端 UI 方案超级 App 打破了浏览器一统天下格局,小程序已是新的 RuntimeFlutter 在探索的就是一个新的跨端 UI 开发方式Fuchsia 则是 Google 在探索的一个更大的局,从 OS 层面推动变革更关键的是:这场变革是前端工程师有机会参与进去的,因为引擎的核心技术——图形技术已经在数据可视化、H5 Game 的推动下成为不少团队能熟练使用的技术。而应用类型的多样性也会给一些垂直市场的 App Runtime 留下生存空间,这块已经有一些成功案例,比如:游戏领域的 Cocos 引擎 和 白鹭引擎、桌面软件开发领域的 Electron,未来应该还会有更多。领域服务“领域服务”对前端来说可能比较陌生,它的背后是大名鼎鼎的 领域驱动设计(DDD:Domain-Driven Design),是应用在云端部分的高度抽象,是系统中的稳定部分,这也正是前端总是改版而服务端接口却可以不变的原因。服务端研发有这样一条演化主线:解决编程语言层面的问题 -> 解决开发框架 & 类库问题 -> 专注于解决业务问题,Java -> Spring -> DDD & Sofaware Architecure 就是典型案例。服务端之所以抗变能力这么强,正式由于把主要精力放在了领域模型抽象和系统架构设计上。为何领域服务在当下对前端也这么重要,因为:领域模型和领域服务是对业务的抽象,也是理解业务的直观体现,好的领域模型能大大降低前端开发成本领域设计的相关思想、理念可以借鉴到前端中,给前端带来解决问题的新思路前端处于研发的十字路口,信息面最广,极有潜力协调产品、设计、服务端等工种共同梳理领域模型和业务链路关于 DDD,可以从这三种非常容易理解和掌握的经典架构入门:Hexagonal Architecture(Ports and Adapters)CQRS - Command Query Responsibility SegregationThe Clean Architecture全功能型团队前端是工程师中离用户最近的群体,很多前端心中都有一个产品梦,这个产品可能是一个技术产品也可能是一个用户产品。很长一段时间内,我们疲于生存,只能忙里偷闲折腾个小工具或者参加下 Hackathon。但随着技术的演进,不少团队已经具备了全栈能力,并承担了 App Development Engine 中的一些平台的自主研发,让这个梦近了一些。但要完整实现,光有全栈能力是远远不够的,还需要一个包含技术、产品、设计、运营的全功能团队才能达成,这种团队不仅能提升协作效率、保证交付质量,还有可能催生出商业化产品。很多公司都在往大中台 + 小前台的方向发展,而支撑小前台的恰恰就是全功能型团队。所以在时机成熟时可以组建全功能型团队,逐步承接业务中人机交互部分的研发工作,让“用户体验”能落到实处。砥砺前行前端未来之路在何方?前端技术的未来,没有标准大图,这份图蕴含在每个业务中,更需要脚踏实地把未来亲手打造出来,业界趋势、新技术、新产品形态都是可以借力的因素。如果你已经有一个愿意与之一起奋斗和成长的业务,就可以结合业务定期推演适合它不同发展阶段的技术大图。如果还没有,也不用急,打好技术基础,做好手上的每个项目,结合业务在 Appliaction Development Engine 领域探索和实践,逐步寻找真正想做的业务、想服务的用户。软件研发是一项理论和实践并重的技术,实践尤为重要,因为最终我们是要写出健壮运行的代码给用户用的。不管未来如何,在持续学习和实践中强化对编程、技术、业务的理解才是根本。除了学习和实践与业务最相关的技术外,建议按自己的专长和兴趣把重点放在这些领域:领域驱动设计:强化领域建模和系统设计能力,力争懂业务、成为领域专家软件架构设计和软件设计哲学:它们会为系统、框架、类库注入灵魂,让代码有生命力图形技术:在应用、引擎两层都有广阔的场景,最关键的是图形应用在未来的占比一定会越来越高AI :不必深入到底层,但需要掌握其使用,不妨先从 TensorFlow 开始编程是一种修行,应用修行的产物,也是我们与世界交流的方式。未来在哪里并不重要,重要的是以空杯心态持续学习和实践,用心写下每行代码。 ...

April 17, 2019 · 2 min · jiezi

纯js实现web端录音与播放功能

纯js实现web端录音功能,功能并不是特别多,逐步增加中,详细地址:github。getUserMedia在非localhost和127的情况下,需要开启https,由于腾讯云的没备案,demo就不放了,可以自行获取代码并启动测试。实现方式实现原理的话,主要是以下三点,利用webrtc的getUserMedia方法获取设备音频输入,使用audioprocess得到音频流(pcm流,范围-1到1)。转码,利用前端中的ArrayBuffer等二进制操作按采样位数处理流信息。使用decodeAudioData转码arraybuffer到audioBuffer并播放(小文件,大文件使用audio)。使用方式script方式直接引入dist下的recorder.js即可let recorder = new Recorder();npm方式安装:npm i js-audio-recorder调用:import Recorder from ‘js-audio-recorder’;let recorder = new Recorder();API基本方法// 开始录音recorder.start();// 暂停录音recorder.pause();// 继续录音recorder.resume()// 结束录音recorder.stop();// 录音播放recorder.play();// 销毁录音实例,释放资源,fn为回调函数,recorder.destroy(fn);recorder = null;下载功能// 下载pcm文件recorder.downloadPCM();// 下载wav文件recorder.downloadWAV();// 重命名pcm文件,wav也支持recorder.downloadPCM(‘重命名’);获取录音时长// 回调持续输出时长recorder.onprocess = function(duration) { console.log(duration);}// 手动获取录音时长console.log(recorder.duration);默认配置sampleBits,采样位数,默认是16 sampleRate,采样频率,浏览器默认的,我的chrome是48000 numChannels,声道数,默认是1传入参数new Recorder时支持传入参数,{ sampleBits: 16, // 采样位数,范围8或16 sampleRate: 16000, // 采样率,范围11025、16000、22050、24000、44100、48000 numChannels: 1, // 声道,范围1或2}注意使用127.0.0.1或localhost尝试,因为getUserMedia在高版本的chrome下需要使用https。兼容性主要是以下几个方面:Web Audio Apihttps://caniuse.com/#search=w…getUserMediahttps://caniuse.com/#search=g…Typed Arrayshttps://caniuse.com/#search=t…欢迎访问和查看:recorder。其他资源基于阿里云实现简单的语音识别功能web Audio学习与音频播放web Audio实现pcm音频数据收集js实现pcm数据编码js转化pcm到wav格式与播放

April 17, 2019 · 1 min · jiezi

大厂h5开源视频系列-网易云音乐年度总结

前言大厂h5开源视频系列是一个专题,在这个专题中我们会解析一些酷酷的线上h5,在每一个细节,每一个细腻的过渡背后都能看到前端工程师付出的心血,本篇带来的是 ???????? 网易云音乐年度总结看视屏学习欢迎关注以往的文章:大厂h5开源视频系列-京东校招宣传线上链接请戳 ???????? 网易云音乐年度总结他并没有多震撼多酷炫, 那些花里胡哨的都没有,能形容的只有两个词:用心 细腻。网易云真的很用心,只要在 app 内部搜索【年度总结】你依然能看到自己的年度总结,在看到那首深夜还在听的歌,听过最多的歌词等瞬间,你是否回想起那个你爱过的女孩,是否能激起心里的涟漪。分屏解析1. 第二屏 概览分解:右上角的文字淡入左下角一个人在音符上摆腿线条直接用了 svg (svg不了解的同学可以参考 流动的SVG线条 )文字淡入这个应该比较简单,我们上篇文章也讲解过:只需要 opacity: 0 过渡到 opacity: 1;transform: translateY(6px); 过渡到 transform: translateY(0px);越到上面的文字越早出现,给每一行文字设置不同的 transition-delay: 0.2s; transition-delay: 0.3s; transition-delay: 0.4s;人在音符上摆腿这里比较费心:布局:可以看到除了音符外,这个人分为 头 身体 大腿 小腿 还有可爱的 jiojio每一个部位都是定位定好的,可以看出原作者真的耗费很多心血。<div class=“id7_yinfu11”> <div class=“id6_tou”> <div class=“P1hair”></div> </div> <div class=“id13_shenti”></div> <div class=“id11_2xiaotui”> <div class=“id12_2jiojiopng”></div> </div> <div class=“id8_1datui”> <div class=“id9_1xiaotui”> <div class=“id10_1jiojiopng”></div> </div> </div> <div class=“id15_yinfu12”></div> </div>音符摆动,左右摇摆即可。animation: yinfu11 5s cubic-bezier(.445,.05,.55,.95) infinite;@keyframes yinfu { 0% { transform: rotate(-2deg); } 51.67% { transform: rotate(2deg); } 100% { transform: rotate(-2deg); }}小腿往前踢,rotate 负数即可。@keyframes xiaotui { 0% { transform: rotate(0deg); } 51.67% { transform: rotate(-32deg); } 100% { transform: rotate(0deg); }}2. 第三屏 在网易云听到最多的歌词【永远】 两个词的出场实在太秀了,但其实实现还比较简单。分解一下就是:文字有旋转并且渐渐放大有背景模糊左右旋转就不过多介绍,渐渐放大和背景模糊,背景模糊这里用到了 filter:blur(),整个动画如下:@keyframes blurAppear { 0% { filter: blur(10px); transform: scale(.8); opacity: 0; } 100% { filter: blur(0); transform: scale(1); opacity: 1; }}3. 第四屏 特别的一天分析一下最靓的一个部分当然是:秋千摆动人在悠闲的踢腿整个秋千如下。左右摆动,设置 rotate 即可,需要注意的是:@keyframes ani4_qiuqian { 0% { transform: rotateZ(0deg);}50% { transform: rotateZ(31.99359208deg);}100% { transform: rotateZ(0deg);}}需要注意的是 这里角度较小,为了摆动的幅度大一点,可以设置transform-origin: -16.10878661% -29.76878613%;秋千完成之后,秋千上只有人的枝干,需要把腿,头,脖子等一一安放好。之后就是摆腿,摇头的动画,我们上文已经提及,这里不过多介绍。4. 第五屏 睡得最晚的一天分析:一只猫一个人这里作者做了分解,把不需要动的作为躯干固定好,比如人的躯干,猫的躯干。之后把需要动的,比如猫尾巴,猫爪, 人手… 作为另外一个部分装上去。5. 年度最喜欢歌手这一屏,我们分解一下右上角的卷纸动画。可以看到这其实是一个雪碧图,@keyframes juanAnimation { 0% { background-position: 0 0 } 3.70% { background-position: -483px 0 } 7.41% { background-position: -966px 0 } 11.11% { background-position: -1449px 0 } … 略过其中的几帧 100.00% { background-position: -1449px -954px }}定好的动画,我们上下卷纸的时候只需要让其中的一个动画反向播放即可。 animation: juanAnimation .5s steps(1) reverse, juanAnimation 1s steps(1) 1s forwards;总结在这个案列中其中很多动画并不难,但却是非常耗费工作量的,很多部位的拆分定位,而且越是细腻的动画需要的代码量也就越多。源码查看效果可戳此你可在 github上获取源码你可以跟着 开源视屏 一步步实现。预告下篇我们依旧带来 h5 的分享,内容依旧精彩。最后, 感谢网易云音乐前端团队的创意作品,给予我们的灵感和一起学习的机会! ...

April 16, 2019 · 1 min · jiezi

微信分享在本地调试配置nginx将本地ip映射为公众号配置域名

微信分享在本地调试的时候会出现域名无效的报错:errMsg:“config:fail,Error: invalid url domain所以配置了一个nginx在微信开发者工具中调试首先声明我是windows系统在C:WindowsSystem32driversetc文件夹下更改hosts文件在最后一行添加上127.0.0.1 www.test.com //这里是你想配置的域名然后安装nginx 更改conf文件夹下的nginx.confserver { listen 80; server_name www.test.com; #charset koi8-r; #access_log logs/host.access.log main; location / { proxy_pass http://localhost:8083; //你代理的本地ip proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header REMOTE-HOST $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; }}这样保存后我是vue项目需要在项目中设置devServer{ disableHostCheck: true}然后重新启动项目和nginx就ok了ps:这里有个弊端,在电脑上没问题 在手机上不能调试

April 16, 2019 · 1 min · jiezi

border-radius:50%,在安卓上存在兼容问题

做移动端开发时为了做适配,通常采用rem作为单位,下面来写一个圆角.round { width: 0.25rem; height: 0.25rem; border-radius: 50%; background: red;}相同的代码,有的是正圆,有的不是,ios,pc均显示正常解决方案:单位rem改为px, 但是这样做无法达到适配的目的设置图片使用svg, 既可以适配,即使再小的圆形也能在不同屏幕上完美展示<svg style=“height: 0.25rem;width: 0.25rem;"> <circle r=“0.12rem” fill=“red” cx=“0.12rem” cy=“0.12rem”></circle></svg>

April 16, 2019 · 1 min · jiezi

happyChat开发系列:使用websocket.io实现双向通信的乐聊大前端开发

一、前言乐聊是一个自己用websocket写一个完整的应用,虽然功能比较欠缺,但是实现了基本的文字聊天,以及群聊,私聊,机器人聊天等功能。因为这个自己做了PC端,无线端(手机端),以及使用cordova打包成一个android的apk。实现了一个大前端的项目,虽然现在android端还是有点有问题,在修改bug。二、websocket的原理介绍1、为什么需要websocket?因为 HTTP 协议有一个缺陷:通信只能由客户端发起。举例来说,我们想了解今天的天气,只能是客户端向服务器发出请求,服务器返回查询结果。HTTP 协议做不到服务器主动向客户端推送信息。这种单向请求的特点,注定了如果服务器有连续的状态变化,客户端要获知就非常麻烦。我们只能使用"轮询":每隔一段时候,就发出一个询问,了解服务器有没有新的信息。最典型的场景就是聊天室。轮询的效率低,非常浪费资源(因为必须不停连接,或者 HTTP 连接始终打开)。2、简介websocket特点:服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话,属于服务器推送技术的一种。其他特点包括:(1)建立在 TCP 协议之上,服务器端的实现比较容易。(2)与 HTTP 协议有着良好的兼容性。默认端口也是80和443,并且握手阶段采用 HTTP 协议,因此握手时不容易屏蔽,能通过各种 HTTP 代理服务器。(3)数据格式比较轻量,性能开销小,通信高效。(4)可以发送文本,也可以发送二进制数据。(5)没有同源限制,客户端可以与任意服务器通信。(6)协议标识符是ws(如果加密,则为wss),服务器网址就是 URL。三、websocket.io使用1、前端在vue项目中,在index.html中 <script src=“https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.2.0/socket.io.js"></script><script> // const socketWeb = io(‘http://localhost:3000’); const socketWeb = io(‘http://chat.chengxinsong.cn’); const userInfo = JSON.parse(sessionStorage.getItem(“HappyChatUserInfo”)) if (userInfo) { socketWeb.emit(‘update’, userInfo.user_id); }</script>2、后端后端是使用koa作为后端const app = new Koa();const server = require(“http”).createServer(app.callback());const io = require(“socket.io”)(server);io.on(“connection”, socket => { const socketId = socket.id; /登录/ socket.on(“login”, async userId => { await socketModel.saveUserSocketId(userId, socketId); }); // 更新soketId socket.on(“update”, async userId => { await socketModel.saveUserSocketId(userId, socketId); }); //私聊 socket.on(“sendPrivateMsg”, async data => { const arr = await socketModel.getUserSocketId(data.to_user); const RowDataPacket = arr[0]; const socketid = JSON.parse(JSON.stringify(RowDataPacket)).socketid; io.to(socketid).emit(“getPrivateMsg”, data); }); // 群聊 socket.on(“sendGroupMsg”, async data => { io.sockets.emit(“getGroupMsg”, data); }); //加好友请求 socket.on(“sendRequest”, async data => { console.log(“sendRequest”, data); const arr = await socketModel.getUserSocketId(data.to_user); const RowDataPacket = arr[0]; const socketid = JSON.parse(JSON.stringify(RowDataPacket)).socketid; console.log(‘给谁的socketid’,socketid) io.to(socketid).emit(“getresponse”, data); }); socket.on(“disconnect”, data => { console.log(“disconnect”, data); });});四、简介和功能乐聊,一个快乐聊天的应用,支持PC端和无线端和安卓APP。(1)PC端和无线端线上地址:http://chat.chengxinsong.cn(2)下载安卓APP地址:暂时还有点小问题待解决,后边放出地址版本v 1.0.0- 1、支持注册用户和邮件激活用户;- 2、支持登陆- 3、支持机器人聊天;- 4、支持加好友,一对一聊天;- 5、支持创建群,加群,一对多聊天;- 6、支持删除好友,退出群- 7、支持个人信息编辑- 8、支持添加好友备注- 9、支持聊天中文字发送- 10、支持浏览器:Chrome,Firefox,Safari,IE9及以上; 版本v 1.1.01、支持聊天中图片发送2、支持聊天中表情发送待续五、运行截图等等。。。六、前后端源码前端代码:https://github.com/saucxs/hap…后端代码:https://github.com/saucxs/hap…七、最后欢迎fork和star,有问题提issue ...

April 16, 2019 · 1 min · jiezi

【Vue源码学习】vue实例化到挂载到dom(上)

作者:王聪本篇目的是介绍vue实例化到挂载到dom的整体路线,一些细节会被省略。从new Vue()开始所有的一切都是从 new Vue()开始的,所以从这个点开始探寻这个过程发生了什么。从源码中找到Vue构造函数的声明,src/core/instance/index.jsimport { initMixin } from ‘./init’import { stateMixin } from ‘./state’import { renderMixin } from ‘./render’import { eventsMixin } from ‘./events’import { lifecycleMixin } from ‘./lifecycle’import { warn } from ‘../util/index’function Vue (options) { if (process.env.NODE_ENV !== ‘production’ && !(this instanceof Vue) ) { warn(‘Vue is a constructor and should be called with the new keyword’) } this._init(options)}initMixin(Vue)stateMixin(Vue)eventsMixin(Vue)lifecycleMixin(Vue)renderMixin(Vue)export default Vue是一个很简洁的function工厂模式声明的一个构造函数。内部做了逻辑判断:构造函数调用必须有 new 关键字。然后执行了this._init(options),该初始化函数就是Vue 初始化的开始。Vue.prototype._init()this._init()是在何时声明的呢?通过下边5个初始化函数的执行,在Vue原型链中添加了大量的的属性与函数。this._init()实际就是调用了原型链上的Vue.prototype._init()函数。initMixin(Vue)stateMixin(Vue)eventsMixin(Vue)lifecycleMixin(Vue)renderMixin(Vue)Vue.prototype._init函数是在initMixin(Vue)中去添加到原型链上的。在src/core/instance/init.js中定义Vue.prototype._init = function (options?: Object) { const vm: Component = this // a uid vm._uid = uid++ let startTag, endTag /* istanbul ignore if / if (process.env.NODE_ENV !== ‘production’ && config.performance && mark) { startTag = vue-perf-start:${vm._uid} endTag = vue-perf-end:${vm._uid} mark(startTag) } // a flag to avoid this being observed vm._isVue = true // merge options if (options && options._isComponent) { // optimize internal component instantiation // since dynamic options merging is pretty slow, and none of the // internal component options needs special treatment. initInternalComponent(vm, options) } else { vm.$options = mergeOptions( resolveConstructorOptions(vm.constructor), options || {}, vm ) } / istanbul ignore else / if (process.env.NODE_ENV !== ‘production’) { initProxy(vm) } else { vm._renderProxy = vm } // expose real self vm._self = vm initLifecycle(vm) initEvents(vm) initRender(vm) callHook(vm, ‘beforeCreate’) initInjections(vm) // resolve injections before data/props initState(vm) initProvide(vm) // resolve provide after data/props callHook(vm, ‘created’) / istanbul ignore if / if (process.env.NODE_ENV !== ‘production’ && config.performance && mark) { vm._name = formatComponentName(vm, false) mark(endTag) measure(vue ${vm._name} init, startTag, endTag) } if (vm.$options.el) { vm.$mount(vm.$options.el) } }}_init函数内部又通过上边的这种调用初始化函数的模式完成了具体模块的初始化。声明钩子的调用也首次在这里出现,通过分析这些函数调用顺序,能更好的理解官方文档中提及的各个生命周期钩子函数的触发时机。initLifecycle(vm)initEvents(vm)initRender(vm)callHook(vm, ‘beforeCreate’)initInjections(vm) // resolve injections before data/propsinitState(vm)initProvide(vm) // resolve provide after data/propscallHook(vm, ‘created’)在_init()函数的最后,执行了vm.$mount()。vm代表的是当前vue实例也就是构造函数被调用后的this指向。$mount是何时在vue上声明的呢?这次并不是在上边的初始化函数中完成声明的。因为 $mount 这个方法的实现是和平台、构建方式都相关,所以在不同构建入口文件中有不同的定义。Vue.prototype.$mount原型上声明的 $mount方法在 src/platform/web/runtime/index.js 中定义,这个方法会被runtime only版本和含编译器完整版中复用,vue版本说明。// public mount methodVue.prototype.$mount = function ( el?: string | Element, hydrating?: boolean): Component { el = el && inBrowser ? query(el) : undefined return mountComponent(this, el, hydrating)}现在接着上边Vue.prototype._init函数中调用了vm.$mount函数,实际上是执行了mountComponent(this, el, hydrating)函数。mountComponent定义在目录src/core/instance/lifecycle.js中export function mountComponent ( vm: Component, el: ?Element, hydrating?: boolean): Component { vm.$el = el if (!vm.$options.render) { vm.$options.render = createEmptyVNode if (process.env.NODE_ENV !== ‘production’) { / istanbul ignore if / if ((vm.$options.template && vm.$options.template.charAt(0) !== ‘#’) || vm.$options.el || el) { warn( ‘You are using the runtime-only build of Vue where the template ’ + ‘compiler is not available. Either pre-compile the templates into ’ + ‘render functions, or use the compiler-included build.’, vm ) } else { warn( ‘Failed to mount component: template or render function not defined.’, vm ) } } } callHook(vm, ‘beforeMount’) let updateComponent / istanbul ignore if / if (process.env.NODE_ENV !== ‘production’ && config.performance && mark) { updateComponent = () => { const name = vm._name const id = vm._uid const startTag = vue-perf-start:${id} const endTag = vue-perf-end:${id} mark(startTag) const vnode = vm._render() mark(endTag) measure(vue ${name} render, startTag, endTag) mark(startTag) vm._update(vnode, hydrating) mark(endTag) measure(vue ${name} patch, startTag, endTag) } } else { updateComponent = () => { vm._update(vm._render(), hydrating) } } // we set this to vm._watcher inside the watcher’s constructor // since the watcher’s initial patch may call $forceUpdate (e.g. inside child // component’s mounted hook), which relies on vm._watcher being already defined new Watcher(vm, updateComponent, noop, { before () { if (vm._isMounted && !vm._isDestroyed) { callHook(vm, ‘beforeUpdate’) } } }, true / isRenderWatcher /) hydrating = false // manually mounted instance, call mounted on self // mounted is called for render-created child components in its inserted hook if (vm.$vnode == null) { vm._isMounted = true callHook(vm, ‘mounted’) } return vm}抛开源码中对性能测试和异常警告部分的代码,这个函数内部做了以下事情:callHook(vm, ‘beforeMount’),调用生命周期钩子beforeMount声明了updateComponent函数new Watcher (vm, updateComponent, noop, {… callHook(vm, ‘beforeUpdate’)}})callHook(vm, ‘mounted’),调用生命周期钩子mounted这里的new Watcher()实例化了Watcher类,内部逻辑先不去深入,这里仅仅需要知道的是在这个实例化的过程中调用了作为参数传入的updateComponent函数,而从这个函数的声明来看,它实际上执行的是vm._update(vm._render(), hydrating)这个函数。首先vm._update和vm._render这两个方法是定义在Vue原型上的。Vue.prototype._renderVue 的 _render 方法是用来把实例渲染成一个虚拟 Node。是在renderMixin(Vue)执行时声明的。它的定义在 src/core/instance/render.js 文件中Vue.prototype._render = function (): VNode { const vm: Component = this const { render, _parentVnode } = vm.$options // reset _rendered flag on slots for duplicate slot check if (process.env.NODE_ENV !== ‘production’) { for (const key in vm.$slots) { // $flow-disable-line vm.$slots[key]._rendered = false } } if (_parentVnode) { vm.$scopedSlots = _parentVnode.data.scopedSlots || emptyObject } // set parent vnode. this allows render functions to have access // to the data on the placeholder node. vm.$vnode = _parentVnode // render self let vnode try { vnode = render.call(vm._renderProxy, vm.$createElement) } catch (e) { handleError(e, vm, render) // return error render result, // or previous vnode to prevent render error causing blank component / istanbul ignore else / if (process.env.NODE_ENV !== ‘production’) { if (vm.$options.renderError) { try { vnode = vm.$options.renderError.call(vm._renderProxy, vm.$createElement, e) } catch (e) { handleError(e, vm, renderError) vnode = vm._vnode } } else { vnode = vm._vnode } } else { vnode = vm._vnode } } // return empty vnode in case the render function errored out if (!(vnode instanceof VNode)) { if (process.env.NODE_ENV !== ‘production’ && Array.isArray(vnode)) { warn( ‘Multiple root nodes returned from render function. Render function ’ + ‘should return a single root node.’, vm ) } vnode = createEmptyVNode() } // set parent vnode.parent = _parentVnode return vnode}函数内部对不同逻辑有不同的处理,但最终返回的都是VNode。Virtual DOM 就是用一个原生的 JS 对象去描述一个 DOM 节点。Vue.prototype._update函数_update是在lifecycleMixin(Vue)函数执行时添加的。在目录src/core/instance/lifecycle.jsVue.prototype._update = function (vnode: VNode, hydrating?: boolean) { const vm: Component = this const prevEl = vm.$el const prevVnode = vm._vnode const restoreActiveInstance = setActiveInstance(vm) vm._vnode = vnode // Vue.prototype.patch is injected in entry points // based on the rendering backend used. if (!prevVnode) { // initial render vm.$el = vm.patch(vm.$el, vnode, hydrating, false / removeOnly */) } else { // updates vm.$el = vm.patch(prevVnode, vnode) } restoreActiveInstance() // update vue reference if (prevEl) { prevEl.vue = null } if (vm.$el) { vm.$el.vue = vm } // if parent is an HOC, update its $el as well if (vm.$vnode && vm.$parent && vm.$vnode === vm.$parent._vnode) { vm.$parent.$el = vm.$el } // updated hook is called by the scheduler to ensure that children are // updated in a parent’s updated hook. }通过源码看接受的参数:vnode: VNodehydrating?: boolean接受的第一个参数类型是VNode(用来描述dom节点的虚拟节点),第二个布尔类型的参数是跟ssr相关。函数内部最关键的执行了vm.$el = vm.patch(…)调用 vm.patch 去把 VNode 转换成真正的 DOM 节点现在回顾总结一下目前的流程:new Vue()操作后,会调用Vue.prototype._init()方法。完成一系列初始化(原型上添加方法和属性)执行Vue.prototype.$mountvm._render()获取描述当前实例的VNodevm._update(VNode),调用 vm.__patch__转换成真正的 DOM 节点流程图: ...

April 15, 2019 · 5 min · jiezi

如何实现vue中不跳转不闪动页面刷新?provide /inject 完美解决方案

在vue的项目中刷新功能你会怎么写?我之前一直用this.$router.go(0)这个方法用户体验很不好,因为页面会闪动一下刷新直到我发现了这个方法 provide /inject 不过这个方法貌似有兼容问题,首先要确定一下你的vue版本,此方法适用vue 2.20+原理:此方法使用的是v-if来控制router-view的显示或隐藏,v-if从false变为true时,vue会重新渲染router-view区域,所以当参数变化时,只需让v-if 从true => false => true,就能实现页面刷新首先,找到自己的route-view//App.vue <template> <div id=“app”> <router-view v-if=“isRouterAlive”/> </div> </template> <script> export default { name: ‘App’, provide() { return { reload: this.reload//调用reload方法 } }, data() { return { isRouterAlive: true//一开始router-view为true } }, methods: { reload() { this.isRouterAlive = false //在修改数据之后使用 $nextTick,则可以在回调中获取更新后的 DOM this.$nextTick(() => { this.isRouterAlive = true }) } } } </script> 然后在<route-view>下显示的vue页面中进行如下操作 export default { name: ’newproduct’, inject:[‘reload’],//在export default下面加上这一段 method:{ //调用App.vue下的this.reload()方法,来改变v-if的状态 clickDiv(){//刷新按钮调用的方法 this.reload() } } 就ok了加油!每天进步一点点! ...

April 15, 2019 · 1 min · jiezi

vue中修改Modal的重置功能怎么写?(重置不单独调后台接口)可利用深拷贝

工作中遇到弹出模态框形式的修改功能,模态框里面是Form表单,Form表单中的内容是从后台获取的,这时候用户修改完没有提交,而是想重置然后重新修改,怎么办呢?①重新调一遍后台的接口,将原始数据再一次放入Form中,这个方法可能会浪费资源,占用带宽②可以利用缓存③可以利用深拷贝简单解释一下深拷贝和浅拷贝a复制b,修改b,a也发生改变,说明拷贝不彻底,此为浅拷贝,a复制b,修改b,a不变,此为深拷贝深拷贝一般复杂数据类型才会发生,原因是基本数据类型和复杂数据类型的存储方式不同。关于深拷贝和浅拷贝的文章有很多,想多了解的同学可以自行搜索下面直接说方法我们可以封装一个深拷贝函数,在随便一个js文件里面(根据自己的项目) /** * 深度拷贝 * @param {*} arr */ export const copyArray = (arr) => { return JSON.parse(JSON.stringify(arr)) } 然后在你用到修改功能的vue文件中,直接引入使用就可以le import { copyArray } from ‘@/utils/util.js’ //修改的时候 this.formInline = copyArray(data)这是深拷贝的json方式,深拷贝的方式有很多,可自行了解说一下这种方式的原理吧上面说过基本数据类型没有深拷贝,json.stringify()将数组数据类型转换成字符串数据类型字符串属于基本数据类型,基本数据类型是按值传递的 var b = 1; var a = b; b++; console.log(a,b)//1,2这时候进行拷贝,然后在将字符串转换成对象,就实现了深拷贝加油!每天进步一点点!

April 15, 2019 · 1 min · jiezi

APICloud |UIChatTools 模块demo

UIChatTools 模块是一个聊天输入框模块,开发者可自定义该输入框的功能。通过 open 接口可在当前 window 底部打开一个输入框,该输入框的生命属于当前 window 所有。当输入框获取焦点后,会自动弹动到软键盘之上。开发者可通过监听输入框距离底部弹动的高度,来改变聊天对话界面的高度,从而实现类似 QQ 聊天页面的功能。UIChatTools 模块是 UIChatBox 模块的优升级。模块文档地址:https://docs.apicloud.com/Cli…此demo覆盖模块所有接口,供大家参考。需要注意的地方,open接口-styles-mask参数若设置,则会弹出遮罩层,点击遮罩层会收起键盘。addFace(添加表情包)接口,需先下载了一个表情包,然后解压(使用到了zip模块)到指定目录。使用fs模块的,可验证文件是否存在。Android添加表情包后,需再次点击表情按钮生效。此输入框模块只是提供了一个界面,和界面上按钮的点击回调事件,具体功能的实现,还需要配合其他api实现。比如,录音功能,还需要结合其他录音模块,或api对象的录音接口去实现。选择图片功能,UIChatTools模块已自带。图标、颜色可根据UI设计进行替换调整,模块提供参数可以进行设置。下载widget代码包:https://community.apicloud.co…

April 15, 2019 · 1 min · jiezi

vue单页面在微信下只能分享落地页的解决方案

实际上关键词叫微信pushState只能分享落地页更贴切一点应用场景:vue + vue-routervue-router使用hash模式(history模式没试过)不使用微信的js-sdk(因为我这个项目是可配置域名的商城,比较特殊,不能使用微信sdk)这个方案并不是最优秀的,会对性能造成一定的影响HTML5 history.pushStatevue-router的内部是通过history.pushState和history.replaceState实现的。但是iOS设备的微信浏览器不会去检测它们的变化。但是我们可以通过更新location.href让微信浏览器识别到当前的url。// vue-router/src/util/push-state.jsexport function pushState (url?: string, replace?: boolean) { saveScrollPosition() // try…catch the pushState call to get around Safari // DOM Exception 18 where it limits to 100 pushState calls const history = window.history try { if (replace) { history.replaceState({ key: _key }, ‘’, url) } else { _key = genKey() history.pushState({ key: _key }, ‘’, url) } } catch (e) { window.locationreplace ? ‘replace’ : ‘assign’ }}export function replaceState (url?: string) { pushState(url, true)}解决方法window.location.href = window.location.href,这段代码可以让微信记录当前的url,且不会刷新页面。可以在app.vue中watch $route在每次页面更新的时候执行一次。// app.vuewatch: { $route: { immediate: true, deep: true, handler(to) { // 微信浏览器判断 const WECHAT_BROWSER = navigator.userAgent.toLowerCase().includes(‘micromessenger’) // 解决iOS微信浏览器分享地址只能是落地页的问题,这个操作是不会刷新页面的,query参数改变也会执行 if (WECHAT_BROWSER) { // eslint-disable-next-line window.location.href = window.location.href } }},使用了上述方法可以解决这个问题,但是这会引出一个很奇葩的问题,在真机上进入http://192.168.1.5:8080和http://192.168.1.5:8080/#/这两个页面,其中有一个链接的bug依然存在。原因具体不清楚,经过测试可以在入口文件(main.js)中在页面还没有展示内容前刷新一次页面,即可解决这个问题。// main.js// 微信浏览器判断const WECHAT_BROWSER = navigator.userAgent.toLowerCase().includes(‘micromessenger’)// 在url插入的search参数,可以随意,但是必须要// 例:http://192.168.1.5:8080/?wx=1#/const wxQuery = ‘wx=1’const isRepeatQuery = location.search.includes(wxQuery)if (WECHAT_BROWSER && !isRepeatQuery) { const unit = (location.search && location.search !== ‘?’) ? ‘&’ : ‘?’ location.search += unit + wxQuery // 添加_wx_参数,该操作会刷新页面}上面的代码之所以要在hash前面加一个?wx=1参数,为了方便刷新页面给一个标志位判断是否已刷新。参数的key-value随意。 ...

April 15, 2019 · 1 min · jiezi

【周刊-2】三年大厂面试官-前端面试题披露(偏难)

前言在阿里和腾讯工作了6年,当了3年的前端面试官,把阿里和腾讯常问的面试题与答案汇总在我的Github中。希望对大家有所帮助,助力大家进入自己理想的企业。项目地址是:https://github.com/airuikun/W…如果你在阿里和腾讯面试的时候遇到了什么不懂的问题,欢迎给我提issue,我会把答案和考点都列出来,公布在下一期的面试周刊里。面试题精选大家如果去阿里和腾讯面试过,就会发现,在网上刷了很多的前端面试题,但是去大厂面试的时候还是一头雾水,那是因为那些在网上一搜就能搜出来的题,大厂的面试官基本看不上,他们都会问一些开放题,在回答开放题的过程中,就能摸清你知识技能的广度和深度,所以本期会加入几道我在面试候选人常用的开放题,供大家学习和思考。我把下面每道题的难度高低,和对标了阿里和腾讯的多少职级,都写上去了,大家可以参考一下自己是什么职级。第 1 题:如何劫持https的请求,提供思路难度:阿里p6+ ~ p7、腾讯t23 ~ t31很多人在google上搜索“前端面试 + https详解”,把答案倒背如流,但是问到如何劫持https请求的时候就一脸懵逼,是因为还是停留在https理论性阶段。我们腾讯新闻部门在18年年底的时候,新疆地区打开腾讯新闻页面全都是被篡改后的页面,但是我们的网站都是https协议的,为什么还会被劫持和篡改呢?因为有人在路由层面上动了手脚,具体方法因为涉密所以不方便公布。想告诉大家的是,就算是https,也不是绝对的安全,以下提供一个本地劫持https请求的简单思路。模拟中间人攻击,以百度为例先用OpenSSL查看下证书,直接调用openssl库识别目标服务器支持的SSL/TLS cipher suite openssl s_client -connect www.baidu.com:443用sslcan识别ssl配置错误,过期协议,过时cipher suite和hash算法 sslscan -tlsall www.baidu.com:443分析证书详细数据 sslscan -show-certificate –no-ciphersuites www.baidu.com:443生成一个证书 openssl req -new -x509 -days 1096 -key ca.key -out ca.crt开启路由功能 sysctl -w net.ipv4.ip_forward=1写转发规则,将80、443端口进行转发给8080和8443端口 iptables -t nat -A PREROUTING -p tcp –dport 80 -j REDIRECT –to-ports 8080 iptables -t nat -A PREROUTING -p tcp –dport 443 -j REDIRECT –to-ports 8443最后使用arpspoof进行arp欺骗如果你有更好的想法或疑问,欢迎在这题目对应的github下留言:https://github.com/airuikun/W…第 2 题:前端如何进行seo优化难度:阿里p5、腾讯t21合理的title、description、keywords:搜索对着三项的权重逐个减小,title值强调重点即可;description把页面内容高度概括,不可过分堆砌关键词;keywords列举出重要关键词。语义化的HTML代码,符合W3C规范:语义化代码让搜索引擎容易理解网页重要内容HTML代码放在最前:搜索引擎抓取HTML顺序是从上到下,保证重要内容一定会被抓取重要内容不要用js输出:爬虫不会执行js获取内容少用iframe:搜索引擎不会抓取iframe中的内容非装饰性图片必须加alt提高网站速度:网站速度是搜索引擎排序的一个重要指标如果你有更好的答案或想法,欢迎在这题目对应的github下留言:https://github.com/airuikun/W…第 3 题:前后端分离的项目如何seo难度:阿里p6 ~ p6+、腾讯t22 ~ t23使用prerender。但是回答prerender,面试官肯定会问你,如果不用prerender,让你直接去实现,好的,请看下面的第二个答案。先去 https://www.baidu.com/robots.txt 找出常见的爬虫,然后在nginx上判断来访问页面用户的User-Agent是否是爬虫,如果是爬虫,就用nginx方向代理到我们自己用nodejs + puppeteer实现的爬虫服务器上,然后用你的爬虫服务器爬自己的前后端分离的前端项目页面,增加扒页面的接收延时,保证异步渲染的接口数据返回,最后得到了页面的数据,返还给来访问的爬虫即可。如果你有更好的答案或想法,欢迎在这题目对应的github下留言:https://github.com/airuikun/W…第 4 题:简单实现async/await中的async函数难度:阿里p6 ~ p6+、腾讯t22 ~ t23async 函数的实现原理,就是将 Generator 函数和自动执行器,包装在一个函数里function spawn(genF) { return new Promise(function(resolve, reject) { const gen = genF(); function step(nextF) { let next; try { next = nextF(); } catch (e) { return reject(e); } if (next.done) { return resolve(next.value); } Promise.resolve(next.value).then( function(v) { step(function() { return gen.next(v); }); }, function(e) { step(function() { return gen.throw(e); }); } ); } step(function() { return gen.next(undefined); }); });}如果你有更好的答案或想法,欢迎在这题目对应的github下留言:https://github.com/airuikun/W…第 5 题:1000-div问题难度:阿里p5 ~ p6、腾讯t21 ~ t22一次性插入1000个div,如何优化插入的性能使用Fragment var fragment = document.createDocumentFragment(); fragment.appendChild(elem);向1000个并排的div元素中,插入一个平级的div元素,如何优化插入的性能先display:none 然后插入 再display:block赋予key,然后使用virtual-dom,先render,然后diff,最后patch脱离文档流,用GPU去渲染,开启硬件加速如果你有更好的答案或想法,欢迎在这题目对应的github下留言:https://github.com/airuikun/W…第 6 题:(开放题)2万小球问题:在浏览器端,用js存储2万个小球的信息,包含小球的大小,位置,颜色等,如何做到对这2万条小球信息进行最优检索和存储难度:阿里p7、腾讯t31你面试阿里和腾讯,能否上p7和t31,就看你对开放题能答有多深和多广。这题目考察你如何在浏览器端中进行大数据的存储优化和检索优化。如果你仅仅只是答用数组对象存储了2万个小球信息,然后用for循环去遍历进行索引,那是远远不够的。这题要往深一点走,用特殊的数据结构和算法进行存储和索引。然后进行存储和速度的一个权衡和对比,最终给出你认为的最优解。我提供几个能触及阿里p7和腾讯t31级别的思路:用ArrayBuffer实现极致存储哈夫曼编码 + 字典查询树实现更优索引用bit-map实现大数据筛查用hash索引实现简单快捷的检索用IndexedDB实现动态存储扩充浏览器端虚拟容量用iframe的漏洞实现浏览器端localStorage无限存储,实现2千万小球信息存储这种开放题答案不唯一,也不会要你现场手敲代码去实现,但是思路一定要行得通,并且是能打动面试官的思路,如果大家有更好的idea,欢迎大家到我的github里补充:https://github.com/airuikun/W…第 7 题:(开放题)接上一题如何尽可能流畅的实现这2万小球在浏览器中,以直线运动的动效显示出来难度:阿里p6+ ~ p7、腾讯t23 ~ t31这题考察对大数据的动画显示优化,当然方法有很多种。但是你有没有用到浏览器的高级api?你还有没有用到浏览器的专门针对动画的引擎?或者你对3D的实践和优化,都可以给面试官展示出来。提供几个思路:使用GPU硬件加速使用webGL使用assembly辅助计算,然后在浏览器端控制动画帧频用web worker实现javascript多线程,分块处理小球用单链表树算法和携程机制,实现任务动态分割和任务暂停、恢复、回滚,动态渲染和处理小球如果大家有更好的idea,欢迎大家到我的github里补充:https://github.com/airuikun/W…第 8 题:(开放题)100亿排序问题:内存不足,一次只允许你装载和操作1亿条数据,如何对100亿条数据进行排序。难度:阿里p6+ ~ p7、腾讯t23 ~ t31这题是考察算法和实际问题结合的一个问题众所周知,腾讯玩的是社交,用户量极大。很多场景的数据量都是百亿甚至千亿级别。那么如何对这些数据进行高效的操作呢,可以通过这题考察出来。以前老听说很多人问,前端学算法没有用,考算法都是垃圾,面不出候选人的能力其实。。。老哥实话告诉你,当你在做前端需要用到crc32、并查集、字典树、哈夫曼编码、LZ77之类东西的时候已经是涉及到框架实现和极致优化层面了 那时你就已经到了另外一个前端高阶境界了所以不要抵触算法,可能只是我们目前的眼界和能力,还没触及到那个层级我前面已经公布了两道开放题的答案了,相信大家已经有所参悟。我觉得在思考开放题的过程中,会有很多意想不到的成长,所以我建议这道题大家可以尝试自己思考一下。本题答案会在周五公布到我的github上。对应的github地址为:https://github.com/airuikun/W…第 9 题:(开放题)a.b.c.d和a’b’[’d’],哪个性能更高难度:阿里p7 ~ p7+、腾讯t31 ~ t32别看这题,题目上每个字都能看懂,但是里面涉及到的知识,暗藏杀鸡这题要往深处走,会涉及ast抽象语法树、编译原理、v8内核对原生js实现问题直接对标阿里p7 ~ p7+和腾讯t31 ~ t32职级,我觉得这个题是这篇文章里最难的一道题,所以我放在了开放题中的最后一题大家多多思考,本题答案会在周五公布到我的github上对应的github地址为:https://github.com/airuikun/W…第 10 题:git时光机问题难度:阿里p5 ~ p6+、腾讯t21 ~ t23现在大厂,已经全部都是用git了,基本没人使用svn了很多面试候选人对git只会commit、pull、push但是有没有使用过reflog、cherry-pick等等,这些都很能体现出来你对代码管理的灵活程度和代码质量管理。针对git时光机经典问题,我专门写了一个文章,轻松搞笑通俗易懂,大家可以看一下,放松放松,同时也能学到对git的时光机操作《git时光机》结语本人还写了一些前端进阶知识的文章,如果觉得不错可以点个star。blog项目地址是:https://github.com/airuikun/blog我是小蝌蚪,腾讯高级前端工程师,跟着我一起每周攻克几个前端技术难点。希望在小伙伴前端进阶的路上有所帮助,助力大家进入自己理想的企业。交流欢迎关注我的微信公众号,微信扫下面二维码或搜索“前端屌丝”,讲述了一个前端屌丝逆袭的心路历程,共勉。 ...

April 15, 2019 · 1 min · jiezi

前端程序员应该往全栈方向发展吗?坚守前端怎么样呢?

虽然本身能写几种代码,始终不觉得自己是全栈工程师,全栈工程师其实是全能的一种表现,现在很多人把懂得前端又能开发后端的技术工程师成为全栈工程师,对于一个前端技术人员在掌握本身技能的情况下,如果能在后端上发力做点事情,无疑能拓展技术道路宽度,虽然就技术工种来讲,专注于一个方向长时间的积累更加容易出成绩,如果从技术拓展的角度考虑,懂得里面背后是如何实现的其实也是在从更加深层次了解知识框架,了解对应后端模块如何实现,在设计前端的数据结构的时候更加容易规避问题。前端程序员应该往全栈方向发展吗?坚守前端怎么样呢?最后,如果大家如果在自学遇到困难,想找一个前端的学习环境,可以加入我们的前端学习圈,点击我加入吧,会节约很多时间,减少很多在学习中遇到的难题。前端最近几年变得非常火热了,也是各大培训机构的最爱,在前几天基本上培训几个月就能很快找到工作,毕竟前端相对来讲比较容易入门,而且前端的框架工具也非常多,但前端成为高手可不是那么容易,前端主要html,css,JavaScript三种编程脚本,JavaScript是核心这种脚本越用越会觉得这种脚本的奇妙性,在编程领域有一种惯性,越是容易入门的编程语言,越是难以成为高手。前端编程最初网站不是很重视,主要桌面版的页面的要求不是炫酷,随着移动端的大方面的普及,对于前端的需求激增,现在很多app都直接采用H5的方式了,所以前端在未来一段时间内市场需求还不不会低了。前端程序员应该往全栈方向发展吗?坚守前端怎么样呢?前端程序员如何规划技术生涯?1.基本的前端知识必须具备前端基础学习学起来非常快,主要还是JavaScript基础语法的学习,还要各种框架的应用,先做到能够使用的程度,伴随着技术的进步,常见的基本的功能可能只需要调用基本的库就能完成了,基础阶段就是以单纯的学习如何使用为主,完成基本的页面布局功能以及动画功能。前端程序员应该往全栈方向发展吗?坚守前端怎么样呢?2.性能和稳定性前端包含着大量的代码量,同样的功能不同层次的工程师会给出不同的结果,越是到了后期老工程师越是不轻易去触碰代码,把什么事情都想明白了再去实施,就要考虑如何用最优的代码实现功能,毕竟前端的性能也是非常重要的一个指标,效果非常好但性能非常差,用户体验就会大幅度下降,所以前端不能仅仅考量如何实现,在设计上也要慢慢融入自己的思想,这样纵观整体考量更加容易制造出高质量的前端页面。前端程序员应该往全栈方向发展吗?坚守前端怎么样呢?3.横向扩展和前端交叉主要两个方向,设计和后端,如果在前端自身已经掌握差不多情况下,就可以考虑在对接层开始全面的对接,特别是如果懂得和前端对接的后端部分,将完成前后端的贯穿,对于前端的认知又到了一个新的层面。不要排斥去学习后端的知识,编程到了一定层面就是编程思想的问题了,直接涉猎也不会存在非常难点的问题,到最后还是决心问题。一个程序员首先要有在行业内立足的专业知识,现有生存的专业,然后再全面拓展知识的广度。时间长了积累多了,年龄问题也不会一直困扰程序员了,最后影响因素还是全面的技术能力,这个方向在市场上没有竞争力,就可以切换到别的方向,具备这种综合能力,就可以做一个技术常青树了。

April 14, 2019 · 1 min · jiezi

Chrome 75 将原生支持图片的惰性加载

随着浏览器性能的提升,前端也越来越关注用户体验,而影响用户体验其中一个很重要的指标便是受首屏渲染速度。我们常常会针对样式、脚本、图片、音频、视频等资源做处理,比如针对样式和脚本的压缩合并,将图片合并成雪碧图、将小图转化成base64、延迟加载等减少网络请求次数。现在大部分web应用含有大量的图片,对图片进行延迟加载无疑极大提升用户体验。以往我们可能会通过对比底部图片据可视区底部距离、窗口高度、滚动条距离来判断是否加载新图片,抑或在支持IntersectionObserver API的浏览器中使用交叉区观察者进行监听,而这都需要我们写脚本去判断及控制。今天给大家带来好消息是,Chrome 75 将原生支持图片的惰性加载,支持对img和iframe进行延迟加载,只需要将loading属性设置为lazy即可。<img src=“celebration.jpg” loading=“lazy” alt="…" /><iframe src=“video-player.html” loading=“lazy”></iframe>loading属性Loading属性控制浏览器是否延迟加载屏幕外的图像和iframe:lazy:对资源进行延迟加载。eager:立即加载资源。auto:浏览器自行判断决定是否延迟加载资源。默认效果(不设置该属性)和loading=auto的效果保持一致。需要注意的是,若浏览器决定该资源适合延迟加载,则需要避免页面不正常显示和影响用户体验。该loading属性支持img标签,无论img标签是否含有srcset属性及被picture标签包裹,以及iframe标签。示例代码:<!– Lazy-load an offscreen image when the user scrolls near it –><img src=“unicorn.jpg” loading=“lazy” alt=".."/><!– Load an image right away instead of lazy-loading –><img src=“unicorn.jpg” loading=“eager” alt=".."/><!– Browser decides whether or not to lazy-load the image –><img src=“unicorn.jpg” loading=“auto” alt=".."/><!– Lazy-load images in <picture>. <img> is the one driving image loading so <picture> and srcset fall off of that –><picture> <source media="(min-width: 40em)" srcset=“big.jpg 1x, big-hd.jpg 2x”> <source srcset=“small.jpg 1x, small-hd.jpg 2x”> <img src=“fallback.jpg” loading=“lazy”></picture><!– Lazy-load an image that has srcset specified –><img src=“small.jpg” srcset=“large.jpg 1024w, medium.jpg 640w, small.jpg 320w” sizes="(min-width: 36em) 33.3vw, 100vw" alt=“A rad wolf” loading=“lazy”><!– Lazy-load an offscreen iframe when the user scrolls near it –><iframe src=“video-player.html” loading=“lazy”></iframe>检测属性支持判断浏览器是否支持loading属性<script>if (’loading’ in HTMLImageElement.prototype) { // Browser supports loading..} else { // Fetch and apply a polyfill/JavaScript library // for lazy-loading instead.}</script>浏览器兼容一个新特性的出现必然无法立即兼容所有的浏览器,这需要我们结合以往的data-src进行懒加载的方式作向后兼容,而不是使用src、srcset、<source>,以避免不支持原生懒加载功能的浏览器对资源进行立即加载。<img loading=“lazy” data-src=“pic.png” class=“lazyload” alt="." />不支持原生懒加载的浏览器,我们使用lazySizes库进行兼容(async () => { if (’loading’ in HTMLImageElement.prototype) { const images = document.querySelectorAll(“img.lazyload”); images.forEach(img => { img.src = img.dataset.src; }); } else { // Dynamically import the LazySizes library const lazySizesLib = await import(’/lazysizes.min.js’); // Initiate LazySizes (reads data-src & class=lazyload) lazySizes.init(); // lazySizes works off a global. }})();请求细节原生懒加载在页面加载时获取前2KB的图像。如果服务器支持范围请求,则前2KB可能包含图像尺寸,这使我们能够生成/显示具有相同尺寸的占位符。当然前2KB也可能包括像图标这样的资产的整个图像。尝鲜在本篇文章发布时,chrome最新版本是73.0.3683.103,但我们可以通过启用浏览器的实验性功能开启这一特性。在chrome://flags页面搜索lazy,将Enable lazy image loading和Enable lazy frame loading设置为Enabled,重启浏览器即可。参考AddyOsmani.com - Native image lazy-loading for the web!Twitter - AddyOsmani 原帖欢迎关注公众号「前端新视界」获取前端技术前沿资讯,后台回复“1”领取100本PDF前端电子书籍。 ...

April 13, 2019 · 1 min · jiezi

Chrome 75将原生支持图片的延迟加载!

加载页面时图片一直是流量的大头,过多的图片会严重影响页面的加载速度,针对图片的性能优化方法有诸如base64、雪碧图等等,延迟加载也是其中一种普遍使用的方法。延迟加载即图片的懒加载或惰性加载,当页面初次加载时只加载显示可视区域的图片,页面滚动时,图片进入了可视区域才会进行资源的加载。过去我们一直通过js来实现图片的延迟加载,而chrome75的到来将原生支持该功能!其实去年2月份Chrome就首次提出内置的图片和iframe延迟加载机制,并在8月的Canary版本中加入实验性功能对其进行了测试,最近Google技术经理Addy Osmani已经宣布今年5月底Chrome 75将会默认开启延迟加载的功能。浏览器启用实验性功能对该功能进行体验和测试需要:下载最新版本Chrome Canary。在chrome://flags中将Enable lazy image loading和Enable lazy frame loading设置为Enabled。重启浏览器。loading属性Loading属性控制浏览器是否延迟加载屏幕外的图像和iframe:lazy:对资源进行延迟加载。eager:立即加载资源。auto:浏览器自行判断决定是否延迟加载资源。默认效果(不设置该属性)和loading=auto的效果保持一致。需要注意的是,若浏览器决定该资源适合延迟加载,则需要避免页面不正常显示和影响用户体验。检测属性支持判断浏览器是否支持loading属性(有坑,文章后面会说):if (’loading’ in HTMLImageElement.prototype) { // 浏览器原生支持 loading 属性..} else { // 通过js实现}浏览器兼容需要使用例如data-original这样的属性名标记资源地址(而不是src、srcset或<source>),以避免在不支持该属性的浏览器中立即加载资源:<img loading=“lazy” data-original=“pic.png” class=“lazy” alt="." />若浏览器支持loading属性,则把data-original替换为src;若不支持则使用回原来延迟加载的方法:const images = document.querySelectorAll(“img.lazy”);if (’loading’ in HTMLImageElement.prototype) { images.forEach(img => { img.src = img.dataset.original; });} else { const LazyLoad = await import(’/lazyload.min.js’); let lazyLoadInstance = new LazyLoad({ elements_selector: “img.lazy” });}图片支持类型看到这个新功能后本来有个想法是,可以结合SVG注入器实现SVG的延迟加载:<img loading=‘lazy’ src=“warning.svg” onload=“SVGInject(this)” />但发现对于SVG类型文件,延迟加载并没有生效:经个人不完全测试,以下为图片类型的支持程度:图片类型是否支持JPEG支持GIF不支持PNG支持APNG不支持SVG不支持重复请求需要注意的是,Chrome会在页面加载时请求需要延迟加载图片的前2048个字节,当用户即将滚动到图片时,Chrome会再次请求剩余的图片字节(不会影响该图片的onload事件)。若服务器支持范围请求,则会在前2048个字节中包含图片尺寸,浏览器会生成/展示相同大小的占位:各方态度火狐:Firefox的一位工程师表示,Mozilla目前还没有任何计划实现Chrome的延迟加载方案。Microsoft Edge:新的Edge浏览器使用了Chromium 75内核,经下载泄露版本测试,该版本在edge://flags/中开启实验性功能,可支持延迟加载,且也会重复请求资源,但HTMLImageElement.prototype无loading属性,只有load属性,需进行区分判断处理。Safari:一位WebKit开发者提到,Apple对这类功能很感兴趣:其他:在WICG上关于原生支持延迟加载图片的讨论。总结在原代码的基础上更新兼容新功能并不复杂,但在启用新功能前可能需要进一步的思考,比如若对所有图片设定loading=“auto”,某些被延迟加载的图片是否会影响用户体验的流畅性?浏览器对图片进行延迟加载的判断与决定是否会影响页面性能?对大量图片进行延迟加载,浏览器会先请求所有延迟加载图片的前2048个字节,在弱网环境下是否会卡在这个阶段反而耽误了首屏图片的加载?其他浏览器是否会遵循这种规范?emmm虽然问题有点多但新功能还是可以带来新玩法~比如以后支持SVG后可对其进行延迟加载,设定loading=“eager"可对首屏重要的大图优先进行加载,对于广告(iframe或图片)的数据统计可更加精准(设定延迟加载并在onload事件中统计)…参考AddyOsmani.com - Native image lazy-loading for the web!Firefox will support image lazy loading for new tab page | ZDNetTwitter上原讨论贴 ...

April 13, 2019 · 1 min · jiezi

fe5-1:HTML知识

head标签定义的东西不显示出来,样式、编码之类的title标签设置网站的页面文件的标题(网站名)meta 中chaeset用来声明网页编码body标签定义的为显示内容input标签用于定义输入框br相当于网页上的回车(换行)<!– 例子 –>:这是HTML的注释<!DOCTYPE html><html> <head> <meta charset=“utf-8”> <title>Dome</title> <style> .radio-button { display: inline-block; padding: 10px; cursor: pointer; } .active { background: red; } </style> </head> <body> <!– 注意, 每个标签都有 class 和 id 这两个属性 –> <!– class 可以重复, id 不能重复 –> <div class=login-form> <input id=id-input-username type=“text” value=“mengxin”> <br> <input id=“id-input-password” type=“password” value=“mengxin”> <br> <button id=“id-button-login”>登录按钮</button> </div> <!– 这是一个选项卡的例子 –> <div class=“radio-control”> <!– 可以设置多个 class, 用空格分开 –> <span class=“radio-button active”>html</span> <span class=“radio-button”>js</span> <span class=“radio-button”>css</span> </div> <!– –> </body></html> ...

April 13, 2019 · 1 min · jiezi

vs code 插件折腾记(二)

6.Bracket Pair Colorizer一个可以更好的区分代码嵌套关系的插件;使用相同的颜色标识匹配同一组括号7.CSS Peek允许窥视css ID与类 字符串作为从html文件到相应CSS的定义,功能十分强大;Ctrl+Shift+F12:内联加载css文件并在那里进行快速编辑F12:直接跳转到css文件或在新编辑器中打开它Ctrl+hover:用鼠标悬停在符号上显示定义Ctrl + T:搜索类或ID名称;快速跳转到正确的CSS / SCSS / LESS代码Alt + F12/hift + F12:在当前html窥视与修改代码8.cssrem一个CSS值转REM的VSCode插件,移动端开发利器9.jQuery Snippets只需键入字母’jq’即可获得所有可用jQuery代码片段的列表,常用jquery开发必备

April 12, 2019 · 1 min · jiezi

HTML5、js、CSS3的自定义表情编辑器

跟大家分享一个款基于HTML5、js、CSS3的自定义表情编辑器您可以在编辑器中为该人脸表情添加和改变各种面部表情、给它戴上帽子,戴上围巾,甚至可以将其他任意Emoji表情添加上去,是不是很酷。源码我已经分享出来了,希望对大家学习HTML5、js、CSS3有帮助。点我预览 点我下载本文作者:IT放大镜欢迎扫描二维码关注公众号,聚焦于IT,每天推送专业IT知识及行业资讯

April 12, 2019 · 1 min · jiezi

前端知识归纳

技能考察:一、关于Html1、html语义化标签的理解; 结构化的理解; 能否写出简洁的html结构; SEO优化 a、理解:根据内容的结构化(内容语义化),选择合适的标签(代码语义化)便于开发者阅读和写出更优雅的代码的同时 让浏览器的爬虫和机器很好地解析。结构化:头部header、侧栏sider、主体内容main、尾部footer. b、作用:没有css,也能呈现内容结构、代码结构;用户体验;有利于SEO;方便设备解析;利于团队开发和维护;2、h5中新增的属性; 如自定义属性data, 类名className等, 新增表单元素, 拖拽Drag a、在html标签自定义属性"data-xxx",js可以通过dataset设置"data-xxx"自定义属性 b、新增表单元素:datalist、keygen、output3、h5中新增的API, 修改的API, 废弃的API 稍作了解 (离线存储, audio, video)a、localStorage:一直存储在本地,直到手动清除; sessionStorage:页面关闭则缓存清空;b、audio音频(兼容苹果用touchstart)、video视频二、关于CSS1、CSS选择器( 三大特性 )a、层叠性:标签的多个重复的样式,一个属性会覆盖另外一个属性,比如设置一个红色背景,一个黄色背景,只能取其一。b、继承性:子标签会继承父标签样式c、优先级:!important>行内样式>id选择器>类选择器>标签选择器>通配符>继承2、 BFC机制a、创建了BFC的元素中,在垂直方向上的margin会发生重叠。根元素<html>就是一个BFC元素(这个可以解释margin重叠)b、BFC元素在页面上是一个独立的容器,外面的元素和里面的元素互不影响。c、BFC元素不会和浮动的元素重叠。(这个可以解释两栏自适应)d、计算BFC元素高度时,里面浮动元素3、 盒模型a、框模型,包含了元素内容(content)、内边距(padding)、边框(border)、外边距(margin)几个元素。b、元素框的总宽度 = 元素(element)的width + padding的左边距和右边距的值 + margin的左边距和右边距的值 + border的左右宽度; 元素框的总高度 = 元素(element)的height + padding的上下边距的值 + margin的上下边距的值 + border的上下宽度。c、w3c标准盒模型: width和height不包括padding和border ie盒模型: width和height包含padding和border4、CSS模块化开发(封装); SCSS和LESS的使用a、scss安装使用npm,less使用ruby5、屏幕适配 以及 页面自适应a、百分比布局b、文字大小用remc、媒体查询6、CSS3中新增的选择器子元素选择器,相邻兄弟选择器,通用兄弟选择器,群组选择器7、CSS3中新增的属性, transform trasition animation等…a、transform: translate,translateX,translateY在水平方向、垂直方向或者两个方向上平移元素b、transform: scale、scaleX、scaleY在水平方向、垂直方向或者两个方向上缩放元素c、transform: rotate 旋转元素d、transform: skew,skewX,skewY在水平方向、垂直方向或者两个方向上使元素倾斜一定的角度e、transform: matrix三、关于布局标准文档流(padding + margin + 负margin) + 浮动float + 定位百分比布局(流式布局): px单位 用 %num代替, 占父级元素的百分比flex弹性布局: 主轴 辅助轴的几个属性grid栅格布局: 使用框架中的类名来替代: 本质上还是百分比布局四、关于JS基础1. 变量数据类型及检测: 基本 + 引用2. 运算符: 算术 + 条件 + 逻辑 + 位 + 短路, 隐式转换等 3. 条件, 循环, 异常处理 if switch(){case xxx:} try catch finally throw 4. 函数定义, 调用方式(apply, call, 直接调用), 传参: 实参给形参赋值5. 字符串, 数组, 对象常用API, 6. 正则表达式五、关于JS高级1. 作用域, 作用域链, 闭包2. 原型, 原型链, 继承3. 函数上下文, this指向4. js的运行机制, 事件队列和循环5. Ajax原理, axios库6. 同步, 异步编程7. jQuery源码学习六、关于浏览器 1. 浏览器的构成和运行机制, 2. 浏览器内核 3. 浏览器交互: BOM和DOM相关webApi, 监听事件 4. 浏览器缓存机制 5. 浏览器的渲染原理 6. 浏览器的安全性: 跨域 和 攻击七、关于网络协议 1. HTTP协议 2. cookie, session, token八、关于ES6语法 1. 字符串, 数组, 对象 扩展的api 2. 变量扩展: let const 解构赋值 块级作用域 3. 函数扩展: 箭头函数 默认参数, rest参数 4. 展开运算符, 模板字符串 5. set 和 map数据结构 6. 迭代器和生成器函数 next 和 yield的理解 7. proxy对象 属性代理器: 属性的读取(get)和设置(set)相关操作 8. promise对象, 异步编程的解决方案 9. async + await: 异步编程的终极方案 promise + generator的语法糖 10. class语法 构造函数的语法糖 11. 模块化编程 export + import 的 导出和导入九、VUE基础 1. 基本指令 2. 实例的 属性 和 方法 3. 实例的生命周期 4. 组件基础: 创建,注册,添加属性方法,套用等… 5. 组件通信传值 父子, 兄弟, 跨级 6. 插槽slot 等…十、VUE高级 1. vue-router: 搭建SPA 路由,组件的配置 路由间的传值 路由跳转 路由的导航守卫 记住在router.js 和 组件页面中的使用方式 2. vuex: 状态管理: 数据仓库store 实例化仓库的5大属性的使用 state, getters, mutations, actions, modules 辅助函数mapState等…, 仓库中计算属性的映射, 方便操作 记住在 store.js 和 组件中 使用方式十一、VUE深入, 源码阅读 1. 数据响应式原理 2. virtual dom 3. diff 算法 4. nextTick等等… 工程能力考察:一、项目能力 1. vue-cli脚手架搭建 和 功能配置 vue.config.js 2. webpack的常用配置 3. 项目构建 打包 4. 熟悉各类框架的文档… 5. UI框架: Bootstrap, MUI, Element-ui等 6. 常用的插件整理, 整理一个自己插件库, 封装自己的方法库,组件库 7. 常用的工具熟练度 8. PC端 和 移动端开发注意事项 9. 经验总结: 快速确定项目的技术选型 10. 坑点总结: 项目遇到坑坑坑!!! 11. 项目中的性能优化记录 ( 都是细节点…多记录 ) 12. 需求文档的理解, 可以结合 项目流程图, UML图 13. 问题解决能力: (bug定位调试, 查找文档, 寻求他人…) 14. 记录习惯养成二、模块化, 组件化开发能力 1. 项目分类; 各类文件整理,分类 2. 各类功能封装 3. 组件和功能模块的抽离, 解耦, 复用内功考察:一、面向对象的编程思想 1. 类的抽象 2. 对象的封装, 继承 为了更好的去管理数据, 分类数据 实现高内聚, 低耦合二、设计模式 设计模式感觉也是 将面向对象思想 再度抽象成现实中 某些特定模式三、数据结构和算法 学习常用的排序搜索算法, 顺序表,链表,栈,队列,树,堆 结构等等… 考验你的 抽象思维 和 数学功底了 将现实需求 抽象成 计算机代码 的思维能力附加技能考察:一. 学习能力持续学习的态度–博客, 笔记记录技术论坛活跃度高, 问答多GitHub开源项目参与二. 了解一门后端语言python, node.js, php等…数据库mysql,redis,mongodb. sql的操作语句, mongo的操作语句, redis操作语句node + express 搭建本地服务等python + django + request + scrapy三. 系统编程Linux命令行操作, 系统文件管理多任务, 多线程, 多进程, 协程, 并发, 并行, 串行, 同步, 异步等概念的理解 ...

April 12, 2019 · 2 min · jiezi