版本 「 1.7.1 」
通过 npm 获得
npm install clipboard --save
<script src="dist/clipboard.min.js"></script>
new Clipboard('.btn');
<!-- Target -->
<input id="foo" value="https://github.com/zenorocha/clipboard.js.git">
<!-- Trigger -->
<button class="btn" data-clipboard-target="#foo">
<img src="assets/clippy.svg" alt="Copy to clipboard">
</button>
本目录
被绑架的 .btn放一边, 看配置
彩蛋
我们从
new Clipboard('.btn');
开始
.btn
代表 class="btn"
的 button
元素
让我们看看它做了什么
clipboard.js-master/src/clipboard.js
class Clipboard extends Emitter {
/**
* @param {String|HTMLElement|HTMLCollection|NodeList} trigger
* @param {Object} options
*/
constructor(trigger, options) { // trigger == .btn
super();
this.resolveOptions(options);
this.listenClick(trigger); // 来到这里
}
clipboard.js-master/src/clipboard.js
/**
* 增加 一个 点击事件监听器 到 过滤的目标
* Adds a click event listener to the passed trigger.
* @param {String|HTMLElement|HTMLCollection|NodeList} trigger
*/
listenClick(trigger) {
this.listener = listen(trigger, 'click', (e) => this.onClick(e));
}
三个点
-
this.listener
存储 -
listen
函数
import listen from 'good-listener';
this.onClick(e)
事件绑定 e == 元素
onClick(e) {
// 绑定好
const trigger = e.delegateTarget || e.currentTarget;
if (this.clipboardAction) {
this.clipboardAction = null;
} // 如果存在,清空
// 重建
this.clipboardAction = new ClipboardAction({
action : this.action(trigger),
target : this.target(trigger),
text : this.text(trigger),
container : this.container,
trigger : trigger,
emitter : this
});
}
ClipboardAction
import ClipboardAction from './clipboard-action';
那么,我们 在 初始化
new Clipboard('.btn');
开始 .btn
流动就结束了,
它被 Clipboard 绑定在了 click 的事件监听器上,并把相关逻辑,给了
import ClipboardAction from './clipboard-action';
next
我们先把 被绑架的 .btn
放一边,看看 this.resolveOptions(options);
class Clipboard extends Emitter {
/**
* @param {String|HTMLElement|HTMLCollection|NodeList} trigger
* @param {Object} options
*/
constructor(trigger, options) { // trigger == .btn
super();
this.resolveOptions(options); //<--- 这个
this.listenClick(trigger);
}
/**
* Defines if attributes would be resolved using internal setter functions
* or custom functions that were passed in the constructor.
* @param {Object} options
*/
// options -就是--> {},在本次说明中。
resolveOptions(options = {}) {
this.action = (typeof options.action === 'function') ? options.action : this.defaultAction;
this.target = (typeof options.target === 'function') ? options.target : this.defaultTarget;
this.text = (typeof options.text === 'function') ? options.text : this.defaultText;
this.container = (typeof options.container === 'object') ? options.container : document.body;
}
所以,上面代码的 options
都是 default
this.action = this.defaultAction
this.target = this.defaultTarget
this.text = this.defaultText
this.container = document.body
this.defaultAction
/**
* Default `action` lookup function.
* @param {Element} trigger
*/
defaultAction(trigger) {
return getAttributeValue('action', trigger);
}
this.defaultTarget
/**
* Default `target` lookup function.
* @param {Element} trigger
*/
defaultTarget(trigger) {
const selector = getAttributeValue('target', trigger);
if (selector) {
return document.querySelector(selector);
}
}
this.defaultText
/**
* Default `text` lookup function.
* @param {Element} trigger
*/
defaultText(trigger) {
return getAttributeValue('text', trigger);
}
看来都指向一个函数 getAttributeValue
/**
* Helper function to retrieve attribute value.
* 帮助 函数去 识别 活动的值
* @param {String} suffix
* @param {Element} element
*/
function getAttributeValue(suffix, element) {
const attribute = `data-clipboard-${suffix}`;
// 前缀都是 `data-clipboard-` 的元素属性
if (!element.hasAttribute(attribute)) {
//没有那个值,返回 null
return;
}
// 返回值
return element.getAttribute(attribute);
}
到这里,我们重新表达一下, 配置
action
this.action => this.defaultAction => getAttributeValue('action', trigger)
// 变
this.action(trigger) = getAttributeValue('action', trigger)
target
this.target(trigger) =
const selector = getAttributeValue('target', trigger);
return document.querySelector(selector);
text
this.text => this.defaultText => getAttributeValue('text', trigger)
// 变
this.text(trigger) = getAttributeValue('text', trigger)
this.container = document.body
next
我们把配置也加上去了,那么现在我们可以去找 .btn
了,
waitting
==
还有个 isSupported 是否支持 clipboard的功能测试噢
,
当然,你着急可以先一步噢-->抢救.btn点击事件行动
next
/**
* Destroy lifecycle.
*/
destroy() {
this.listener.destroy(); // 监听 去掉
if (this.clipboardAction) {
this.clipboardAction.destroy(); // action 元素和事件 去掉
this.clipboardAction = null;
}
}
next
那么我们看彩蛋
/**
* Returns the support of the given action, or all actions if no action is
* given.
* @param {String} [action]
*/
// 静态函数,可以 Clipboard.isSupported 被人使用
static isSupported(action = ['copy', 'cut']) {
// 默认测两个 copy cut
const actions = (typeof action === 'string') ? [action] : action;
let support = !!document.queryCommandSupported; // 从英文上看,查询命令支持?
actions.forEach((action) => {
support = support && !!document.queryCommandSupported(action);
});
// support = support && !!document.queryCommandSupported(action);
// 这行 support = support 很关键
// 一旦 support == false
// 那么这个值就一直是 false
return support;
}
那么,Done or
import Emitter from 'tiny-emitter';
Emitter
用在了 Clipboard
的 继承上
class Clipboard extends Emitter {
import listen from 'good-listener';
listener
用在了 Clipboard this.listener
上
listenClick(trigger) {
this.listener = listen(trigger, 'click', (e) => this.onClick(e));
}