Przycisk kopiowania do schowka (JavaScript i React)
Przycisk kopiowania do schowka
Przycisk kopiowania do schowka w JavaScript i React | We.Inc
Zbuduj przycisk kopiowania z navigator.clipboard.writeText: działające demo, hook React, kopiowanie sformatowanego HTML i obrazów przez ClipboardItem, dostępny komunikat Skopiowano i obsługa błędów.
Wywołaj navigator.clipboard.writeText(text) z handlera kliknięcia. Zwraca obietnicę, więc użyj await, potem pokaż krótki komunikat Skopiowano i obsłuż przypadek błędu. API działa tylko na HTTPS lub localhost i wymaga prawdziwej akcji użytkownika, np. kliknięcia, więc nie wywołuj go przy ładowaniu strony.
Przycisk kopiowania wygląda banalnie, a jednak fragmenty kodu wysoko w wynikach często pomijają to, co się psuje: obietnica może zostać odrzucona, osadzone ramki mogą być zablokowane, a użytkownicy czytników ekranu nigdy nie usłyszą, że coś się stało. Demo poniżej naprawdę kopiuje w Twojej przeglądarce, a kod obejmuje każdy z tych przypadków.
Naciśnij przycisk Kopiuj w demo. Etykieta zmienia się na Skopiowano na dwie sekundy, a ukryty komunikat statusu to ogłasza.
Wklej do pola testowego, aby sprawdzić, co dokładnie trafiło do schowka.
Wypróbuj przycisk kopiowania sformatowanego tekstu, a potem wklej do e-maila lub edytora dokumentów, aby zobaczyć, że wersja HTML zachowuje formatowanie.
Skopiuj poniżej kod w czystym JavaScript, hook React lub kod kopiowania sformatowanego tekstu.
Zawsze obsługuj odrzucenie. Pokaż komunikat w stylu Naciśnij Ctrl+C, aby skopiować, i zaznacz tekst, aby osoba mogła dokończyć ręcznie.
Ogłaszaj sukces w regionie role="status". Sama zmiana ikony nic nie mówi użytkownikom czytników ekranu.
Utrzymuj stałą szerokość etykiety przycisku, gdy zmienia się na Skopiowano, aby nic wokół nie skakało.
Kopiuj wartość ze swoich danych, a nie z innerText ostylowanego elementu, który może złapać ukryte lub nadmiarowe białe znaki.
Wewnątrz iframe Chromium wymaga, aby rodzic zezwolił na clipboard-write przez Permissions Policy, na przykład allow="clipboard-write".
Najczęściej zadawane pytania
Dlaczego navigator.clipboard jest undefined?
Strona nie działa w bezpiecznym kontekście. Clipboard API jest dostępne tylko na stronach HTTPS i na localhost, więc strona serwowana przez zwykłe HTTP lub z adresu w sieci lokalnej go nie ma.
Dlaczego writeText rzuca NotAllowedError?
Przeglądarka odmówiła zapisu, zwykle dlatego, że nie było niedawnej akcji użytkownika, strona nie miała fokusu albo ramka została zablokowana przez Permissions Policy. Wywołaj go bezpośrednio w handlerze kliknięcia i unikaj długich await przed nim.
Czy potrzebuję biblioteki do kopiowania do schowka w React?
Nie. Wystarczy dziesięciolinijkowy hook wokół navigator.clipboard.writeText. Biblioteki głównie dodają rozwiązanie awaryjne z execCommand dla bardzo starych przeglądarek, którego obecne przeglądarki nie potrzebują.
Czy mogę skopiować obraz do schowka?
Tak, przez navigator.clipboard.write i ClipboardItem, którego kluczem jest image/png, a wartością Blob PNG. Użyj ClipboardItem.supports(), aby najpierw sprawdzić typ: PNG to format, który przeglądarki akceptują najpewniej.
Czy document.execCommand('copy') jest nadal w porządku?
Jest przestarzałe. Nadal działa w wielu przeglądarkach w różnych warunkach, ale nowy kod powinien używać asynchronicznego Clipboard API, a w razie niepowodzenia prosić osobę o ręczne skopiowanie.
Trzy zasady, które egzekwuje przeglądarka
Zapis do schowka to akcja uprzywilejowana, więc przeglądarki wymagają bezpiecznej strony, dokumentu z fokusem, a w Firefox i Safari także świeżego gestu użytkownika przy każdym zapisie. Chromium może też przyznać trwałe uprawnienie clipboard-write.
W praktyce uruchamiaj kopiowanie kliknięciem lub naciśnięciem klawisza, wykonuj zapis wcześnie w handlerze i traktuj niepowodzenie jako coś normalnego, a nie wyjątkowego.
Informacja zwrotna, którą ludzie zauważą
Zmień etykietę na Skopiowano na około dwie sekundy, a potem ją przywróć. Podpowiedź pojawiająca się tylko po najechaniu jest niewidoczna na ekranach dotykowych i dla użytkowników klawiatury.
Umieść ten sam komunikat w uprzejmym regionie live. role="status" ogłasza go bez przerywania tego, co czytał czytnik ekranu.
Kopiowanie sformatowane i własne zdarzenia copy
ClipboardItem może jednocześnie zawierać wersję text/plain i text/html. Aplikacje rozumiejące HTML wklejają wersję sformatowaną, a zwykłe pola tekstowe drugą.
Aby zmienić to, co kopiuje zwykłe Ctrl+C, na przykład dodać linię ze źródłem, nasłuchuj zdarzenia copy, wywołaj event.preventDefault() i ustaw własne dane przez event.clipboardData.setData().
Czysty JavaScript
Przycisk kopiowania z informacją zwrotną i rozwiązaniem awaryjnym
Element statusu jest wizualnie ukryty, ale odczytywany na głos. Przy niepowodzeniu tekst zostaje zaznaczony, aby osoba mogła nacisnąć Ctrl+C lub Cmd+C.
Hook React
useCopyToClipboard
Zwraca stan i funkcję kopiowania. Timer jest czyszczony przy odmontowaniu, więc nigdy nie aktualizuje usuniętego komponentu.
Sformatowany tekst, obrazy i zdarzenie copy
Kopiowanie HTML z wersją awaryjną w zwykłym tekście
Każdy typ MIME to Blob. Miejsca wklejenia wybierają najbogatszy format, który rozumieją.
Dodanie linii ze źródłem do zwykłego kopiowania
Używaj oszczędnie. Zmiana tego, co ludzie kopiują, może ich irytować, więc ogranicz to do cytatów lub kodu, gdzie źródło pomaga.
Błędy i ich przyczyny
Gdy kopiowanie się nie udaje
Co widzisz
Prawdopodobna przyczyna
Rozwiązanie
navigator.clipboard jest undefined
Strona serwowana przez zwykłe HTTP
Serwuj przez HTTPS lub testuj na localhost
NotAllowedError
Brak gestu użytkownika lub karta bez fokusu
Wywołuj w handlerze kliknięcia
NotAllowedError wewnątrz iframe
Permissions Policy blokuje clipboard-write
Dodaj allow="clipboard-write" do iframe
Kopiowanie obrazu odrzucone
Nieobsługiwany typ MIME
Przekonwertuj do PNG i sprawdź ClipboardItem.supports()
Skopiowano
Błąd
Kopiuj
Kopiuj sformatowany tekst
Skopiowano do schowka
Kopiowanie nie powiodło się. Zaznacz tekst i naciśnij Ctrl+C lub Cmd+C.
Wypróbuj
Przyciski kopiowania zwykłego tekstu i sformatowanego HTML z polem do wklejenia, aby sprawdzić wynik.