vue如何获取光标位置
作者:波塞西呀
这篇文章主要介绍了vue获取光标位置方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
vue获取光标位置
新建组件configFormulaSalary
<template> <div> <el-dialog title="公式配置" :visible="isConfigFormula" top="15vh" width="1200px" custom-class="config-dialog" :before-close="onClose" append-to-body :close-on-click-modal="false" @mousedown.native="handleDialogMousedown($event)" @mouseup.native="handleDialogMouseup($event)" > <div class="form-main"> <div class="left-cont"> <div class="left-title">{{info? info.name : ''}}=</div> <div class="input-box"> <el-input type="textarea" v-model="formulaValue" autofocus="autofocus" @keyup.enter.native="searchHandle" ref="configInput" id="configInput" placeholder="请输入计算公式或选择函数" @focus="getCursor"></el-input> </div> <div class="formula-btn"> <div class="formula-left"> <el-button class="btn-experience" @click="onCheckItemFormula">公式校验</el-button> <span class="margin-l-20 tips-box" v-if="msgSuccessTips"> <i class="el-icon-circle-check"></i> {{msgSuccessTips}} </span> <span class="margin-l-20 tips-box err" v-if="msgErrorTips"> <i class="el-icon-circle-close"></i> {{msgErrorTips}} </span> </div> <div class="right-form-btn"> <el-select v-model="formulaRule" placeholder="请选择" class="config-select-btn"> <el-option v-for="item in formulaRuleList" :key="item.value" :label="item.label" :value="item.value"> </el-option> </el-select> <span class="label-text">保留</span> <el-select v-model="decimalPoint" placeholder="请选择" class="select-right"> <el-option v-for="item in decimalPointList" :key="item" :label="item" :value="item"> </el-option> </el-select> <span class="label-text">位小数</span> </div> </div> <div class="formula-item"> <span class="item-title">快捷运算符</span> <span class="formula-label" v-for="(unit,indexU) in formulaTypeList" :key="indexU" @click="onSelectOperator(unit.value)">{{unit.label}}</span> </div> <div class="bottom-drap"> <div class="drap-title">点击选择薪资字段</div> <div class="drap-list"> <!-- <el-checkbox-group v-model="drapSelectList" @change="onSelect"> <el-checkbox-button v-for="(drap,indexD) in drapList" :label="'#'+drap+'#'" :key="indexD">{{drap}}</el-checkbox-button> </el-checkbox-group> --> <div class="list" v-for="(drap,indexD) in drapList" :key="indexD"> <div class="item" @click="onSelect(drap,'#')" v-if="info.name !==drap">{{drap}}</div> </div> </div> </div> </div> <div class="right-cont" @mouseleave="onLeave"> <div class="title-bar">插入函数</div> <div class="right-box"> <div class="box-title-bar">常用函数</div> <ul class="box-item-list" > <li class="item-cont" v-for="(formula,indexV) in formulaData.common" :key="indexV" @mouseenter="onEnterFormulaData(indexV,formula,1)" :class="isSelectIndex1 == indexV?'is-active':''" @click="onSelect(formula.grammar)"> <span>{{formula.title}}</span> <el-button type="text">插入</el-button> </li> </ul> <div class="box-title-bar">系统函数</div> <ul class="box-item-list"> <li class="item-cont" v-for="(formula,indexV) in formulaData.system" :key="indexV" @mouseenter="onEnterFormulaData(indexV,formula,2)" :class="isSelectIndex2 == indexV?'is-active':''" @click="onSelect(formula.grammar)"> <span>{{formula.title}}</span> <el-button type="text">插入</el-button> </li> </ul> </div> <div class="right-item-por" v-show="selectClass"> <div class="title">{{selectFunObj.title}}</div> <p v-html="selectFunObj.describe"></p> </div> </div> </div> <span slot="footer" class="dialog-footer"> <el-button @click="onClose">取 消</el-button> <el-button type="primary" @click="onSubmit('ruleForm')">确 定</el-button> </span> </el-dialog> </div> </template>
<script> // import {getCommonAndSystemFunctions,checkItemFormula} from "@/api/salary" export default { props: { isConfigFormula: Boolean, info: Object, drapList: Array, fieldGroupList: Array }, data () { return { formulaValue: '', formulaRule: 'round', formulaRuleList: [ { value: 'round', label:'四舍五入' }, { value: 'floor', label:'向下取整' }, { value: 'ceil', label:'向上取整' }, ], blurIndex: null,//输入框光标位置 msgSuccessTips: '', msgErrorTips: '', decimalPoint: 2, decimalPointList: [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15], formulaTypeList: [ {value: '+', label: '+'}, {value: '-', label: '-'}, {value: '*', label: '*'}, {value: '/', label: '/'}, {value: '()', label: '()'}, {value: '>', label: '>'}, {value: '<', label: '<'}, {value: '=', label: '='}, {value: '>=', label: '≥'}, {value: '<=', label: '≤'}, {value: '!=', label: '≠'}, {value: "''", label: "''"}, ], drapSelectList: [], selectFunObj: {}, selectClass: false, isSelectIndex1: null, isSelectIndex2: null, formulaData:{ system: [], common: [], }, classDialogmodel: false, } }, created(){ if (this.info) { this.formulaValue = this.info.text this.formulaRule = this.info.mode || 'round' this.decimalPoint = this.info.count !==null && this.info.count !== undefined ? this.info.count : 2 this.getList() } }, methods: { // 选择薪资项 onSelect(e,value){ let index=this.blurIndex let str=this.formulaValue if(value) { // this.formulaValue = this.formulaValue + ' #'+e+'#' let formulaValue ='#'+e+'#' this.insertAtCursor(formulaValue) } else { // this.formulaValue = this.formulaValue +e // this.formulaValue=str.slice(0, index) + e + str.slice(index); this.insertAtCursor(e) } }, onSelectOperator(e){ // this.formulaValue = this.formulaValue +e this.insertAtCursor(e) }, // 获取光标位置 async insertAtCursor(myValue) { const myField = document.querySelector('#configInput'); // const myField = this.$refs.configInput; if (myField.selectionStart || myField.selectionStart === 0) { var startPos = myField.selectionStart var endPos = myField.selectionEnd this.formulaValue = myField.value.substring(0, startPos) + myValue + myField.value.substring(endPos, myField.value.length) await this.$nextTick() // 这句是重点, 圈起来 myField.focus() // 检测函数是否下一次插入点位置 设置光标位置 if(myValue.indexOf('(') !== -1) { let arr = myValue.split('') let index = arr.findIndex(o=>{return o=='('}) // myField.setSelectionRange(endPos + myValue.length, endPos + myValue.length) myField.setSelectionRange(endPos + index+1, endPos + index+1) } else { myField.setSelectionRange(endPos + myValue.length, endPos + myValue.length) } } else { this.formulaValue += myValue } }, onCheckItemFormula() { let arr = this.fieldGroupList.reduce((last,next)=>{ return last.concat(...next.fieldList) },[]) let parmetn = { checkItemName: this.info.name, formulaText: this.formulaValue, salaryItemGroupList: Array.from(new Set(arr)), } this.msgSuccessTips = '' this.msgErrorTips = '' // checkItemFormula(parmetn).then(res=> { // if(res.code='SUCCESS') { // this.msgSuccessTips = res.message // } // }).catch(err=> { // this.$message.error({ // message: err.message // }) // this.msgErrorTips = err.message // }) }, getCursor(e){ this.blurIndex = e.srcElement.selectionStart }, searchHandle(event) { event.preventDefault(); }, onLeave(vule){ this.selectClass = false; this.isSelectIndex1 = null this.isSelectIndex2 = null }, onEnterFormulaData(index,row,type) { this.selectClass = true this.selectFunObj = row if(type==1) { this.isSelectIndex1 = index this.isSelectIndex2 = null } else { this.isSelectIndex1 = null this.isSelectIndex2 = index } }, onClose () { this.$emit('onClose') }, onSubmit () { let data = { formulaValue: this.formulaValue, mode: this.formulaRule, count: this.decimalPoint, } this.$emit('onSubmitEdit',data) }, onRuleChange(event) { this.ruleForm.ruleId = event }, getList () { // getCommonAndSystemFunctions().then(res=> { // if(res.code=="SUCCESS") { // this.formulaData.common = res.common // this.formulaData.system = res.system // } // }).catch(err=> { // this.$message.error({ // message: err.message // }) // }) }, // 监测弹框鼠标事件 handleDialogMousedown(e) { // 如果为true,则表示点击发生在遮罩层 this.classDialogmodel= !!e.target.classList.contains('el-dialog__wrapper') }, handleDialogMouseup(e) { if((!!e.target.classList.contains('el-dialog__wrapper')) && this.classDialogmodel){ this.onClose() } this.classDialogmodel=false }, }, watch: { isConfigFormula() { if(this.isConfigFormula) { this.getList() } } } } </script>
<style lang="less" scoped> @deep: ~'>>>'; // 删除薪资组 @{deep}.config-dialog { .el-dialog__header { padding: 20px 24px 14px; font-size: 18px; line-height: 18px; font-family: PingFang SC; font-weight: 400; color: #333; border-bottom: 1px solid #E9E9E9; } .form-main { display: flex; justify-content: flex-start; } .el-dialog__body { padding: 0 !important; } .el-dialog__footer { text-align: right; padding-top: 10px; padding-bottom: 14px; border-top: 1px solid #E9E9E9; .el-button { padding: 0; width: 80px; height: 32px; text-align: center; line-height: 32px; font-size: 14px; font-family: PingFang SC; font-weight: 400; } .close-but { border: 1px solid #D9D9D9; border-radius: 4px; color: #666666; &:hover { background: transparent; } } .primary-btn { color: #FFFFFF; background: #3277FF; border-radius: 4px; } } .left-cont { width: 850px; padding: 0 24px; border-right: 1px solid #E8E8E8; .left-title { font-size: 14px; font-family: 'PingFang-SC-Bold'; font-weight: bold; color: #333; padding: 14px 0; } .input-box { padding-bottom: 10px; .el-textarea__inner { width: 100%; height: 124px; line-height: 26px; border: 1px solid #D5D5D5; border-radius: 4px; font-size: 14px; color: #333; padding: 0 10px; &::placeholder { font-size: 14px; font-family: PingFang SC; font-weight: 400; // color: #CCCCCC; } } } .formula-btn { display: flex; justify-content: space-between; align-items: center; padding-bottom: 24px; .btn-experience { width: 86px; height: 32px; padding: 0; text-align: center; line-height: 32px; background: #3277FF; border-radius: 4px; border-color: #3277FF; font-size: 14px; font-family: PingFang SC; font-weight: 400; color: #FFFFFF; } .right-form-btn { } .config-select-btn { .el-input__inner { width: 102px; height: 32px; line-height: 32px; background: #FFFFFF; border: 1px solid #D5D5D5; border-radius: 4px; // color: #333; &::placeholder { // color: #666; } } .el-input__icon { line-height: 32px; } } .select-right { margin-left: 10px; .el-input__inner { width: 56px; height: 32px; line-height: 32px; background: #FFFFFF; border: 1px solid #D5D5D5; border-radius: 4px; // color: #333; &::placeholder { // color: #666; } } .el-input__icon { line-height: 32px; } } .label-text { display: inline-block; font-size: 14px; font-family: PingFang SC; padding-left: 10px; font-weight: 400; color: #666666; } } .formula-item { display: flex; justify-content: flex-start; align-items: center; padding-bottom: 14px; .item-title { display: inline-block; font-size: 14px; font-family: 'PingFang-SC-Bold'; font-weight: bold; color: #333; margin-right: 12px; } .formula-label { display: inline-block; width: 44px; height: 32px; text-align: center; line-height: 30px; font-size: 20px; font-family: 'PingFang-SC-Medium'; font-weight: 500; color: #666666; border: 1px solid #D5D5D5; border-radius: 4px; margin-right: 14px; cursor: pointer; &:hover,&.is-active { border-color: #3277FF; color: #3277FF; } } } .bottom-drap { padding-bottom: 25px; .drap-title { font-size: 14px; line-height: 14px; padding-bottom: 15px; font-family: 'PingFang-SC-Bold'; font-weight: bold; color: #333; } .drap-list { width: 801px; height: 200px; background: #FAFAFA; overflow: hidden; overflow-y: scroll; padding: 15px 10px; display: flex; // align-items: center; flex-wrap: wrap; .item{ width: 118px; padding: 0 10px; height: 32px; line-height: 30px; text-align: center; font-size: 14px; font-family: PingFang SC; font-weight: 400; color: #333; background: #FFFFFF; border: 1px solid #D9D9D9; border-radius: 4px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; margin-right: 14px; margin-bottom: 14px; cursor: pointer; } &::-webkit-scrollbar { /*滚动条整体样式*/ display: none; } } .el-checkbox-button { .el-checkbox-button__inner { width: 118px; padding: 0 10px; height: 32px; line-height: 30px; text-align: center; font-size: 14px; font-family: PingFang SC; font-weight: 400; color: #333; background: #FFFFFF; border: 1px solid #D9D9D9; border-radius: 4px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; margin-right: 14px; margin-bottom: 14px; } &:nth-child(6n){ .el-checkbox-button__inner { margin-right: 0; } } &.is-checked,&:hover { .el-checkbox-button__inner { border-color: #3277FF; color: #3277FF; } } } } } .formula-left { display: flex; justify-content: flex-start; align-items: center; .tips-box { display: inline-block; font-size: 14px; max-width: 350px; line-height: 16px; color: #15bc83; &.err { color: #ff4141; } } } .right-cont { padding: 0 24px; position: relative; .title-bar { font-size: 14px; font-family: PingFang SC; font-weight: 400; color: #333; line-height: 42px; } .right-box { width: 301px; height: 480px; border: 1px solid #DCDCDC; border-radius: 4px; overflow: hidden; overflow-y: scroll; padding: 12px 0px; &::-webkit-scrollbar { /*滚动条整体样式*/ width: 6px; /*高宽分别对应横竖滚动条的尺寸*/ height: 1px; background-color: transparent; } &::-webkit-scrollbar-thumb { /*滚动条里面小方块*/ border-radius: 2px; border: 5px solid #A9AAB1; box-shadow: 5px 0 0 #A9AAB1 inset; } &::-webkit-scrollbar-thumb:hover { box-shadow: 5px 0 0 #A9AAB1 inset; } .box-title-bar { font-size: 14px; font-family: PingFang SC; font-weight: 400; color: #AEAEAE; line-height: 14px; padding:0 5px, } .box-item-list { padding: 8px 0; } .item-cont { font-size: 14px; font-family: PingFang SC; font-weight: 400; color: #333; line-height: 14px; padding: 10px 12px; cursor: pointer; display: flex; justify-content: space-between; align-items: center; &:hover, &.is-active { background: #3277FF; color: #fff; } .el-button { padding: 0; color: #fff; } } } .right-item-por { position: absolute; left: -280px; height: 480px; width: 300px; overflow: hidden; overflow-y: scroll; padding: 10px 20px; background: #fff; border: 1px solid #DCDCDC; top: 41px; border-radius: 4px; font-size: 12px; color: #333; line-height: 30px; &::-webkit-scrollbar { /*滚动条整体样式*/ width: 6px; /*高宽分别对应横竖滚动条的尺寸*/ height: 1px; background-color: transparent; } &::-webkit-scrollbar-thumb { /*滚动条里面小方块*/ border-radius: 2px; border: 5px solid #A9AAB1; box-shadow: 5px 0 0 #A9AAB1 inset; } &::-webkit-scrollbar-thumb:hover { box-shadow: 5px 0 0 #A9AAB1 inset; } .title { font-size: 16px; color: #333; line-height: 30px; } } } } </style>
在父组件中引入configFormulaSalary
<!-- 配置 --> <configFormulaSalary :isConfigFormula="isConfigFormula" :drapList="drapList" :info="formulaSalaryInfo" @onClose="onConfigFormulaClose" @onSubmitEdit="onConfigFormulaGroup" v-if="isConfigFormula" :fieldGroupList="fieldGroupList"></configFormulaSalary> <script> import configFormulaSalary from './components/configFormulaSalary.vue' export default { name: 'App', components: { HelloWorld, configFormulaSalary }, data () { return { isConfigFormula:false, classmodel: false, drapList:[], formulaSalaryInfo:{}, fieldGroupList: [] } }, methods: { // 关闭配置弹框 onConfigFormulaClose(){ this.isConfigFormula = false }, // 打开配置弹框 onConfigFormulaGroup(e){ this.isConfigFormula = true }, } } </script>
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。