vue ElementUI textarea在光标位置插入指定变量及校验
需求
项目需求:TTS功能(文本转语音),需要在文本中添加变量,也就是一个固定模版,通过不同变量完成来改变模版内容,例如:【你好,{姓名}】(这里的{姓名}在传往后端时会转为{name}) ===》【你好,李伟】或【你好,孟浩然】等等。(项目是vue2项目ElementUI)。
要求:大括号不能嵌套,大括号数量不能超过5对。
效果
代码
HTML模块
<template><el-form ref="form":model="form":rules="rules"label-width="55px"v-loading="loading">...<el-form-item label="内容"prop="contextStr"><el-input v-model.trim="form.contextStr"type="textarea"ref="textarea"show-word-limitmaxlength="150":autosize="{ minRows: 4, maxRows: 6}"@blur="blurEvent"></el-input><div class="tab-box"><el-tag v-for="item in customKeyList":key="item.name"color="#6a7aee"size="small"style="cursor: pointer; border-color: #6a7aee; color: #fff;"@click="onClickTab(item)">{{ item.id }}</el-tag></div></el-form-item>...<el-form-item><el-button size="small"type="primary"@click="onSubmit">确 认</el-button></el-form-item></el-form>
</template>
JS模块
export default {data() {return {...customKeyList: [{id: "名称", name: "name"},{id: "号码", name: "phone"},{id: "自定义字段1", name: "customize1"},{id: "自定义字段2", name: "customize2"},{id: "自定义字段3", name: "customize3"},{id: "自定义字段4", name: "customize4"},],form: {...context: '', // 内容contextStr: '', // 内容...},rules: {...contextStr: [{ required: true, message: '请输入内容', trigger: 'blur' },{ min: 1, max: 150, message: '长度在1到150个字符', trigger: 'blur' }]...}...}},methods:{// 获取光标所在位置的indexblurEvent(e) {this.blurIndex = e.srcElement.selectionStart // 光标所在的位置},onClickTab(obj) {if (this.form.contextStr.length >= 150) {this.$message.error('内容长度不能超过 150 个字符')return}const message = this.isCorrectBracket(this.form.contextStr) // 判断括号是否正确if (message) {this.$message.error(message)return}const right = this.form.contextStr.slice(0, this.blurIndex).lastIndexOf('}' )const left = this.form.contextStr.slice(0, this.blurIndex).lastIndexOf('{')if (left >= 0 && right >= 0) { // 两个都存在if (left > right) {this.$message.error('当前光标聚焦的位置不对,或‘{}’不对称!')return}} else if (left >= 0 || right >= 0) { // 有一个不存在this.$message.error('当前光标聚焦的位置不对,或‘{}’不对称!')return}this.form.contextStr = this.form.contextStr.slice(0, this.blurIndex) + '{' + obj.id + '}' + this.form.contextStr.slice(this.blurIndex)this.blurIndex = this.blurIndex + obj.id.length + 2this.$refs.form.validateField('contextStr')},isCorrectBracket(str, bool) { // 判断括号是否正确 括号不可嵌套且需成对出现 参数bool位 true校验是否正确 false或null判断是否可添加let errorMsg = ''const BracketsDic = {'{': '}'}let leftBracket = nulllet leftBracketIndex = nulllet index = 1let countL = 0 // 左大括号数量let countR = 0 // 右大括号数量for (const char of str) {// 是否左括号if (char === '{') {countL++ // 记录存在多少个右括号// 是否已有左括号if (leftBracket) {errorMsg = `因括号不可嵌套,第${leftBracketIndex}个字符 ${leftBracket} 在匹配右括号前,不能出现第${index}个字符 ${char} `break} else {leftBracket = charleftBracketIndex = index}} else {// 是否右括号if (char === '}') {countR++// 是否已有左括号if (leftBracket) {// 是否匹配左括号if (BracketsDic[leftBracket] === char) {leftBracket = nullleftBracketIndex = null} else {errorMsg = `第${leftBracketIndex}个字符 ${leftBracket} 与第${index}个字符 ${char} 不匹配`break}} else {errorMsg = `第${index}个字符 ${char} 前缺少左括号`break}}}index++}if (!errorMsg) {if (leftBracket) {errorMsg = `第${leftBracketIndex}个字符 ${leftBracket} 后缺少右括号`}}if ((countL === countR)) {if (bool) {if (countL > 10) {errorMsg = `最多只能存在10对大括号,当前大括号数量${countL}对`}} else {if (countL >= 10) {errorMsg = `最多只能存在10对大括号,当前大括号数量${countL}对`}}}return errorMsg},setContext() { // 设置contextStr对应的context字段this.form.context = this.form.contextStrthis.customKeyList.forEach(element => {this.form.context = this.form.context.replaceAll('{' + element.id + '}', '{' + element.name + '}')})},onSubmit() {const message = this.isCorrectBracket(this.form.context_str, true)if (message) {this.$message.error(message)return} else {this.setContext() // 设置contextStr}this.$refs.form.validate((valid) => {....})}}
}
CSS模版
.el-tag {margin-right: 10px;user-select: none;
}