经常会有这样一种需求:我需要把一段文字从一个设备发送到另一个设备,虽然确实会有很多解决办法,比如登陆QQ、微信,然后传过去,但是这些都需要繁琐的登陆步骤,并且有些时候你需要发送的设备是一台不可信的你不愿意在上面暴露自己账号密码的设备,所以想弄一个无需登陆的小Demo,花了四个小时,效果还不错。

#准备工作

#编辑器

网页访问应该是最方便快捷的方式了,所以这个小demo就依托 web。解决了框架的问题,下一个需要考虑的问题是选择什么样的前端编辑器。

最初的设想是采用一些开源的 markdown 编辑器,毕竟 markdown 是我最经常编写的文本样式了,也确实有一些很好看的编辑器:

但这背离了我的初衷,我要做的不是一个在线的编辑器,而仅仅是一个可以存放文本的编辑器,markdown的解析和预览需要很大的工作量,且样式不一定是我喜欢的。

最终我选择一款纯CSS3制作可编辑的微软Word样式文档,他的github地址

#数据存储

我的网站挂在GitHub上,只有前端没有服务器,如果仅仅只是为了一个小demo就迁移到服务器上,未免有些小题大做。
我的博客上其实就有基于后端的内容,用的是leancloud的服务,免费版的api限制是 3万次/天,对于个人日常使用完全足够。故本demo的数据存储与同步也同样使用 leancloud,相关的文档见数据存储开发指南 · JavaScript

#具体实现

这里只考虑js逻辑,其它详见代码。

#获取当前url参数

在线文档当然不能只有一个可编辑的页面,所以我的设想是获取 url 上的额外参数,以此作为文档的唯一ID,这样就可以有无数个文档可以存放内容,比如 /doc/?1/doc/?12 就是两个不同的文档。
而本身的域名可能发生改变,为了方便拓展, url 参数应该是去掉协议(https://)域名(xxxxx.com)端口号(80)后的结果。

1
2
// 获取当前url
var url = window.location.href.slice(window.location.href.indexOf('/doc/'));

#拉取远端数据

页面第一次加载时应该拉取远端的数据,来恢复文档内容(如果远端存在备份内容):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
AV.init({
appId: "jIRe5LRqbWDB2dxmu7FH8c1S-gzGzoHsz",
appKey: "xxxxxxxxxxxxxxxxx",
serverURLs: "https://jire5lrq.lc-cn-n1-shared.com"
});

var query = new AV.Query('DocSync');
query.equalTo('url', url);
query.find().then(function (docsync) {
// 拉取远端结果
if (docsync.length == 1) {
docEle.innerHTML = docsync[0].attributes.content;
content = docsync[0].attributes.content;
objectId = docsync[0].id;
}
});

#更新远端数据

数据更新的策略是,判断当前页面在远端是否有字段保留,如果有就更新字段即可,否则需要新增一条记录保存当前 url 的内容。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
function update() {
if (objectId == '') {
// 声明 class
var DocSync = AV.Object.extend('DocSync');

// 构建对象
var docsync = new DocSync();

// 为属性赋值
docsync.set('url', url);
docsync.set('content', docEle.innerHTML);

// 将对象保存到云端
docsync.save().then(function (docsync) {
// 成功保存之后,执行其他逻辑
console.log('保存成功。objectId:' + docsync.id);
objectId = docsync.id;
}, function (error) {
// 异常处理
console.log(error);
});
} else {
var docsync = AV.Object.createWithoutData('DocSync', objectId);
docsync.set('content', docEle.innerHTML);
docsync.save().then(function (docsync) {
console.log('更新成功。');
}, function (error) {
console.log(error);
});
}
content = docEle.innerHTML;
}

#更新策略

我设置的更新的策略是 10s 自动保存一次。

1
2
3
4
5
setInterval(function () {
if (docEle.innerHTML != content && docEle.innerHTML != '') {
update();
}
}, 1000 * 10);

#Demo

详见https://onns.xyz/doc/

#TODO

  • 因为是用 leancloud 服务,不清楚单个字段的大小限制,可能出现无法保存或无法完整保存的情况,需要编辑器加以限制。
  • 一些诸如保存时间、字数大小等控制信息的显示。
  • 编辑器本身支持很多功能,需要相关组件来丰富。
  • 由于接口调用限制,数据的远端拉取并未定时执行而只会在网页加载时执行一次,可以有更多合理的策略。
  • 更新策略也可以更智能,比如如果新增文字数大于阈值则马上更新。
  • 手机端UI不友好。

如果有建议欢迎留言~