mousePressed 2秒后将文本复制到剪贴板

时间:2018-04-15 11:44:50

标签: javascript reactjs execcommand

想法是在react中创建一个元素,可以单击或longClicked(长按)。 onClick应该直接打开链接,longClick应该将链接复制到剪贴板(按下按钮2秒后)。

这两个功能都适用于自己的功能。但如果我将它们合并为一个,浏览器会说execCommand被忽略了,因为它不是直接用户交互的一部分。好吧,这意味着需要2秒才能触发此命令。

我测试了它,在Firefox 59中,treshhold是ca. 0.5秒,在Chrome 65中,它是1秒。

如果您在此时间之后触发某项功能,则不再是直接用户互动。

因此,如果我设置time={0.4}秒,就像在下面的代码中一样,它可以工作:

    import { ListItem, ListItemText } from 'material-ui/List'
    import PropTypes from 'prop-types'
    import React, { Component } from 'react'
    import { withStyles } from 'material-ui/styles'
    import { withRouter } from 'react-router-dom'
    import ClickNHold from 'react-click-n-hold';

    const styles = {
        card: {
            borderBottom: '1px solid rgba(0, 0, 0, 0.12)',
            '&:last-of-type': { borderBottom: 'none' }
        },
        title: {
            marginBottom: 16,
            fontSize: 14
        },
        itemText: { fontSize: '0.8em' }
    }

    class GroupCard extends Component {

        openGroup = () => {
            this.props.history.push(`/groups/${this.props.link}`)
        }

        copyToClipboard = () => {
            const uri = 'https://example.com/api/',
                textField = document.createElement('textarea')
            textField.innerText = `${uri}groups/${this.props.link}`
            document.body.appendChild(textField)
            textField.select()
            document.execCommand('copy')
            textField.remove()
        }

        touchEnd = (e, enough) => {
            enough ? null : this.openGroup()
        }

        render() {
            const { classes, name, link } = this.props,
                uri = 'https://example.com/api/'
            return (

                <ClickNHold time={0.4}
                            onClickNHold={this.copyToClipboard}
                            onEnd={this.touchEnd}>
                    <ListItem button className={classes.card} >
                        <ListItemText
                            primary={name ? name : 'unknown'}
                            secondary={<span className={classes.itemText}>{`${uri}groups/${link}`}</span>}
                        />
                    </ListItem>
                </ClickNHold>

            )
        }
    }

    GroupCard.propTypes = { classes: PropTypes.object.isRequired }

    export default withRouter(withStyles(styles)(GroupCard))

但代码不适用于time={2}秒。所以这里唯一的问题是时间因素。是否有其他解决方案可以将文本复制到剪贴板或避免更直接的用户交互的默认时间? 或者在基于网络的APP中这是不可能的,我必须使用像react-native这样的东西?

2 个答案:

答案 0 :(得分:1)

这是一种应避免性能问题的方法建议。

<强>的伪:

const mouseDown = false; //Track the state of the `click`
const openLink = false; //Track if opening the link when `click` is released

document.listen(mouseEvent, (event) {
 if(event === 'mouseDown') {
   openLink = true;
   mouseDown = true;
   setTimeOut(() => { 
      if(mouseDown) {
        openLink = false; //Don't open the link on click release, we copied to clipboard instead;
        copyToClipboard()
      }          
    }, 2*seconds);
  } else {
    mouseDown = false;
    if(openLink = true) {
      openLink = false;
      openTheLink();
    }
  }
});

答案 1 :(得分:1)

按照Seth的想法,链接会立即被复制,但是2秒后信息就会出现。似乎是一个很好的解决方法..

    class GroupCard extends Component {

        openGroup = () => {
            this.props.history.push(`/groups/${this.props.link}`)
        }
        touchStart = () => {
            const uri = 'https://example.com/',
                textField = document.createElement('textarea')
            textField.innerText = `${uri}groups/${this.props.link}`
            document.body.appendChild(textField)
            textField.select()
            document.execCommand('copy')
            textField.remove()
        }

        touchEnd = (e, enough) => {
            !enough && this.openGroup()
        }

        render() {
            const { classes, name, link } = this.props,
                uri = 'https://example.com/'
            return (

                <ClickNHold time={2}
                            onStart={this.touchStart}
                            onClickNHold={console.log('copied')}
                            onEnd={this.touchEnd}>
                    <ListItem button className={classes.card} >
                        <ListItemText
                            primary={name ? name : 'unknown'}
                            secondary={<span className={classes.itemText}>{`${uri}groups/${link}`}</span>}
                        />
                    </ListItem>
                </ClickNHold>

            )
        }
    }