1. 前语

面向搜索引擎开发时,咱们常常看到这样的情况:登录后仿制。

user-select:none真的能制止文本的仿制粘贴吗?

因为设置了css特点 user-select:none,此刻鼠标无法完成选中文本,也就无法仿制文本,通常会选用这种办法来制止仿制文本。翻开开发者工具-检查元素,撤销此款式,就能够选中文本了。

user-select:none真的能制止文本的仿制粘贴吗?

可是,你们有尝试过这样的仿制、粘贴吗?

user-select:none真的能制止文本的仿制粘贴吗?

咦,本来也能够不必登录后仿制嘛。

其实,在记事本、textarea等纯文本框内粘贴是能够经过此特点达到制止仿制的功用,可是在富文本框内粘贴也就无能为力了。

那咱们先了解下user-select,然后完善制止仿制的才能。

2. user-select

该特点用来操控用户能否选中文本。其对应常用的值:

  • none:元素及其子元素的文本不行选中。
  • auto:具体取值取决于一系列条件,具体如下:
    • ::before::after伪元素上,选用的特点值是none
    • 假如元素是可编辑元素,则选用的特点值是contain
    • 不然,假如此元素的父元素的user-select选用的特点值为all,则该元素选用的特点值也为all
    • 不然,假如此元素的父元素的user-select选用的特点值为none,则该元素选用的特点值也为none
    • 不然,选用的特点值为text
  • text:用户能够选中文本。
  • all:当单击文本时,会选中这一行文本。

悉数值如下:

/* Keyword values */
user-select: none;
user-select: auto;
user-select: text;
user-select: contain;
user-select: all;
/* Global values */
user-select: inherit;
user-select: initial;
user-select: revert;
user-select: revert-layer;
user-select: unset;

3. 选中、仿制、粘贴操作

独自选中带有user-select:none的文本款式是无法选中的,可是,咱们借用能够选中的文本,虽然中间那个文本是无法看到拖蓝,跨段选中然后仿制。

user-select:none真的能制止文本的仿制粘贴吗?

咱们发现在富文本框,能够将设置了none的文本正确地粘贴了。前提需求凭借能够仿制的文本跨段选中。所以前语中“登录后仿制”的代码也能运用这种办法,在wps等富文本编辑器中粘贴取得完好代码。

4. user-select:none如何完成制止仿制文本

在中仿制文章粘贴时,会发现文本最终会带上版权信息。已然能够悄悄的改动仿制的文本内容,那咱们也就能够操控哪些文本是否能够仿制。

终究咱们要完成的作用是,设置了user-select:none的节点,无论在纯文本内仍是富文本框内粘贴,都不会粘贴出来,完成了真正的制止仿制,趁便添加版权信息。

user-select:none真的能制止文本的仿制粘贴吗?

首要,为网页添加copy事情。梦想开端的当地。

选用Selection对象获取到选中的文本,这里面包含了user-select:none节点。

window.addEventListener('copy',()=>{
    const selection = window.getSelection()
    const copyNode = selection.getRangeAt(0).cloneContents();
})

创建一个div,将copyNode放在div内,并挂载到dom树上,以便获取节点的user-select特点值,来操控是否需求仿制该节点。

const div = document.createElement('div');
div.appendChild(copyNode);
// 经过getComputedStyle获取style值,需求将节点挂载到dom树上,因而append到body
document.body.appendChild(div);
const nodelist = div.childNodes;
for (let i = 0; i < nodelist.length; i++) {
    const curnode = nodelist[i];
    const nodeType = curnode.nodeType;
    // 重点操作
    // 将节点类型为元素节点,而且设置了user-select:none的节点从仿制的内容中过滤掉
    if (nodeType === 1 && window.getComputedStyle(curnode).userSelect === 'none') {
      div.removeChild(curnode);
    }
}
// 获取过滤后的数据
const cpt = div.innerHTML;

将处理好的数据设置为选中,趁便设置个版权信息。

// 又创建个div,将选区设置为此div
const div2 = document.createElement('div');
const copyright = `
<br><br>作者:Yue栎廷
<br>来历:<a href='https:///user/3421335917437134' target='_blank'>https:///user/3421335917437134@Yue栎廷</a>
<br>著作权归作者一切。商业转载请联络作者取得授权,非商业转载请注明出处。
`
div2.innerHTML = cpt + copyright;
// 要设置选区,需求挂载在dom树上
document.body.appendChild(div2);
// 更新选区
selection.selectAllChildren(div2);

咱们创建了2个div,而且append到了页面上,这不应该对用户可见。因而:

  1. 经过设置css,将div放在页面不行见当地
const div2 = document.createElement('div');
+ div2.style.position = 'fixed';
+ div2.style.left = '9999px';
const copyright = `
<br><br>作者:Yue栎廷
<br>来历:<a href='https:///user/3421335917437134' target='_blank'>@Yue栎廷</a>
<br>著作权归作者一切。商业转载请联络作者取得授权,非商业转载请注明出处。
`
  1. 或者在操作最终及时移除节点
// 更新选区
selection.selectAllChildren(div2)
+ setTimeout(() => {
+    document.body.removeChild(div2);
+    document.body.removeChild(div);
+})

以上就是完成完好地制止仿制的悉数代码。

戳一戳,快速体会:

user-select:none真的能制止文本的仿制粘贴吗?

5.你的是我创作的动力

网上大部分仿制文本添加版权的做法是,经过window.getSelection().toString()获取到选中的文本,可是这种办法不会过滤掉设置了user-select:none的文本。

为什么没有经过剪切板去获取仿制的文本数据呢? 因为copy事情触发时刻是在实践仿制操作之前,所以此刻剪贴板内还没有数据,曲线救国选用了selection

其次,添加版权信息的做法是,经过window.clipboardData.setData('text', copyNode + copyright)将数据设置到剪贴板上,可是这种办法只能设置纯文本,无法粘贴带款式的文本,可是也能够经过设置新的选区来完成获取富文本数据。

之前在项目里用了此css特点来完成部分灵敏信息的制止仿制,自己在开发自测时的确无法选中文本仿制,可是上线后,用户反馈文本仍是能够仿制并粘贴到同界面的一个富文本框内。后边了解到用户的仿制操作是在鼠标拖蓝选中的文本中将不行选中的文本一同仿制了,并刚好在富文本框内粘贴,防不胜防啊。

不过,看到此文的你们必定不会再有此bug!