• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# 使用Web组件与系统剪贴板交互处理网页内容
2<!--Kit: ArkWeb-->
3<!--Subsystem: Web-->
4<!--Owner: @zourongchun-->
5<!--Designer: @zhufenghao-->
6<!--Tester: @ghiker-->
7<!--Adviser: @HelloCrease-->
8
9开发者能够通过Web组件和系统剪贴板进行交互,实现各种类型数据的复制和粘贴。支持通过[菜单](web_menu.md)、键盘快捷键以及[W3C剪贴板接口](https://www.w3.org/TR/clipboard-apis/)对网页内容执行剪切、复制和粘贴操作。
10
11## 通过菜单或键盘快捷键与系统剪贴板交互
12
13开发者能够自定义菜单中的功能选项,当用户选择特定选项时,开发者可以通过调用[cut](../reference/apis-arkweb/arkts-basic-components-web-WebContextMenuResult.md#cut9)、[copy](../reference/apis-arkweb/arkts-basic-components-web-WebContextMenuResult.md#copy9)、[copyImage](../reference/apis-arkweb/arkts-basic-components-web-WebContextMenuResult.md#copyimage9)、[paste](../reference/apis-arkweb/arkts-basic-components-web-WebContextMenuResult.md#paste9)、[pasteAndMatchStyle](../reference/apis-arkweb/arkts-basic-components-web-WebContextMenuResult.md#pasteandmatchstyle20)等接口,将网页中的文本、HTML或图片数据复制到系统剪贴板,或从系统剪贴板粘贴到网页的可输入区域。
14
15菜单功能接口的使用可参考[使用Web组件菜单处理网页内容](web_menu.md)。
16
17当设备有物理键盘时,用户也能够通过键盘快捷键:CTRL + X(剪切)、CTRL + C(复制)、CTRL + V(粘贴),与剪贴板进行交互。
18
19> **说明:**
20>
21> 通过[paste](../reference/apis-arkweb/arkts-basic-components-web-WebContextMenuResult.md#paste9)、[pasteAndMatchStyle](../reference/apis-arkweb/arkts-basic-components-web-WebContextMenuResult.md#pasteandmatchstyle20)接口访问系统剪贴板内容,需[申请访问剪贴板权限](../basic-services/pasteboard/get-pastedata-permission-guidelines.md):ohos.permission.READ_PASTEBOARD22
23## 通过W3C异步剪贴板接口与系统剪贴板交互
24
25[异步剪贴板接口(Async Clipboard API)](https://www.w3.org/TR/clipboard-apis/#async-clipboard-api)提供给网页开发者读写系统剪贴板的方法,这让Web应用程序可以实现剪切、复制和粘贴的功能。
26
27- writeText:将文本内容写入系统剪贴板。
28
29```javascript
30// 写入文本到剪贴板
31await navigator.clipboard.writeText("文本内容");
32```
33
34- write:将任意类型内容写入系统剪贴板。
35
36```javascript
37// 写入 HTML到剪贴板
38const clipboardItem = new ClipboardItem({
39    'text/html': new Blob(["HTML内容"], { type: 'text/html' })
40});
41await navigator.clipboard.write([clipboardItem]);
42```
43
44- readText:从系统剪贴板读取文本内容。
45
46```javascript
47// 从剪贴板读取文本
48const text = await navigator.clipboard.readText()
49```
50
51- read():从系统剪贴板读取任意类型内容。
52
53```javascript
54// 从剪贴板读取 HTML
55const clipboardItems = await navigator.clipboard.read();
56const htmlBlob = await clipboardItems[0].getType('text/html');
57```
58
59> **说明:**
60>
61> 通过异步剪贴板接口read()和readText()方法访问系统剪贴板内容,需[申请访问剪贴板权限](../basic-services/pasteboard/get-pastedata-permission-guidelines.md):ohos.permission.READ_PASTEBOARD62
63```ts
64// xxx.ets
65import { webview } from '@kit.ArkWeb';
66
67@Entry
68@Component
69struct WebComponent {
70  controller: webview.WebviewController = new webview.WebviewController();
71
72  build() {
73    Column() {
74      Web({ src: $rawfile("clipboard.html"), controller: this.controller })
75    }
76  }
77}
78```
79
80加载的html:
81
82```html
83<!--clipboard.html-->
84<!DOCTYPE html>
85<html lang="zh">
86<head>
87    <meta charset="UTF-8">
88    <meta name="viewport" content="width=device-width, initial-scale=1.0">
89    <title>Clipboard API demo</title>
90    <style>
91        #output {
92            margin-top: 20px;
93            border: 1px solid #ccc;
94            padding: 10px;
95            min-height: 50px;
96        }
97        .button-group {
98            margin-bottom: 10px;
99        }
100    </style>
101</head>
102<body>
103<h1>Clipboard API demo</h1>
104<div class="button-group">
105    <button id="copyTextButton">复制文本</button>
106    <button id="copyHtmlButton">复制HTML</button>
107</div>
108
109<div class="button-group">
110    <button id="pasteTextButton">粘贴文本</button>
111    <button id="pasteHtmlButton">粘贴HTML</button>
112    <button id="clearOutputButton">清空输入框</button>
113</div>
114
115<div id="result"></div>
116<div id="output" contenteditable="true"></div>
117
118<script>
119    const textContent = "这是一些文本内容";
120    const htmlContent = `<strong><em>这是一些 HTML 内容</em></strong>`;
121
122    // writeText()接口
123    async function copyText() {
124        await navigator.clipboard.writeText(textContent);
125        document.getElementById('result').innerText = "文本已复制到剪贴板!";
126    }
127
128    // write()接口
129    async function copyHtml() {
130        const clipboardItem = new ClipboardItem({
131            'text/html': new Blob([htmlContent], { type: 'text/html' })
132        });
133        await navigator.clipboard.write([clipboardItem]);
134        document.getElementById('result').innerText = "HTML 已复制到剪贴板!";
135    }
136
137    // readText()接口
138    async function pasteText() {
139        const text = await navigator.clipboard.readText();
140        document.getElementById('output').innerText = text;
141    }
142
143    // read()接口
144    async function pasteHtml() {
145        const items = await navigator.clipboard.read();
146        for (const item of items) {
147            const types = item.types;
148            if (types.includes('text/html')) {
149                const blob = await item.getType('text/html');
150                const html = await blob.text();
151                document.getElementById('output').innerHTML = html;
152                return;
153            }
154        }
155        document.getElementById('result').innerText = "剪贴板中没有 HTML 内容。";
156    }
157
158    function clearOutput() {
159        document.getElementById('result').innerText = " ";
160        document.getElementById('output').innerHTML = '';
161    }
162
163    // 事件监听
164    document.getElementById('copyTextButton').addEventListener('click', copyText);
165    document.getElementById('copyHtmlButton').addEventListener('click', copyHtml);
166    document.getElementById('pasteTextButton').addEventListener('click', pasteText);
167    document.getElementById('pasteHtmlButton').addEventListener('click', pasteHtml);
168    document.getElementById('clearOutputButton').addEventListener('click', clearOutput);
169</script>
170</body>
171</html>
172```
173
174module.json5权限配置:
175
176**需要权限**:ohos.permission.READ_PASTEBOARD,应用访问剪贴板内容需[申请访问剪贴板权限](../basic-services/pasteboard/get-pastedata-permission-guidelines.md)。
177
178```json
179// module.json5
180{
181  "module" : {
182    // ...
183    "requestPermissions":[
184      {
185        "name" : "ohos.permission.READ_PASTEBOARD",
186        "reason": "$string:module_desc",
187        "usedScene": {
188          "abilities": [
189            "FormAbility"
190          ],
191          "when":"inuse"
192        }
193      }
194    ]
195  }
196}
197```
198
199![clipboard_api](./figures/web-clipboard_api.gif)
200
201## 通过W3C剪贴板事件接口与系统剪贴板交互
202
203[剪贴板事件(Clipboard Event)](https://www.w3.org/TR/clipboard-apis/#clipboard-events-and-interfaces)描述了与剪切板相关的cut、copy和paste事件。当用户执行剪切、复制或粘贴操作时,相应的事件将被触发。开发者可以通过监听这些事件,对系统剪贴板进行读写操作,或拦截默认行为,以更改复制或粘贴的结果。
204
205```ts
206// xxx.ets
207import { webview } from '@kit.ArkWeb';
208
209@Entry
210@Component
211struct WebComponent {
212  controller: webview.WebviewController = new webview.WebviewController();
213
214  build() {
215    Column() {
216      Web({ src: $rawfile("clipboard_event.html"), controller: this.controller })
217    }
218  }
219}
220```
221
222加载的html:
223
224```html
225<!--clipboard_event.html-->
226<!DOCTYPE html>
227<html lang="zh">
228<head>
229    <meta charset="UTF-8">
230    <meta name="viewport" content="width=device-width, initial-scale=1.0">
231    <title>Clipboard Event demo</title>
232    <style>
233        .output {
234            margin-top: 20px;
235            border: 1px solid #ccc;
236            padding: 10px;
237            max-width: 400px;
238        }
239    </style>
240</head>
241<body>
242<h2>Clipboard Event监听示例</h2>
243<textarea id="inputArea" rows="4" cols="50" placeholder="在这里输入文本,尝试复制和粘贴..."></textarea>
244
245<div class="output" id="output">
246    <h3>输出内容:</h3>
247    <p id="resultText">没有复制或粘贴内容。</p>
248</div>
249
250<script>
251    const inputArea = document.getElementById('inputArea');
252    const resultText = document.getElementById('resultText');
253
254    // 监听复制事件
255    inputArea.addEventListener('copy', (event) => {
256        const selection = document.getSelection();
257        const copiedText = selection.toString() + "(复制自ArkWeb)"
258        event.clipboardData.setData("text/plain", copiedText);
259        event.preventDefault();
260        resultText.textContent = `复制的内容: "${copiedText}"`;
261    });
262
263    // 监听粘贴事件
264    inputArea.addEventListener('paste', (event) => {
265        const pastedData = event.clipboardData.getData('text');
266        resultText.textContent = `粘贴的内容: "${pastedData}"`;
267    });
268
269    // 监听剪切事件
270    inputArea.addEventListener('cut', (event) => {
271        const selection = document.getSelection();
272        const cutText = selection.toString() + "(剪切自ArkWeb)"
273        event.clipboardData.setData("text/plain", cutText);
274        selection.deleteFromDocument();
275        event.preventDefault();
276        resultText.textContent = `剪切的内容: "${cutText}"`;
277    });
278</script>
279</body>
280</html>
281```
282
283![clipboard_event](./figures/web-clipboard_event.gif)
284
285## 设置剪贴板复制范围选项
286
287开发者可以通过设置Web组件的[copyOptions](../reference/apis-arkweb/arkts-basic-components-web-attributes.md#copyoptions11)属性,来指定Web组件上剪贴板复制的范围。可以指定的选项有:CopyOptions.None(不支持复制)、CopyOptions.InApp(支持应用内复制)以及CopyOptions.LocalDevice(支持设备内复制)。默认值为:CopyOptions.LocalDevice,即默认支持设备内部的复制。
288
289```ts
290// xxx.ets
291import { webview } from '@kit.ArkWeb';
292
293@Entry
294@Component
295struct WebComponent {
296  controller: webview.WebviewController = new webview.WebviewController();
297  @State copyOption: CopyOptions = CopyOptions.LocalDevice;
298
299  build() {
300    Column() {
301      Web({ src: $rawfile("copyOptions.html"), controller: this.controller })
302        .copyOptions(this.copyOption)
303    }
304  }
305}
306```
307
308加载的html:
309
310```html
311<!--copyOptions.html-->
312<!DOCTYPE html>
313<html lang="zh">
314<head>
315    <meta charset="UTF-8">
316    <meta name="viewport" content="width=device-width, initial-scale=1.0">
317    <title>Clipboard CopyOption demo</title>
318</head>
319<body>
320<h2>Clipboard CopyOption示例</h2>
321<textarea id="inputArea"></textarea>
322</body>
323</html>
324```
325