vue-clipboard.ts 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. import Clipboard from "clipboard";
  2. import { App, DirectiveBinding, VNode } from "vue";
  3. import { clipboardKey } from "./injectionKey";
  4. // clipboard config
  5. const VueClipboardConfig = {
  6. autoSetContainer: false,
  7. appendToBody: true,
  8. };
  9. // 枚举复制的状态
  10. enum status {
  11. success = "success",
  12. error = "error",
  13. }
  14. // 方法调用 返回promise
  15. const $copyText = (
  16. text: string,
  17. container?: HTMLElement
  18. ): Promise<ClipboardJS.Event> => {
  19. return new Promise((resolve, reject) => {
  20. const fakeElement = document.createElement("button");
  21. const clipboard = new Clipboard(fakeElement, {
  22. text: () => text,
  23. action: () => "copy",
  24. container: typeof container === "object" ? container : document.body,
  25. });
  26. clipboard.on(status.success, (e: ClipboardJS.Event) => {
  27. clipboard.destroy();
  28. resolve(e);
  29. });
  30. clipboard.on(status.error, (e: ClipboardJS.Event) => {
  31. clipboard.destroy();
  32. reject(e);
  33. });
  34. if (VueClipboardConfig.appendToBody) document.body.appendChild(fakeElement);
  35. fakeElement.click();
  36. if (VueClipboardConfig.appendToBody) document.body.removeChild(fakeElement);
  37. });
  38. };
  39. // v-direction bind
  40. const bind = (
  41. el: ClipboardElement,
  42. binding: DirectiveBinding,
  43. vnode: VNode
  44. ) => {
  45. if (binding.arg === status.success) el._vClipboard_success = binding.value;
  46. else if (binding.arg === status.error) el._vClipboard_error = binding.value;
  47. else {
  48. const clipboard = new Clipboard(el, {
  49. text: () => binding.value,
  50. action: () => (binding.arg === "cut" ? "cut" : "copy"),
  51. container: VueClipboardConfig.autoSetContainer ? el : undefined,
  52. });
  53. clipboard.on(status.success, (e) => {
  54. const cb = el._vClipboard_success;
  55. cb && cb(e);
  56. });
  57. clipboard.on(status.error, (e) => {
  58. const cb = el._vClipboard_error;
  59. cb && cb(e);
  60. });
  61. el._vClipboard = clipboard;
  62. }
  63. };
  64. // v-direction update
  65. const update = (el: ClipboardElement, binding: DirectiveBinding) => {
  66. if (binding.arg === status.success) el._vClipboard_success = binding.value;
  67. else if (binding.arg === status.error) el._vClipboard_error = binding.value;
  68. else {
  69. (<ClipboardJS.Options>el._vClipboard).text = () => binding.value;
  70. (<ClipboardJS.Options>el._vClipboard).action = () =>
  71. binding.arg === "cut" ? "cut" : "copy";
  72. }
  73. };
  74. // v-direction unbind
  75. const unbind = (el: ClipboardElement, binding: DirectiveBinding) => {
  76. if (binding.arg === status.success) delete el._vClipboard_success;
  77. else if (binding.arg === status.error) delete el._vClipboard_error;
  78. else {
  79. (<ClipboardJS>el._vClipboard).destroy();
  80. delete el._vClipboard;
  81. }
  82. };
  83. const VueClipboard3 = {
  84. install: (app: App<Element>) => {
  85. // const copySymbol = Symbol();
  86. // provide注入 方便组合api调用
  87. app.provide(clipboardKey, { $copyText });
  88. app.config.globalProperties.$clipboardConfig = VueClipboardConfig;
  89. app.config.globalProperties.$copyText = $copyText;
  90. app.directive("clipboard", {
  91. beforeMount: bind,
  92. updated: update,
  93. unmounted: unbind,
  94. });
  95. },
  96. config: VueClipboardConfig,
  97. };
  98. export default VueClipboard3;