我是靠谱客的博主 年轻店员,最近开发中收集的这篇文章主要介绍艾特某人代码实现_Vue@某人,At某人,仿新浪微博@某人,@user,艾特,艾特某人...,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

  • 展开更多群成员

import getCaretCoordinates from 'textarea-caret'

export default {

props: {

value: { //输入框初始值

type: String,

default: null

},

suffix: { //插入字符链接

type: String,

default: ' '

},

loop: { //上下箭头循环

type: Boolean,

default: true

},

avoidEmail: { //@前不能是字符

type: Boolean,

default: true

},

hoverSelect: { //悬浮选中

type: Boolean,

default: true

},

members: { //选择框选项列表

type: Array,

default: () => []

},

nameKey: {

type: String,

default: ''

}

},

data() {

return {

atItems: ['@'],

bindsValue: this.value != null,

atwho: null

}

},

computed: {

style() {

if(this.atwho) {

const {

list,

cur,

x,

y

} = this.atwho

const {

wrap

} = this.$refs

const el = this.$el.querySelector('textarea')

if(wrap) {

const left = x + el.offsetLeft - el.scrollLeft + 'px'

const top = y + el.offsetTop - el.scrollTop + 25 + 'px'

return {

left,

top

}

}

}

return null

}

},

watch: {

members() {

this.handleInput(true)

},

value(value, oldValue) {

if(this.bindsValue) {

this.handleValueUpdate(value)

}

}

},

mounted() {

if(this.bindsValue) {

this.handleValueUpdate(this.value)

}

},

methods: {

getAtAndIndex(text, ats) {

return ats.map((at) => {

return {

at,

index: text.lastIndexOf(at)

}

}).reduce((a, b) => {

return a.index > b.index ? a : b

})

},

isCur(index) {

return index === this.atwho.cur

},

handleValueUpdate(value) { //更新textarea的值

const el = this.$el.querySelector('textarea')

if(value !== el.value) {

el.value = value

}

},

handleItemHover(e) {

if(this.hoverSelect) {

this.selectByMouse(e)

}

},

handleItemClick(e) {

this.selectByMouse(e)

this.insertItem()

},

handleKeyDown(e) {

const {

atwho

} = this

if(atwho) {

if(e.keyCode === 38 || e.keyCode === 40) { // ↑/↓

if(!(e.metaKey || e.ctrlKey)) {

e.preventDefault()

e.stopPropagation()

this.selectByKeyboard(e)

}

return

}

if(e.keyCode === 13) { // enter

this.insertItem()

e.preventDefault()

e.stopPropagation()

return

}

if(e.keyCode === 27) { // esc

this.closePanel()

return

}

}

// 为了兼容ie ie9~11 editable无input事件 只能靠keydown触发 textarea正常

// 另 ie9 textarea的delete不触发input

const isValid = e.keyCode >= 48 && e.keyCode <= 90 || e.keyCode === 8

if(isValid) {

setTimeout(() => {

this.handleInput()

}, 50)

}

if(e.keyCode === 8) { //删除

//this.handleDelete(e)

}

if(e.keyCode === 13) { //删除

this.$emit("enterSend",e)

}

},

handleInput(event) {

const el = this.$el.querySelector('textarea')

this.$emit('input', el.value) //更新父组件

const text = el.value.slice(0, el.selectionEnd)

if(text) {

const {

atItems,

avoidEmail

} = this

let show = true

const {

at,

index

} = this.getAtAndIndex(text, atItems)

if(index < 0) show = false

const prev = text[index - 1] //上一个字符

const chunk = text.slice(index + at.length, text.length)

if(avoidEmail) { //上一个字符不能为字母数字 避免与邮箱冲突,微信则是避免 所有字母数字及半角符号

if(/^[a-z0-9]$/i.test(prev)) show = false

}

if(/^s/.test(chunk)) show = false //chunk以空白字符开头不匹配 避免`@ `也匹配

if(!show) {

this.closePanel()

} else {

const {

members,

filterMatch

} = this

if(!event) { // fixme: should be consistent with At.vue

this.$emit('at', chunk)

}

const matched = members.filter(v => {

return v.toString().indexOf(chunk) > -1

})

if(matched.length) {

this.openPanel(matched, chunk, index, at)

} else {

this.closePanel()

}

}

} else {

this.closePanel()

}

},

closePanel() {

if(this.atwho) {

this.atwho = null

}

},

openPanel(list, chunk, offset, at) { //打开Atuser列表 matched, chunk, index, at 过滤数组,匹配项,匹配项index,'@'

const fn = () => {

const el = this.$el.querySelector('textarea')

const atEnd = offset + at.length // 从@后第一位开始

const rect = getCaretCoordinates(el, atEnd)

this.atwho = {

chunk,

offset,

list,

atEnd,

x: rect.left,

y: rect.top - 4,

cur: 0, // todo: 尽可能记录

}

}

if(this.atwho) {

fn()

} else { // 焦点超出了显示区域 需要提供延时以移动指针 再计算位置

setTimeout(fn, 10)

}

},

selectByMouse(e) {

function closest(el, predicate) { //遍历直到有data-index为止

do {

if(predicate(el)) return el;

} while (el = el && el.parentNode);

}

const el = closest(e.target, d => {

return d.getAttribute('data-index')

})

const cur = +el.getAttribute('data-index')

this.atwho = {

...this.atwho,

cur

}

},

selectByKeyboard(e) {

const offset = e.keyCode === 38 ? -1 : 1

const {

cur,

list

} = this.atwho

const nextCur = this.loop ?

(cur + offset + list.length) % list.length :

Math.max(0, Math.min(cur + offset, list.length - 1))

this.atwho = {

...this.atwho,

cur: nextCur

}

},

// todo: 抽离成库并测试

insertText(text, el) {

const start = el.selectionStart

const end = el.selectionEnd

el.value = el.value.slice(0, start) +

text + el.value.slice(end)

const newEnd = start + text.length

el.selectionStart = newEnd

el.selectionEnd = newEnd

},

insertItem() {

const {

chunk,

offset,

list,

cur,

atEnd

} = this.atwho

const {

suffix,

atItems

} = this

const el = this.$el.querySelector('textarea')

const text = el.value.slice(0, atEnd)

const {

at,

index

} = this.getAtAndIndex(text, atItems)

const start = index + at.length // 从@后第一位开始

el.selectionStart = start

el.focus() // textarea必须focus回来

const curItem = list[cur]

const t = '' + curItem + suffix

this.insertText(t, el)

this.$emit('insert', curItem) //插入字符

this.handleInput()

}

}

}

.atwho-wrap {

width: 100%;

font-size: 12px;

color: #333;

position: relative;

.atwho-panel {

position: absolute;

&.test {

width: 2px;

height: 2px;

background: red;

}

.atwho-inner {

position: relative;

}

}

.atwho-view {

color: black;

z-index: 11110 !important;

border-radius: 2px;

box-shadow: 0 0 10px 0 rgba(101, 111, 122, .5);

position: absolute;

cursor: pointer;

background-color: rgba(255, 255, 255, .94);

width: 170px;

max-height: 312px;

&::-webkit-scrollbar {

width: 11px;

height: 11px;

}

&::-webkit-scrollbar-track {

background-color: #F5F5F5;

}

&::-webkit-scrollbar-thumb {

min-height: 36px;

border: 2px solid transparent;

border-top: 3px solid transparent;

border-bottom: 3px solid transparent;

background-clip: padding-box;

border-radius: 7px;

background-color: #C4C4C4;

}

}

.atwho-ul {

list-style: none;

padding: 0;

margin: 0;

li {

box-sizing: border-box;

display: block;

height: 25px;

padding: 2px 10px;

white-space: nowrap;

display: flex;

align-items: center;

justify-content: space-between;

&.atwho-cur {

background: #f2f2f5;

color: #eb7350;

}

span {

overflow: hidden;

text-overflow: ellipsis;

}

img {

height: 13px;

width: 13px;

}

}

}

}

最后

以上就是年轻店员为你收集整理的艾特某人代码实现_Vue@某人,At某人,仿新浪微博@某人,@user,艾特,艾特某人...的全部内容,希望文章能够帮你解决艾特某人代码实现_Vue@某人,At某人,仿新浪微博@某人,@user,艾特,艾特某人...所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(42)

评论列表共有 0 条评论

立即
投稿
返回
顶部