由正则表达式如何匹配相同字符出发,讲讲正则表达式中的选择、分组和引用。
在外刊君读者群中看到有人提出这样的一个需求:
把字符串切成连续相同字符的正则怎么写?比如
abbcccdddd切成a,bb,ccc,dddd
之前我对正则表达式也是略有研究,想尝试一下。其实我对正则表达式的学习基本完全来源于犀牛书的第10章,真正看懂这一章,我觉得操作正则表达式应该不在话下。
先给出我的答案吧:
1 | 'abbccddd'.match(/(\w)\1*/g) // ["a", "bb", "cc", "ddd"] |
拿到这个问题,首先要匹配字符[a-zA-Z0-9],这里直接使用\w。然后是全局匹配,在最后加上g。难点在于怎么判断重复。
翻看了犀牛书后,又读了一遍分组和引用的部分。使用小括号()将字符作为一个最小单元,同时小括号还能记忆这个组合相匹配的字符串。再使用反斜杠\引用前面分组的表达式,数字1表示第一个小括号。这时完成了2个字符重复的要求。最后再使用*来匹配出现0次或n次。这个正则表达式就写完了。
下面详细说说分组和引用。
正则表达式的选择、分组和引用字符表
| 字符 | 含义 |
|---|---|
| ` | ` |
(...) |
组合,将几个项组合为一个单元,这个单元可通过* + ? ` |
(?:...) |
只组合,把项组合到一个段元,但不记忆与该组相匹配的字符 |
\n |
和第n个分组第一次匹配的字符相匹配,组是圆括号中的子表达式(也有可能是嵌套的),组索引是从左到右的左括号数,(?:形式的分组不编码 |
本文主要说明对这个博客主题的改版和代码重构的过程。这个简洁高雅的博客主题受到了很多朋友的喜欢。在写第一版界面时,我对前端并不是很熟悉,对Jekyll也不熟悉。现在距离当时也一年了,对自己当时写的代码也不太满意了,同时Jekyll如今也已经升级了,目前最新版为3.1.2。因此我在临近毕业尚未入职前做一下博客主题的代码重构和改版吧。
主要想做这些事情有:添加归档,添加标签,添加分类页面,主页显示文章摘要,代码去除 jQuery 和 BootStrap,优化移动端显示,将所有变量写入配置文件_config.yml中等。再优化一些细节吧。希望更多人会喜欢。
使用 GitHub 风格的代码块 Markdown 写法 (Fenced code blocks)。
即 GFM(github flavored markdown) 的方式。
Jekyll 已经升级至 3.1.2(2016-03),其中有一些新的要注意的地方,比如官网上说使用了 Rouge 去做代码高亮而不是默认的 Pygments,因为 Jekyll 本身是基于 Ruby 的,因此我看到官方说希望不再使用基于 Python 的 Pygments 了,而是都使用基于 Ruby 的代码。详情见官网升级说明 syntax-highlighter-changed。
首页中添加摘要
摘要可以在每一篇 md 文件头中使用 excerpt 属性写出来。也可以在正文中,4个换行符来分割,这个设置见配置文件_config.yml。
添加归档
上一版中没有归档,现在专门做了一个归档页面,当文章很多时方便根据年份快速查阅。
添加标签
标签还是很有必要添加的,上一版中也没有这个功能。现在也可以根据标签查找文章了。同时标签还有一个重要的作用是,用来获取相似文章的。
添加分类页
之前的分类就是在首页中直接完成的,现在和标签和归档类似,我将分类单独制作为一页,方便查阅。
去掉 jQuery 和 BootStrap
我觉得太重了,没必要使用这两个库,使用原生 JavaScript 和 CSS就可以做到一样的效果,代码量大大减轻,载入速度略有提高。
重写了demo页的瀑布流布局
改变数据写死的方式,将数据用 json 格式录入,由 JavaScript 拼接为 HTML 代码。同时,使用 Masonry,重写了瀑布流布局。
简化评论配置,支持 多说 和 disqus
在_config.yml中评论配置直接添加自己的short_name,评论就能正常使用了。
下面列举一些可能遇到的问题,至少我是遇到了:
以前我使用的是 RubyGems 的淘宝镜像https://ruby.taobao.org/。现在这个镜像已经不再维护了,作者 huacnlee (李华顺) 转到 Ruby China 中继续维护了,详情见 RubyGems 镜像- Ruby China。
在执行任何gem命令的时候出现以下错误:
1 | ERROR: While executing gem ... (Gem::RemoteFetcher::FetchError) |
根据 https://gems.ruby-china.org/ 页面最下方提供的 GitHub Issue 地址。
可以进入这个 issue:https://github.com/ruby-china/rubygems-mirror/issues/3
其中 sanlengjingvv 给出了一个链接地址 https://gist.github.com/fnichol/867550 里面提供了方法。我就是采用这里面的方法解决的。
我使用的是 The Manual Way,因为 The Ruby Way 我没有成功,不知道什么原因,有兴趣的朋友可以试试。下面说说我的具体操作吧。
首先从 https://curl.haxx.se/ca/cacert.pem 将文件cacert.pem下载至 C:\RailsInstaller\cacert.pem
然后执行
1 | set SSL_CERT_FILE=C:\RailsInstaller\cacert.pem |
就成功了,不会再出现 SSL 错误了。
最后原文中说,为了长久设置,将这个目录存入控制面板中。我没理解是什么意思,是指环境变量吗?有朋友知道的话,欢迎留言告知我。
我存入环境变量后,还是会出现 SSL 错误,这时再次执行上面那条命令即可。
因为 jekyll 3 中默认安装已经没有这个分页组件了,官方把这个分页组件插件化了,因此要独立安装。详情见 https://jekyllrb.com/docs/pagination/。
在启动 jekyll 服务的时候出现以下错误:
1 | jekyll serve |
我们安装这个插件到本地即可。
1 | gem install jekyll-paginate |
在本地使用命令
1 | jekyll serve |
出现错误,如下
1 | jekyll serve |
网上查阅后,这篇博文解决了我的问题。谁占了我的端口 for Windows –By Liu Xia, ThoughtWorks Senior Consultant. .NET Expert
上述报错主要原因是,jekyll 启动使用的4000端口被福昕pdf阅读器的自动更新进程占用了,关掉这个进程,jekyll在本地调试启动服务时就没有问题了。
简单的解决方法是:
输入命令,查看各端口被占用情况
1 | netstat -ano |
找到4000端口被占用的PID
我的结果如下:
1 | 协议 本地地址 外部地址 状态 PID |
可以看到4000端口的PID是2476。下面查看是什么进程,命令行中输入:
1 | tasklist /svc /FI "PID eq 2476" |
得到结果:
1 | 映像名称 PID 服务 |
可以看到正是福昕阅读器。下面关掉这个服务就好了。在 win10 中进入任务管理器,选择服务选项卡,关闭这个服务就好了,如下图:

当然也可以在启动jekyll服务的时候指定端口号,如下:
1 | jekyll serve --port 3000 |
这样在浏览器中输入 http://localhost:3000/ 就可以访问了。
还可以在配置文件_config.yml中添加端口号设置(参考官网文档-Serve Command OptionsPermalink),如下:
1 | # port |
此时,启动jekyll服务后,访问 http://localhost:1234/ 即可
起因是这样的,在尝试前后端分离的这条道路上,我自己也在不断摸索,感觉要把大部分的坑都踩踩了。目前我用的技术是:
但最近写了一个项目类似知乎这样的多页网站。前端 url 的处理让我觉得不够优雅。我使用的是 hash 的方式处理动态 url 的,为此我专门在知乎上提了一个问题:前端如何处理动态url?
这里我将问题描述如下:
前后端彻底分离的情况下,页面跳转页全部由前端控制。那么如何更好的处理动态url地址?
例如本问题的url为
https://www.zhihu.com/question/38802932
这肯定是用后台路由处理的url纯前端怎么处理?用hash吗,如下:
https://www.zhihu.com/question#38802932
那如果本页跳转,只改变hash的话,页面不会刷新。
使用location.reload()倒是可以解决。但总觉得这样处理不够优雅。大家在工作中是如何处理此类场景的?还是用传统的后台路由来提供动态url?
感谢郑海波和剧中人的热心回答。都提到了history对象中的pushState,这是我第一次接触到这方面的内容(顿时觉得自己真是才疏学浅)。
同时也有人提到了pjax,这个就是pushState+Ajax的封装,也很有意思。
下面就来研究和实践一下吧。
window对象通过history对象提供对浏览器历史记录的访问能力。它暴露了一些非常有用的方法和属性,让你在历史记录中自由前进和后退,而在 HTML5 中,更可以操纵历史记录中的数据。
back(), forward(), go(), length浏览器的历史记录就好像一个栈,最新的在最上面,较早之前看过的在下面。
如下图,Chrome的历史记录:

下面介绍怎么在这些历史记录中跳转,但要注意,上图中的浏览器历史记录和本文说的 history 还不太同。
back()
在历史记录中后退
history.back();
forward()
在历史记录中前进
history.forward();
go()
移动到指定的历史记录点
history.go(-1);
通过指定一个相对于当前页面位置的数值,你可以使用go()方法从当前会话的历史记录中加载页面(当前页面位置索引值为0,上一页就是-1,下一页为1)。
go()不填参数或参数为go(0)时,页面会刷新,即history.go()或history.go(0)相当于location.reload()
length
length为history的属性,显示history长度。
本节在线demo见:History & pjax demo 源代码:
经过亲自测试,history对象只记录同一个 tab 页内的历史。如果是在新窗口打开的,则无效。如:在a标签中添加target="_blank",或按住ctrl点击,这类场景下,在新的tab页中,history对象也是新的。
且history对象记录的信息与是否同源也无关,所以唯一要满足的就是同一个标签页。
pushState(), replaceState()HTML5 引进了history.pushState()方法和history.replaceState()方法,它们允许你逐条地添加和修改历史记录条目,能够在不加载新页面的情况下没改变浏览器的URL。这些方法可以协同window.onpopstate事件一起工作。
使用history.pushState()会改变referrer的值,而在你调用方法后创建的 XMLHttpRequest 对象会在 HTTP 请求头中使用这个值。referrer的值则是创建 XMLHttpRequest 对象时所处的窗口的 URL。
pushState(any data, string title, [string url])
第一个参数为history对象的state属性值,可以放任意数据,记录历史状态。第二个参数是新状态的标题,目前浏览器基本不支持。第三个参数为可选的相对url。
执行pushState后,可以在不加载新页面的情况下,更改url。同时history栈中新增一条数据。
例如,我们有这样一段代码:
<button id="push1">pushState()</button>
document.querySelector('#push1').addEventListener('click', function() {
history.pushState('abc','pushStatePageTitle','pushState.html');
document.querySelector('#length').innerHTML = history.length;//重新读取历史长度
});
当点击按钮的时候,页面不会刷新,但url地址的最后已经变为pushState.html。这一点非常像hash的作用,但比hash更优雅。
replaceState(any data, string title, [string url])
与pushState()类似,只是在history栈中不是新增记录,而是替换一条记录。
需要注意的是:pushState()和replaceState()方法存在安全方面的限制,本地测试是无效的,会报错,可以简单放到任何服务端测试,或者使用http-server开启简单服务器,通过访问localhost来查看效果。
本节demo见:History & pjax demo - pushState
现在再看本文一开始提出的问题,如何让前端优雅的控制 url,这里就可以考虑 pjax 技术了。我们把 pushState + ajax 进行封装,合起来简称为 pjax。虽然不是什么新的技术,但概念已然不同。
如果不使用 pjax。我们依然可以使用hash来实现文本开始的需求。但会不利于 SEO,看着也不够优雅。
Pjax的原理十分简单。
pushState()修改Url。个人理解3中也可以仅仅请求数据,再由浏览器渲染。
每当同一个文档的浏览历史(即history对象)出现变化时,会触发window.onpopstate事件。
window.onpopstate = function(event) {
console.log(event.state);
console.log(location);
};
这样在用户点击前进后退时也可以很好的监听url,来做相应的页面渲染。
若用户刷新了页面,但没有相应的页面资源,这时页面就会显示不存在。所以我认为较好的方法是在写pushState()第三个参数的时候,写为?a=1这样的参数形式。History.js 也是这么写的。但是这样应该会多一次请求。也许使用 nodeJS 作为中间层会好一些吧。
对于上述的探索,不知道是不是我还不够深入,总觉得还是不够完美。
做了一张思维导图。总结这几个月对 JavaScript 的学习吧,也是一个复习。也是我目前的技能树。

weinre官网 上有两句有意思的介绍:
weinre is WEb INspector REmote. Pronounced like the word “winery”. Or maybe like the word “weiner”. Who knows, really.
weinre is a debugger for web pages, like FireBug (for FireFox) and Web Inspector (for WebKit-based browsers), except it’s designed to work remotely, and in particular, to allow you debug web pages on a mobile device such as a phone.
上面说 weinre 是一个远程 web 调试器。说到了它的发音,还挺幽默,哈哈。
远程 web 调试器。先说调试器,就像火狐中的 FireBug,Chrome 中的调试器一样。就是在浏览器中按下 F12 出现的那个工具。但是在手机上,你没办法按 F12,而这个 weinre 就是在手机上的 F12,与传统的不同的是,它是在手机上浏览你的 web 页面,在 PC 上查看调试工具,非常方便,这就是所谓的远程。
现代浏览器中调试工具都非常强大了,可以直接模拟手机设备,为什么还要用 weinre 这么麻烦的东西呢?
我觉得 PC 端的浏览器虽说可以模拟,但模拟毕竟还是模拟,还只是鼠标长按滑来滑去。在开发过程中,使用手机或平板直接来感受是多么的酷,指尖在移动设备的屏幕上摩擦摩擦!给人的直观感受绝对秒杀浏览器的模拟。
使用一种工具之前,了解它的原理和结构是很有帮助的。weinre 作为一种远程调试工具,在结构上分为三层:
三层结构如下图所示:

weinre 的 debug 客户端是基于 Web Inspector 开发,而 Web Inspector 只与以 WebKit 为核心的浏览器兼容,所以 Weinre 的客户端只能用 Chrome 或者 Safari 打开。
官网上也有相应的平台支持说明:
Platforms supported - debug server 服务端
任何支持 node.js 的平台。
Platforms supported - debug client 客户端(跑 debugger 界面的浏览器)
Platforms supported - debug target 目标页面(在移动设备中调试运行的目标页面)
weinre 是 nodeJS 的一个应用,首先要 安装 nodeJS 运行环境
使用 npm 命令,安装 weinre
npm -g install weinre
安装成功后会有类似的信息:
C:\Users\haoyang\AppData\Roaming\npm\weinre -> C:\Users\haoyang\AppData\Roaming\npm\node_modules\weinre\weinre
weinre@2.0.0-pre-I0Z7U9OV C:\Users\haoyang\AppData\Roaming\npm\node_modules\weinre
├── underscore@1.7.0
├── nopt@3.0.2 (abbrev@1.0.7)
└── express@2.5.11 (mime@1.2.4, qs@0.4.2, mkdirp@0.3.0, connect@1.9.2)
启动服务
weinre --boundHost -all- --httpPort 8081
–boundHost [hostname | ip address | -all-]
The ip address to bind the server to.
–httpPort [portNumber]
The port to run the HTTP server on.
更多配置项参考 官网的说明。
启动成功后看到如下界面:

给目标页面添加一行脚本
可以看到 2.中的 Target Script 说要添加一行脚本到要调试的 web 页面中。
Target Script
You can use this script to inject the weinre target code into your web page.
http://localhost:8081/target/target-script-min.js#anonymous
Example:
<script src="http://localhost:8081/target/target-script-min.js#anonymous"></script>
这里要说明一下,要把上面的 localhost 换为本机的 ip 地址。
我们可以在命令行中 使用 ipconfig 得到 ip 地址,如下(当然你的可能和我的不一样):
IPv4 地址 . . . . . . . . . . . . : 192.168.1.107
即插入如下代码:
<script src="http://192.168.1.107:8081/target/target-script-min.js#anonymous"></script>
进入调试页面
PC 端访问这个地址:
debug client user interface: http://localhost:8081/client/#anonymous
此时 target 为 none,如下图:

现在我们要用手机访问同一个局域网下的这个目标页面。我们可以把要调试的页面放到这个路径下:
C:\Users\haoyang\AppData\Roaming\npm\node_modules\weinre\web
通过 http://192.168.1.107:8081/FILE_NAME 在手机上访问,就可以看到了。当然前提是同一个局域网。
但是这样可能不太灵活,每次都要把目标页面放到指定的目录下。所以我们可以另外开一个服务器。
我使用了基于 node.js 的 http-server 工具。将要调试的页面发布。这样我就能通过 ip 地址加端口号在手机上访问到了。
我在手机上访问 http://192.168.1.107:8080 打开要调试的页面,此时 debug client user interface 中自动检测到 target。就可以进行调试了!
如下图:


往前推2到3年,前端工程师还在忧心忡忡地想,移动互联网时代下,前端是不是没有生存空间了。但今天一看,在我们团队,前端工程师超过一半的工作都是在做移动端的Web或者APP的开发。移动Web或者APP在技术本质上是和做桌面端Web没有本质区别,但是移动端的坑那是非常的多,通过学习这部分内容,让你成为一名桌面移动通吃的前端开发工程师。
上面这个 slide 资料讲的非常好,算是一个入门的介绍吧。带我们建立基本的移动 web 开发知识体系和常见问题的实践。包含以下几个方面:
基本概念
Native
本地应用 使用 Java \ Objective-C \ Swift 开发
WebApp
网页应用 html5 开发
Hybrid
混合应用 ooxx(native, web)
对比
视觉
交互
实践
调试
浏览器自己的调试工具,模拟手机设备
weinre
关于 weinre 我写了一篇博客介绍它。Weinre –WebApp 调试工具
参考:
上面的链接详细的讲解了:
DOCTYPE
charset
lang属性
优先使用 IE 最新版本和 Chrome
360 使用Google Chrome Frame
SEO 优化部分:页面标题
为移动设备添加 viewport
viewport 可以让布局在移动浏览器上显示的更好。 通常会写
1 | <meta name ="viewport" content ="initial-scale=1, maximum-scale=3, minimum-scale=1, user-scalable=no"> |
content 参数:
ios 设备,iOS 图标,Android,Windows 8
总结:
1 | <!DOCTYPE html> <!-- 使用 HTML5 doctype,不区分大小写 --> |
关于 HammerJS 的一个中文文档
CSS语言由于其自身语言设计的问题,加上一些浏览器兼容性问题,往往会使得我们在写它的时候,要写很多冗余代码,或者为了兼容性对同一个样式设定写好几遍。针对这些问题,诞生了CSS预处理和后处理的概念及相关方法、工具。
这些工具和方法帮助我们能够更加高效地书写可维护性更强的CSS代码。
这里我尝试使用了 Sass,果然很好用。下面记录几个 sass 教程。
首先要有 ruby 环境。
由于国内网络原因(你懂的),导致 rubygems.org 存放在 Amazon S3 上面的资源文件间歇性连接失败。这时候我们可以通过gem sources命令来配置源,先移除默认的 https://rubygems.org 源,然后添加淘宝的源 https://ruby.taobao.org/,然后查看下当前使用的源是哪个,如果是淘宝的,则表示可以输入 sass 安装命令 gem install sass 了。
$ gem sources --remove https://rubygems.org/
$ gem sources -a https://ruby.taobao.org/
$ gem sources -l
*** CURRENT SOURCES ***
https://ruby.taobao.org
# 请确保只有 ruby.taobao.org
$ gem install sass
sass --watch style.scss:style.css --style expanded
rem
字体单位使用 rem,用户在手机上设置了字体大小时,不会打破布局,造成混乱。
安全是大家经常容易忽视,但其实一旦出现影响会非常大的问题,尤其对于没有经历过企业开发,或者没有踩过坑的同学,如果等到公司工作,做实际项目后非常容易发生安全问题。
WEB基本攻击大致可以分为三大类:“资源枚举”、“参数操纵” 和 “其它攻击”
跨网站脚本(Cross-site scripting,通常简称为XSS或跨站脚本或跨站脚本攻击)是一种网站应用程序的安全漏洞攻击,是代码注入的一种。它允许恶意用户将代码注入到网页上,其他用户在观看网页时就会受到影响。这类攻击通常包含了HTML以及用户端脚本语言。
XSS攻击通常指的是通过利用网页开发时留下的漏洞,通过巧妙的方法注入恶意指令代码到网页,使用户加载并执行攻击者恶意制造的网页程序。这些恶意网页程序通常是JavaScript,但实际上也可以包括Java, VBScript, ActiveX, Flash 或者甚至是普通的HTML。攻击成功后,攻击者可能得到更高的权限(如执行一些操作)、私密网页内容、会话和cookie等各种内容。
——维基百科
浏览器解析顺序:
HTML Parser >> CSS Parser >> JavaScript Parser
浏览器解码顺序:
HTML Decoding >> URL Decoding >> JavaScript Decoding
具体的防护方式:
对于 innerHTML 的方式输出的,我们可以采用如下的方式转码
1 | /** |
参考:
在自己做一些小项目时,可能是学校的一些网站项目,流量可能日均都不超过500,而且大多是校园局域网内访问;或者是开发一些实验室的MIS系统,这辈子你都不会去使用你开发的这个系统。在这样一些项目中,性能优化往往会被你忽略。
但是如果你是做一个日均PV数万、数十万、甚至更大的量级,开发的页面会被全国各地,不同网络条件的用户来进行访问。这个时候,性能问题就无法忽视了。在当今的网络条件下,如果你的页面3秒都无法完成首屏渲染,一定会让你的网站流失很多用户。
整个网站的性能优化有很多的环节和工作,大多数时候,不是前端工程师单独就能完成的,尤其在职能划分明确的公司中,往往需要前后端、运维、DBA等多个职位协同完成。所以,在我们的课程中,主要让你了解整个性能优化都涉及哪些方面的工作,同时,我们会专注介绍一些在前端领域可以重点关注的技术点。
这里就是网页的打开速度,如果你的网页打开速度很慢,那么一定会有用户的流失。所以性能优化很重要。
具体细节参考文章:
我在 ToDo 这个任务中主要使用了 CDN 来加载静态资源。比如我使用了 百度静态资源公共库。引用了里面的 fontawesome,速度果然比在 GitHub 仓库里快很多。下一步是压缩我自己写的静态资源。
其他参考资料:
对于一个复杂项目,特别是多人协作的复杂项目,如何合理划分模块,如何更加方便地进行模块加载,如何管理模块之间的依赖,是一个项目团队都会面临的问题,目前业界已经有了一些较为普遍的解决方案,如AMD。这个部分希望你能够通过学习JavaScript的模块化,学习如何合理地规划项目模块,合理使用模块化工具来优化你的项目代码结构。
一个模块就是实现特定功能的文件,有了模块,我们就可以更方便地使用别人的代码,想要什么功能,就加载什么模块。模块开发需要遵循一定的规范,否则就都乱套了。
根据AMD规范,我们可以使用 define 定义模块,使用 require 调用模块。
目前,通行的 js 模块规范主要有两种:CommonJS 和 AMD。
AMD 即 Asynchronous Module Definition,中文名是“异步模块定义”的意思。它是一个在浏览器端模块化开发的规范,服务器端的规范是 CommonJS
模块将被异步加载,模块加载不影响后面语句的运行。所有依赖某些模块的语句均放置在回调函数中。
AMD 是 RequireJS 在推广过程中对模块定义的规范化的产出。
详细 API 如下:
CommonJS 是服务器端模块的规范,Node.js 采用了这个规范。Node.JS 首先采用了 js 模块化的概念。
根据 CommonJS 规范,一个单独的文件就是一个模块。每一个模块都是一个单独的作用域,也就是说,在该模块内部定义的变量,无法被其他模块读取,除非定义为 global 对象的属性。
输出模块变量的最好方法是使用 module.exports 对象。
试想一下,如果一个网页有很多的js文件,那么浏览器在下载该页面的时候会先加载js文件,从而停止了网页的渲染,如果文件越多,浏览器可能失去响应。其次,要保证js文件的依赖性,依赖性最大的模块(文件)要放在最后加载,当依赖关系很复杂的时候,代码的编写和维护都会变得困难。
RequireJS就是为了解决这两个问题而诞生的:
(1)实现js文件的异步加载,避免网页失去响应;
(2)管理模块之间的依赖性,便于代码的编写和维护。
CMD(Common Module Definition) 通用模块定义。该规范明确了模块的基本书写格式和基本交互规则。该规范是在国内发展出来的。AMD是依赖关系前置,CMD是按需加载。
AMD 是 RequireJS 在推广过程中对模块定义的规范化产出。
CMD 是 SeaJS 在推广过程中对模块定义的规范化产出。
对于依赖的模块,AMD 是提前执行,CMD 是延迟执行。
AMD:提前执行(异步加载:依赖先执行)+延迟执行
CMD:延迟执行(运行到需加载,根据顺序执行)
业界目前有非常多的前端开发工具,完成一些开发过程中可以自动化完成的工作,提高研发效率,并且可以提高多人协作时的开发过程一致性,提高整个项目的运维效率。
在EFE日常工作中,我们是基于EDP,完成项目开发过程中的项目构建、包管理、调试、单测、静态检测、打包、压缩、优化、项目部署等一系列所有工作。
注:
如果网络不好,可以使用 淘宝 NPM 镜像。
在任务三中,做了一个 PC 端的 ToDo 应用。任务四是将它优化,以适应移动端设备。
数据存储
以 JSON 模拟数据表的形式存储于 LocalStorage 中
使用数据库的思想,构建3张表。
cateJson 分类
childCateJson 子分类
taskJson 任务
分类表 cate
----------------------
id* | name | child(FK)
----------------------
子分类表 childCate
--------------------------------
id* | pid(FK) | name | child(FK)
--------------------------------
任务表 task
----------------------------------------------
id* | pid(FK) | finish | name | date | content
----------------------------------------------
使用 Sass 重构了 CSS 代码
使用分块、继承等方式,使得代码更加清晰明了。
响应式布局
针对手机端细节做了很多调整,更符合手机上的视觉交互习惯。
加入页面切换效果
使用 translate3d(),纯 CSS3 切换动画效果。
处理了 XSS 防护
对可能造成破坏的字符进行转码。
性能优化
使用 CDN 处理静态资源 fontAwesome,压缩静态资源等
模块化
使用 requireJS 模块化 JavaScript 代码。重构 JavaScript 代码。优化之前写的耦合性高的绑定事件,重新绑定事件,降低耦合性。期间根据具体需求重写了事件代理的代码。
前端工程化
使用 gulp,自动编译 Sass,压缩 CSS 和 JavaScript 代码。并且配置了自动流程。
-webkit-tap-highlight-color 属性感谢 fiona 指出。
safari移动端点击的时候会闪一下加上 -webkit-tap-highlight-color: transparent; 就不会闪了。
参考:
为什么用 disabled 属性?
因为我发现仅仅使用 readonly 属性,在 IE 下是显示光标的。于是使用 disabled。
出现的问题
各家浏览器对于 disabled 属性有自己的样式设定,比如 IE 下是灰色的。苹果设备下也是。改变这些样式的方法也不是统一的。如果要兼容 Safari 必须加上
1 | background: #fff; |
于是最终代码如下:
1 | textarea:disabled { |
tag:
缺失模块。
1、请确保node版本大于6.2
2、在博客根目录(注意不是yilia根目录)执行以下命令:
npm i hexo-generator-json-content --save
3、在根目录_config.yml里添加配置:
jsonContent:
meta: false
pages: false
posts:
title: true
date: true
path: true
text: false
raw: false
content: false
slug: false
updated: false
comments: false
link: false
permalink: false
excerpt: false
categories: false
tags: true