vue的使用,vue实现聊天功能
这篇文章主要介绍了如何通过某视频剪辑软件实现微博中常见的@人的功能,同时增加鼠标点击事件和一些页面小优化。感兴趣的小伙伴可以跟随小编一起学习一下
本文采用vue,同时增加鼠标点击事件和一些页面小优化
基本结构
新建一个sandBox.vue文件编写功能的基本结构
div class=内容
!-文本框-
差异
编辑器
ref=divRef
内容可编辑
@keyup=handkeKeyUp
@keydown=handleKeyDown
/div
!-选项-
AtDialog
v-if=showDialog
:visible=showDialog
:位置=位置
:queryString=queryString
@onPickUser=handlePickUser
@onHide=handleHide
@onShow=handleShow
/AtDialog
/div
脚本
从对话框导入./components/AtDialog
导出默认值{
名称:"沙箱",
组件:{ AtDialog },
data () {
返回{
节点: ,//获取到节点
用户: ,//选中项的内容
endIndex: ,//光标最后停留位置
查询字符串: ,//搜索值
showDialog: false,//是否显示弹窗
职位:{
x: 0,
y: 0
}//弹窗显示位置
}
},
方法:{
//获取光标位置
getCursorIndex () {
常量选择=窗口。获取选择()
return selection.focusOffset //选择开始处焦点节点的偏移量
},
//获取节点
getRangeNode () {
常量选择=窗口。获取选择()
return selection.focusNode //选择的结束节点
},
//弹窗出现的位置
getRangeRect () {
常量选择=窗口。获取选择()
常量范围=选择。getrangeat(0)//是用于管理选择范围的通用对象
const rect=范围。getclientrects()[0]//择一些文本并将获得所选文本的范围
const LINE_HEIGHT=30
返回{
x: rect.x,
y:矩形线条高度
}
},
//是否展示@
showAt () {
const node=this.getRangeNode()
如果(!节点 node.nodeType!==节点. TEXT_NODE)返回错误的
常量内容=节点。文本内容
const regx=/@([^@\s]*)$/
常量匹配=regx。执行(内容。slice(0,this.getCursorIndex()))
返回匹配match.length===2
},
//获取@用户
getAtUser () {
const content=this.getRangeNode().textContent
const regx=/@([^@\s]*)$/
常量匹配=regx。执行(内容。slice(0,this.getCursorIndex()))
if (match match.length===2) {
返回匹配[1]
}
返回未定义
},
//创建标签
createAtButton(用户){
常量BTN=文档。createelement(“span”)
BTN。风格。display= inline-block
BTN。数据集。用户=JSON。字符串(用户)
BTN。类名=at-button
btn.contentEditable=false
btn.textContent=`@${user.name} `
const wrapper=文档。createelement(“span”)
包装纸。风格。display= inline-block
wrapper.contentEditable=false
const space elem=文档。createelement(“span”)
太空元素。风格。空白= pre
spaceElem.textContent=\u200b
太空元素。内容可编辑= false
const clonedSpaceElem=spaceelem。克隆节点(真)
wrapper.appendChild(spaceElem)
wrapper.appendChild(btn)
包装纸。appendchild(克隆空间元素)
返回包装
},
replaceString (raw,replacer) {
返回raw.replace(/@([^@\s]*)$/,替换者)
},
//插入@标签
替换用户(用户){
常量节点=this .节点
如果(节点用户){
常量内容=节点。文本内容
const endIndex=this.endIndex
const pres切片=this。替换字符串(内容。slice(0,endIndex),)
const rest slice=内容。切片(结束索引)
const父节点=节点。亲代交点
const nextNode=node.nextSibling
const previousTextNode=新文本(前切片)
const nextTextNode=新文本( \u200b restSlice) //添加0 宽字符
const at button=this。createatbutton(用户)
parentNode.removeChild(node)
//插在文本框中
if (nextNode) {
父节点。在前面插入(上一个文本节点,下一个节点)
父节点。在之前插入(在按钮处,下一个节点)
父节点。在前面插入(下一个文本节点,下一个节点)
}否则{
父节点。appendchild(上一个文本节点)
父节点。appendchild(在按钮上)
父节点。appendchild(下一个文本节点)
}
//重置光标的位置
常量范围=新范围()
常量选择=窗口。获取选择()
range.setStart(nextTextNode,0)
range.setEnd(nextTextNode,0)
selection.removeAllRanges()
selection.addRange(范围)
}
},
//键盘抬起事件
handkeKeyUp () {
if (this.showAt()) {
const node=this.getRangeNode()
常数结束索引=this。getcursorindex()
this.node=节点
this.endIndex=endIndex
这个。位置=这个。getrangerect()
这个。查询字符串=this。getatuser()
this.showDialog=true
}否则{
this.showDialog=false
}
},
//键盘按下事件
手柄向下键(e) {
if (this.showDialog) {
if (e.code===ArrowUp
e.code===向下箭头
e.code===Enter) {
预防默认()
}
}
},
//插入标签后隐藏选择框
handlePickUser(用户){
this.replaceAtUser(用户)
this.user=用户
this.showDialog=false
},
//隐藏选择框
handleHide () {
this.showDialog=false
},
//显示选择框
handleShow () {
this.showDialog=true
}
}
}
/脚本
样式范围的语言=scss 。内容{
字体系列:无衬线字体;
h1{
文本对齐:居中;
}
}。编辑{
边距:0自动;
宽度:600像素
高度:150像素
背景:# fff
边框:1px纯蓝;
边框半径:5px
文本对齐:左对齐;
填充:10px
溢出:自动;
行高:30px
:焦点{
大纲:无;
}
}
/风格
如果添加了点击事件,节点和光标位置获取,需要在【键盘抬起事件】中获取,并保存到数据
//键盘抬起事件
handkeKeyUp () {
if (this.showAt()) {
常量节点=this。getrangenode()//获取节点
常数结束索引=this。getcursorindex()//获取光标位置
this.node=节点
this.endIndex=endIndex
这个。位置=这个。getrangerect()
这个。查询字符串=this。getatuser()
this.showDialog=true
}否则{
this.showDialog=false
}
},
新建一个组件,编辑弹窗选项
模板
差异
class=包装器
:style={position:fixed ,top:position.y px ,left:position.x px}
div v-if=! mockList.length class=empty 无搜索结果/div
差异
v-for=(item,i) in mockList
:key=item.id
class=item
:class={active: i===index}
ref=usersRef
@click=clickAt($event,item)
@mouseenter=hoverAt(i)
div class= name"{ item。name } }/div
/div
/div
/模板
脚本
const mockData=[
{名称: HTML ,id: HTML },
{名称: CSS ,id: CSS },
{名称: Java ,id: Java },
{名称: JavaScript ,id: JavaScript }
]
导出默认值{
名称: AtDialog ,
道具:{
可见:布尔型,
位置:对象,
查询字符串:字符串
},
data () {
返回{
用户:[],
索引:-1,
模拟列表:模拟数据
}
},
观察:{
查询字符串(瓦尔){
瓦尔这个。模拟列表=模拟数据。筛选器(({ name })=名称。以(val))开头:这个。模拟列表=模拟数据。切片(0)
}
},
已安装(){
文档。addevent侦听器( keyup ,this.keyDownHandler)
},
销毁(){
文档。移除事件侦听器( keyup ,this.keyDownHandler)
},
方法:{
keyDownHandler (e) {
if (e.code===Escape) {
这个emit(onHide )
返回
}
//键盘按下=
if (e.code===ArrowDown) {
如果(这个。指数=这个。模拟列表。长度-1){
this.index=0
}否则{
this.index=this。索引一
}
}
//键盘按下=
if (e.code===ArrowUp) {
if (this.index=0) {
这个。指数=这个。模拟列表。长度-1
}否则{
this.index=this.index - 1
}
}
//键盘按下=回车
if (e.code===Enter) {
if (this.mockList.length) {
const user={
名称当前位置.姓名,
id: this.mockList[this.index].编号
}
这个发出( onPickUser ,用户)
这个。索引=-1
}
}
},
单击(e,项目){
const user={
名称:项目名称,
id:项目。编号
}
这个发出( onPickUser ,用户)
这个。索引=-1
},
hoverAt(索引){
this.index=index
}
}
}
/脚本
样式范围的语言=scss 。包装{
宽度:238像素
边框:1px实心# e4e 7版;
边框-半径:4px
背景色:# fff
box-shadow:0 2px 12px 0 RGB(0 0 0/10%);
框大小:边框-框;
填充:6px 0;
}。空的
字体大小:14px
填充:0 20像素
颜色:# 999;
}。项目{
字体大小:14px
填充:0 20像素
行高:34px
光标:指针;
颜色:# 606266;活动{
背景:# f5f 7 fa
颜色:蓝色;id {
颜色:蓝色;
}
}
:第一个孩子{
border-radius:5px 5px 0 0;
}
:最后一个孩子{
边框半径:0 0 5px 5px
}。id {
字体大小:12px
颜色:rgb(83,81,81);
}
}
/风格
以上就是如何通过某视频剪辑软件实现@人的功能的详细内容,更多关于Vue @人功能的资料请关注我们其它相关文章!
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。