简单的历史记录实现

时间:2015年03月17日 作者:剧中人

近来小剧又在发疯似的造一个轮子:mditor一款轻量的markdown编辑器。既然是编辑器,肯定少不了撤销Ctrl+Z 和 重做Ctrl+Y 功能。今天小剧就来说一说我是如何处理撤销、重做功能的。

其实撤销与重做,只是围绕历史记录在做的两个常用功能,下面小剧用比较逗比科幻的角度来解释与历史记录相关的几个概念。

历史记录 ,其自身是一组数据,用于记录一定时间内的操作,你可以把它理解为你自己最近几年主要活动的时空轨迹。

撤销,回到到上一步的操作,一款现实生活绝对买不到的后悔药。是穿越时空的超能力,撤销可以带你回到你最想去更改的某个时间点,也可以抹去刚刚不小心犯下的错误。

重做,也称之为恢复,假如你只是想回到过去看一眼,那你还有机会选择重做立即回到未来,继续现在的生活。

最大历史记录,最多可允许恢复的历史记录步数。每时空旅行者的超能力都有限度,只能在一定范围内的时空游走。

这四个概念给了时空穿梭极大的自由度,但有一点需要注意,历史记录仅仅是一条单行的线,你可以在时间线上前后穿越。一旦你回到某一个过去,改变了某一件小事,之后的时空便不复存在。相信看过《蝴蝶效应》的小伙伴都会了解,这里没有平行世界的概念呦!

小剧的胡言乱语了这么多,用这个疯癫的逻辑建立一个历史记录的模型就不是难事了,代码祭出。

简单的历史记录类

 /**
 * 历史记录
 **/
 function LOG(max){
 //历史记录存储字段
 this.data = [];
 //当前所处在的时间点
 this.current = -1;
 //最大历史记录
 this.maxLength = max || 20;
 }
 LOG.prototype = {
 //新的一步
 push: function(item){
 //已经有新的改变,若有时间线后的操作全部作废
 if(this.data.length > this.current + 1){
 this.data.length = this.current + 1;
 }
 this.current++;
 this.data.push(item);
 //超出最大历史纪录数,删除最早的历史记录
 if(this.data.length > this.maxLength){
 this.data = this.data.slice( -this.maxLength);
 this.current = this.maxLength - 1;
 }
 },
 //撤销
 undo: function(){
 if(this.current < 0){
 return null;
 }
 return this.data[--this.current];
 },
 //重做
 redo: function (){
 if(this.data.length > this.current + 1){
 return this.data[++this.current];
 }else{
 return null;
 }
 }
 };

有了这么一个简单的历史操作的类,就可以在自己的功能里包装历史记录功能了。规划好每次存储历史记录需要记下的字段,以及撤销、重做的时候,如何把存储的数据重新渲染到视图里。

简单的使用demo

/**
 * getPosition 和 setPosition为获取、设置光标位置的方法,细节不具体展开
 **/
var log = new LOG(20),
 $textarea = $('textarea');
$textarea.on('change',function(){
 //向历史记录列表追加记录
 log.push({
 selection : getPosition($textarea),
 content: $(this).val()
 });
});
$('.undo').click(function(){
 //撤销
 var step = log.undo();
 writeStep(step);
});
$('.redo').click(function(){
 //重做
 var step = log.redo();
 writeStep(step);
});
//绘制当前步骤
function writeStep(step){
 if(!step || !step.content){
 return
 }
 $textarea.val(step.content);
 setPosition($textarea,step.selection[0],step.selection[1]);
}

PS:为什么要有最大历史记录的限制?

这个限制一般软件都会有,特别因为这里是JS,完全是内存存储,自然不允许无限制存储历史记录。

本文关键字:历史记录 原理 javascript
转载请注明来源:http://bh-lay.com/blog/14c23552433

小剧客栈

小剧客栈是剧中人在成长路上的一个缩影,也希望借此结交更多前辈好友。分享小剧在前端、nodeJS、设计和web的各个细节上的点点滴滴,愿与你共同分享,一起进步!

相关链接

关于

关于剧中人 关于小剧客栈

design & code by @剧中人,base on nodeJS + mongoDB

感谢七牛提供近乎免费的CDN,阿里云提供的优质云服务,以及360云加速的给力支持。

皖ICP备14001331号-1

AltStyle によって変換されたページ (->オリジナル) /