Hao
Hi, I am Hao (👋): a coder, a woodworker, a blogger, and a father.
一些前端技巧
April 28, 2016

以下是前端开发来的一些有用的小技巧。

网页顶部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;
    }
}