以下是前端开发来的一些有用的小技巧。
网页顶部100%高度
任何一个有节操的网页设计师都不会创造出一个带有100%可视区域高度的顶部的网页来,因为这样会造成很多问题。如果网页高度太窄,则100%顶部区域内的很多部件会错乱(显示不全、导航条位置错误等等)。
然而好马虽多,良驹尤少。面临一份带有100%高度顶部的设计图时,妄图使用100vh
或者Javascript来即时调整文档结构的办法都是不切实际而且注定失败的。对于第一种方法来说,首先有兼容性问题,其次在移动Safari浏览器下有bug。第二种方法来说,使用Javascript来调整结构无异于杀鸡取卵,高射炮打飞机的行为,不仅会让网页变慢性能降低,还会让人产生脱裤子放屁的错觉。
正确的办法是使用如下代码。优点:无兼容性问题,原生态速度快,可拓展性极强。
<div class="container">
<div class="head1"></div>
<div class="head2"></div>
<div class="content">
<div class="demo">
</div>
</div>
</div>
html,body,.container {
height: 100%;
margin: 0;
}
.head1 {
height: 100%;
position: relative;
background: gray;
}
.head2 {
height: 100%;
position: relative;
background: darkgray;
}
.demo {
height: 1000px;
background: lightgray;
}
正则表达式获取中英文字数
无需赘言。但此法与实际数字略有出入,主要是暂时无法识别中文段落中与中文混在一起的英文单词。需要继续改进。
let matches = openedFile.content.match(/[\u00ff-\uffff]|\s+/g) || [];
wordCount = matches.length;
基于textarea的简单代码编辑器
有时候不想使用Codemirror或者ACE这种巨型编辑器,又不想使用可编辑内容的div
,此时最没存在感的<textarea/>
就派上大用场。在这里简单谈一下编辑器的思路:
textarea速度快,用法简单,缺点是无法修改编辑内容。如想高亮代码,则非寻他路不可。然而,把textarea和pre结合起来,另有一番作为。具体做法是,设置textarea和pre完全相同的绝对位置组件,把pre置于textarea上,但设置pointer-event: none
忽略任何鼠标动作。而textarea则设定背景全透明,字体为任意颜色,设置-webkit-text-fill-color: transparent
从而隐藏textarea的文字但显示其光标(caret)。当用户看到编辑器时,他们以为自己在一个所见即所得的编辑器上,但实际上却是在textarea这个最简单的文字栏中。利用Prism.js来获取textarea的任何文字变动,并转换识别添加各种span
,可在CSS中编辑不同span
的颜色,从而达到代码高亮的目的。
这个方案一项重大问题是,如果文字超过一页(右侧出现滚动条)时,textarea和pre的文字会发生莫名错乱,导致光标位置与编辑位置不同。经调查,此为滚动条的出现导致textarea区域宽度变化,而断行的位置发生变化所致。解决办法为禁止textarea和pre的滚动,利用Javascript监听textarea的onWheel
事件,从而滚动二者,而滚动条则可以自己做一个。
Node应用中把HTML保存为PDF文件的方法
目前jsPDF是最好的生成PDF文件的工具,但是从现成的HTML直接转成PDF文件,jsPDF缺少CSS式样,因此十分难看。想到浏览器自带一种叫做“打印到PDF”的功能,因此利用此办法来生成PDF文件。具体做法为,把HTML内容添加一些标签(html
, head
, meta
, 等等)使用fs保存到一个临时文件中。打开一个隐藏的webview,加载该文件,触printToPDF函数。
把缩进数组转换成树
如果Jade语法来编辑HTML,语法为规范的缩进形式。在最近一个项目中想做一个JadeParser来解析Jade语法,则需要把Jade的行转化成一个树。即首先使用split()
函数把一篇Jade文档分成由行来组成的数组,并且通过计算空格得到该行的缩进值。比如:
[0, 0, 0, 1, 2, 2, 1, 2, 3, 0]
需要把这个数组完全转化为如下的结构:
[
0,
0,
0: [
1: [
2,
2
],
1: [
2: [
3
]
]
],
0
]
使用迭代函数来完成,代码如下:
class Line {
constructor(indent) {
this.indent = indent;
this.children = [];
}
}
class JadeParser {
constructor(jade: String) {
this.lines = [];
var split = jade.split('\n');
for (var i = 0; i < split.length; i++) {
if (split[i] !== '') {
let line = new Line(split[i]);
let father = this.findFather(line);
if (father) {
father.children.push(line);
} else {
this.lines.push(line)
}
}
}
}
findFather(line) {
if (this.lines.length === 0) return null;
var possibleFather = this.lines[this.lines.length - 1];
while (line.indent - 1 != possibleFather.indent) {
if (possibleFather.indent === line.indent) return null;
possibleFather = possibleFather.children[possibleFather.children.length - 1];
}
return possibleFather;
}
}