2016-09-14 4 views
15

Я использую ReactJS, и когда пользователь нажимает на ссылку, я хочу скопировать некоторый текст в буфер обмена.В реакцииJS, как скопировать текст в буфер обмена?

Я использую Chrome 52, и мне не нужно поддерживать какие-либо другие браузеры.

Я не понимаю, почему этот код не приводит к копированию данных в буфер обмена. (происхождение фрагмента кода происходит из сообщения Reddit).

Я делаю это неправильно? Может ли кто-нибудь предложить, есть ли «правильный» способ реализовать копию в буфер обмена с помощью реакции?

copyToClipboard = (text) => { 
    console.log('text', text) 
    var textField = document.createElement('textarea') 
    textField.innerText = text 
    document.body.appendChild(textField) 
    textField.select() 
    document.execCommand('copy') 
    textField.remove() 
} 
+1

ли вы попробовать использовать 3rd решения партии, как https://clipboardjs.com/ или https://github.com/zeroclipboard/zeroclipboard? – EugZol

+0

@EugZol Я действительно предпочитаю писать код, а не добавлять другую зависимость, предполагая, что код довольно мал. –

+0

Проверьте эти ответы http://stackoverflow.com/questions/400212/how-do-copy-to-the-clipboard-in-javascript – elmeister

ответ

15

Самый простой способ будет использовать пакет react-copy-to-clipboard НПМ.

Вы можете установить его с помощью следующей команды

npm install --save react react-copy-to-clipboard 

Используйте ее следующим образом.

const App = React.createClass({ 
    getInitialState() { 
    return {value: '', copied: false}; 
    }, 


    onChange({target: {value}}) { 
    this.setState({value, copied: false}); 
    }, 


    onCopy() { 
    this.setState({copied: true}); 
    }, 


    render() { 
    return (
     <div> 

      <input value={this.state.value} size={10} onChange={this.onChange} /> 

     <CopyToClipboard text={this.state.value} onCopy={this.onCopy}> 
      <button>Copy</button> 
     </CopyToClipboard> 

       <div> 
     {this.state.copied ? <span >Copied.</span> : null} 
       </div> 
     <br /> 

     <input type="text" /> 

     </div> 
    ); 
    } 
}); 

ReactDOM.render(<App />, document.getElementById('container')); 

подробное объяснение предоставляется по следующей ссылке

https://www.npmjs.com/package/react-copy-to-clipboard

Вот работает fiddle.

+0

Есть ли какие-либо решения, если мне нужно делать наоборот? Т.е. автор будет копировать текст из электронной почты в текстовую область в приложении reactjs. Мне не нужно сохранять теги html, однако мне нужно сохранить только разрывы строк. – TechTurtle

+0

Возможно, вам нужно подключить событие 'onpaste' – Koen

12

Вы должны обязательно рассмотреть возможность использования пакета, такого как @Shubham выше, советует, но я создал рабочий код на основе того, что вы описали: http://codepen.io/dtschust/pen/WGwdVN?editors=1111. Он работает в моем браузере в хроме, возможно, вы можете увидеть, есть ли что-то, что я там сделал, что вы пропустили, или если в приложении есть какая-то сложная сложность, которая мешает этому работать.

// html 
<html> 
    <body> 
    <div id="container"> 

    </div> 
    </body> 
</html> 


// js 
const Hello = React.createClass({ 
    copyToClipboard:() => { 
    var textField = document.createElement('textarea') 
    textField.innerText = 'foo bar baz' 
    document.body.appendChild(textField) 
    textField.select() 
    document.execCommand('copy') 
    textField.remove() 
    }, 
    render: function() { 
    return (
     <h1 onClick={this.copyToClipboard}>Click to copy some text</h1> 
    ) 
    } 
}) 

ReactDOM.render(
<Hello/>, 
    document.getElementById('container')) 
+0

Почему пакет лучше вашего решения? –

+2

Потенциально лучшая поддержка кросс-браузера и больше глаз на упаковке в случае необходимости исправления ошибок –

+0

работает как шарм. Да. Интересно также о поддержке кросс-браузера. –

8

Я лично не вижу необходимости в библиотеке для этого. Глядя на http://caniuse.com/#feat=clipboard, он довольно широко поддерживается сейчас, однако вы все равно можете делать такие вещи, как проверка на наличие функциональности в текущем клиенте и просто скрыть кнопку копирования, если это не так.

import React from 'react'; 

class CopyExample extends React.Component { 

    constructor(props) { 
    super(props); 

    this.state = { copySuccess: '' } 
    } 

    copyToClipboard = (e) => { 
    this.textArea.select(); 
    document.execCommand('copy'); 
    // This is just personal preference. 
    // I prefer to not show the the whole text area selected. 
    e.target.focus(); 
    this.setState({ copySuccess: 'Copied!' }); 
    }; 

    render() { 
    return (
     <div> 
     { 
     /* Logical shortcut for only displaying the 
      button if the copy command exists */ 
     document.queryCommandSupported('copy') && 
      <div> 
      <button onClick={this.copyToClipboard}>Copy</button> 
      {this.state.copySuccess} 
      </div> 
     } 
     <form> 
      <textarea 
      ref={(textarea) => this.textArea = textarea} 
      value='Some text to copy' 
      /> 
     </form> 
     </div> 
    ); 
    } 

} 

export default CopyExample; 
+0

отличное решение :) – Pixelomo

+0

Это лучший ответ. Мы не должны поощрять разработчиков использовать пакеты для каждой мелочи, если они не нуждаются в старой поддержке браузера. – tugce

5

Почему бы не использовать только событие метод сбора clipboardData e.clipboardData.setData(type, content)?

На мой взгляд, это самый streightforward метод для достижения толкая SMTH внутри буфера обмена, проверить это (я использовал, что для изменения данных в то время как родное копирование действия):

... 

handleCopy = (e) => { 
    e.preventDefault(); 
    e.clipboardData.setData('text/plain', 'Hello, world!'); 
} 

render =() => 
    <Component 
     onCopy={this.handleCopy} 
    /> 

Я следовал по этому пути: https://developer.mozilla.org/en-US/docs/Web/Events/copy

Cheers!

EDIT: Для целей тестирования, я добавил codepen: https://codepen.io/dprzygodzki/pen/ZaJMKb

+0

нет поддержки 'clipboardData' в IE –

+0

@KarlPokus Вопросник только ищет решение для Chrome – TechTurtle

+0

не работает на Chrome – ian

0

Ваш код должен работать отлично, я использую его таким же образом. Только убедитесь, что если событие щелчка запускается из всплывающего экрана, такого как загрузочный модальный или что-то еще, созданный элемент должен быть в пределах этого модального кода, иначе он не будет копироваться. Вы всегда можете указать идентификатор элемента внутри этого модального (как второй параметр) и получить его с помощью getElementById, а затем добавить вновь созданный элемент к этому, а не к документу.Что-то вроде этого:

copyToClipboard = (text, elementId) => { 
    const textField = document.createElement('textarea'); 
    textField.innerText = text; 
    const parentElement = document.getElementById(elementId); 
    parentElement.appendChild(textField); 
    textField.select(); 
    document.execCommand('copy'); 
    parentElement.removeChild(textField); 
} 
Смежные вопросы