封装一个复制组件

应用场景: WEB/WAP 工程中有一些复制文本的需求,目的是为了减少用户的操作步骤。既然该功能比较常用,那就封装成组件吧。

API

1. document.execCommand

当一个HTML文档切换到设计模式(designMode)时,文档对象暴露execCommand方法,该方法允许运行命令来操纵可编辑区域的内容。

1
2
3
4
5
6
7
/**
*若bool = false 则表示document.execCommand方法不被当前浏览器支持或未被启用
*@property {String} aCommandName 命令的名称,如:copy/cut/paste【必选】
*@property {Boolean} aShowDefaultUI 是否展示用户界面,默认false【可选】
*@property {String} aValueArgument 一些命令(例如insertImage)需要额外的参数(insertImage需要提供插入image的url),默认null【可选】
**/
bool = document.execCommand(aCommandName, aShowDefaultUI, aValueArgument);

2. ClipboardEvent.clipboardData(注:实验中的功能)

ClipboardEvent.clipboardData 属性保存了一个 DataTransfer 对象,这个对象可用于:

  1. 描述哪些数据可以由 cut 和 copy 事件处理器放入剪切板,通常通过调用 setData(format, data) 方法;
  2. 获取由 paste 事件处理器拷贝进剪切板的数据,通常通过调用 getData(format) 方法
1
data = ClipboardEvent.clipboardData

Q: 那既然ClipboardEvent.clipboardData是实验中的功能,那兼容性就需要考虑了,那在IE低版本下如何实现将内容传给剪切板呢?
A:通过插入input节点,再通过input.select()方法选中内容的方式去hack,这总hack方式浏览器的兼容性更好。

基于Regular实现copy组件

Component - HTML:

1
2
3
4
<div class="command-container">
<div class="content {extendClass_content}" r-modal={content}>{content}</div>
<a class="u-btn u-btn_copy {extendClass_copy}" href="javascript:void(0)" on-tap={this.copy()}>{buttonTxt || '复制'}</a>
</div>

Component - JS:

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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
define([
'pro/widget/BaseComponent',
'pro/components/toast/toast',
'text!./copy.html',
], function(BaseComponent, toast, tpl) {
var Copy = BaseComponent.extend({
template: tpl,
config: function(data) {
this.supr(data);
},
copy: function() {
try {
this.clipCopy();
} catch(e) {
//低版本浏览器通过input方式hack复制兼容
this.inputCopy();
}
},
clipCopy: function() {
var data = this.data;
document.addEventListener('copy', function copy(evt) {
//将需要复制的内容传给系统的剪切板
evt.clipboardData.setData('text/plain', data.content);
evt.preventDefault();
});
var isCopySuc = document.execCommand('copy');
document.removeEventListener('copy', 'copy');
this.callback(isCopySuc);
},
inputCopy: function() {
var data = this.data;
var input = document.createElement('input');
input.style.display = 'none';
input.setAttribute('value', data.content);
document.body.appendChild(input);
input.select();
var isCopySuc = document.execCommand('copy');
document.body.removeChild(input);
this.callback(isCopySuc);
},
callback: function(isCopySuc) {
var data = this.data;
if (data.onSuccess && isCopySuc) { //copy组件实例复制成功回调
data.onSuccess();
return;
}
if (data.onFail && !isCopySuc) { //copy组件实例复制失败回调
data.onFail();
return;
}
// 若copy组件实例无相关回调,触发默认的toast
var message = isCopySuc? '复制成功': '不支持复制,请手动复制';
toast.toast({message: message, singleMsg: true});
}
});

return Copy;
});

兼容性:IE9+, AOS4.1+, iOS7.1+ (部分待验证)

copy组件使用文档:

Usage

1
<Copy content={ content }></Copy>

Props

参数 类型 默认值 说明
content String 【必选】复制的内容
extendClass_content String 【可选】内容框自定义class
extendClass_copy String 【可选】复制按钮自定义class
buttonTxt String 【可选】复制按钮自定义文字
onSuccess Function 【可选】复制成功回调函数
onFail Function 【可选】复制失败回调函数