鼠标按下 2 秒后将文本复制到剪贴板

Copy text to clipboard after mousePressed 2 seconds

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

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

我测试了它,在 Firefox 59 中,阈值是 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} 秒内不起作用。所以这里唯一的问题是时间因素。是否有其他解决方案可以将文本复制到剪贴板或避免直接用户交互的 broser 默认时间? 或者在基于网络的应用程序中是不可能的,我必须使用类似 react-native 的东西?

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

伪:

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();
    }
  }
});

根据 Seth 的想法,link 立即被复制,但相关信息会在 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>

            )
        }
    }