├── README.md
├── atuser.gif
├── atuser3
├── atuser.vue
├── index.html
├── index.js
└── index.vue
├── edit.gif
├── vue-at
├── .babelrc
├── .gitignore
├── .npmignore
├── LICENSE
├── README.md
├── WechatIMG1.jpeg
├── WechatIMG2.jpeg
├── index.html
├── package.json
├── src
│ ├── App.vue
│ ├── At.scss
│ ├── At.vue
│ ├── AtTemplate.vue
│ ├── AtTextarea.vue
│ ├── main.js
│ └── util.js
├── static
│ ├── awesome.svg
│ └── electron.svg
└── webpack
│ ├── base.js
│ ├── demo.js
│ └── prod.js
├── vue-edit
├── atuser.vue
├── edit.vue
├── index.html
├── index.js
├── index.vue
├── src
│ ├── chooseImg.js
│ ├── cursorPosition.js
│ ├── emoji.js
│ └── paste.js
└── 复制图片测试.html
├── 聊天底部.html
└── 聊天底部2.html
/README.md:
--------------------------------------------------------------------------------
1 | # vue-atuser
2 | Vue@某人,At某人,仿新浪微博@某人,@user
3 |
4 | 
5 |
6 | # vue-edit
7 | ### [Vue实现渲染数据后控制滚动条位置📜](https://juejin.im/post/5ded14d3e51d4557ff13fe56)
8 | ### [Element.scrollIntoView()](https://developer.mozilla.org/zh-CN/docs/Web/API/Element/scrollIntoView)
9 | ```
10 | Element.scrollIntoView() // 如果为false,元素的底端将和其所在滚动区的可视区域的底端对齐。
11 | ```
12 | ### [Web聊天工具的富文本输入框](https://juejin.im/post/5c79f249e51d457ab52e67e1)
13 | 
14 | ### [div+contenteditable 实现富文本发布框的小结](https://juejin.im/post/5c851ce8f265da2dc0068c14)
15 | ### [实现高度“听话”的多行文本输入框](https://juejin.im/post/5c9a1645e51d4559bb5c666f)
16 | ### [原生js 实现输入框emoji表情发布](https://juejin.im/post/5c9cd1ecf265da60d0005235)
17 | ### [Twitter和微博都在用的 @ 人的功能是如何设计与实现的?](https://juejin.cn/post/7036965252428202021)
18 | # 获取光标位置,设置光标位置
19 | ### [Vue实现字符串中自定义标识符的解析渲染🎩](https://juejin.im/post/5de6715ff265da33f11ab400)
20 | ```
21 | /**
22 | * 获取光标位置
23 | * @param {DOMElement} element 输入框的dom节点
24 | * @return {Number} 光标位置
25 | */
26 | export const getCursorPosition = (element) => {
27 | let caretOffset = 0
28 | const doc = element.ownerDocument || element.document
29 | const win = doc.defaultView || doc.parentWindow
30 | const sel = win.getSelection()
31 | if (sel.rangeCount > 0) {
32 | const range = win.getSelection().getRangeAt(0)
33 | const preCaretRange = range.cloneRange()
34 | preCaretRange.selectNodeContents(element)
35 | preCaretRange.setEnd(range.endContainer, range.endOffset)
36 | caretOffset = preCaretRange.toString().length
37 | }
38 | return caretOffset
39 | }
40 |
41 | /**
42 | * 设置光标位置
43 | * @param {DOMElement} element 输入框的dom节点
44 | * @param {Number} cursorPosition 光标位置的值
45 | */
46 | export const setCursorPosition = (element, cursorPosition) => {
47 | const range = document.createRange()
48 | range.setStart(element.firstChild, cursorPosition)
49 | range.setEnd(element.firstChild, cursorPosition)
50 | const sel = window.getSelection()
51 | sel.removeAllRanges()
52 | sel.addRange(range)
53 | }
54 | ```
55 | ### [Vue实现图片与文字混输🔥](https://juejin.im/post/5de26d39e51d455da17be1e3)
56 | # DEMO
57 | > atuser.vue
58 |
59 | ```js
60 |
61 |
64 |
72 |
70 |
5 |
13 |
11 |