Skip to content

How to solve this bug where when deleting content with spaces, the mouse cursor will automatically return to the beginning of the first line when encountering spaces #229

@15515507548

Description

@15515507548

Describe the bug

下面是vue-codemirror的使用

<style> .el-form-item--mini .el-form-item__content, .el-form-item--mini .el-form-item__label, .el-form-item__content { line-height: 20px; } .velocity-tip { color: #606266; font-size: 13px; font-weight: normal; } .velocity-var { } .velocity-var li { font-size: 14px; color: #606266; line-height: 26px; } .velocity-var a { color: #409eff; font-weight: 500; } .velocity-var a:hover { color: rgba(64, 158, 255, 0.75); } .hasFix { position: fixed; top: 0; } .el-dropdown-link { cursor: pointer; color: #409eff; } .el-icon-arrow-down { font-size: 12px; } span.split { color: #ccc; margin: 0 3px; } </style> <script> import { codemirror } from "vue-codemirror"; import "codemirror/theme/neat.css"; import "codemirror/theme/darcula.css"; import "codemirror/theme/material.css"; /** 搜索 替换框置顶*/ import "codemirror/addon/scroll/annotatescrollbar.js"; import "codemirror/addon/search/matchesonscrollbar.js"; import "codemirror/addon/search/match-highlighter.js"; import "codemirror/addon/search/jump-to-line.js"; import "codemirror/addon/dialog/dialog.js"; import "codemirror/addon/dialog/dialog.css"; import "codemirror/addon/search/searchcursor.js"; import "codemirror/addon/search/search.js"; require("codemirror/mode/velocity/velocity"); import "codemirror/theme/ambiance.css"; import "codemirror/lib/codemirror.css"; import "codemirror/addon/hint/show-hint.css"; require("codemirror/addon/edit/matchbrackets"); require("codemirror/addon/selection/active-line"); require("codemirror/mode/sql/sql"); require("codemirror/addon/hint/show-hint"); require("codemirror/addon/hint/sql-hint"); require("codemirror/mode/clike/clike.js"); require("codemirror/addon/edit/closebrackets.js"); import "codemirror/mode/javascript/javascript.js"; import "codemirror/addon/lint/lint.css"; import "codemirror/addon/lint/lint.js"; import "codemirror/addon/selection/active-line.js"; const TEMPLATE_CODE_THEME = "gen.template.code.theme"; export default { components: { codemirror }, props: { formData: { type: Object, default: () => ({ content: "", labeName: "" }), }, isNoEdit: { type: Boolean, default: false, }, maxHeight: { type: String, default: "calc(-203px + 100vh)", }, }, inject: ["developLowCodeIndex"], data() { return { error_Msg: "", codeThemeList: ["neat", "darcula", "material"], shortcutKeyList: [ "保存(Ctrl+S)", "删除当行(Ctrl+D)", "复制当行(Ctrl+C)", "剪切当行(Ctrl+X)", "替换(Ctrl+Shift+F)", ], //code mirror配置 cmOptions: { value: "", mode: "text/x-java", theme: "neat", readOnly: false, tabSize: 4, // tab的空格个数 indentUnit: 2, // 一个块(编辑语言中的含义)应缩进多少个空格 autocorrect: true, // 自动更正 spellcheck: true, // 拼写检查 lint: true, // 检查格式 lineNumbers: true, //是否显示行数 lineWrapping: true, //是否自动换行 styleActiveLine: true, //line选择是是否高亮 // keyMap: 'intellij', // sublime编辑器效果 matchBrackets: true, //括号匹配 autoCloseBrackets: true, // 在键入时将自动关闭括号和引号 matchTags: { bothTags: true }, // 将突出显示光标周围的标签 foldGutter: true, // 可将对象折叠,与下面的gutters一起使用 gutters: [ "CodeMirror-lint-markers", "CodeMirror-linenumbers", "CodeMirror-foldgutter", ], highlightSelectionMatches: { minChars: 2, style: "matchhighlight", showToken: true, }, hintOptions: { // 自定义提示选项 completeSingle: false, // 当匹配只有一项的时候是否自动补全 tables: {}, // 代码提示 }, }, marks: [], errorsLists: [], }; }, mounted() { //初始化代码主题 this.cmOptions.theme = this.getAttr(TEMPLATE_CODE_THEME) || "neat"; this.$nextTick(() => { this.$refs.editor.codemirror.on("inputRead", (cm, event) => { if (this.isNoEdit) { if (/^[a-zA-Z\.=]$/gi.test(event.text[0])) { cm.showHint(); } } else { const index = this.formData.labeName.lastIndexOf("."); const code = this.formData.labeName.slice(index); if (code === ".java") { if (/^[a-zA-Z\.=]$/gi.test(event.text[0])) { cm.showHint(); } } } }); this.$refs.editor.codemirror.on("blur", () => { if (this.formData.content) { this.$emit("fatherMethod", false); } else { this.$emit("fatherMethod", true); } }); this.$refs.editor.codemirror.on("mousedown", (cm, event) => { const editorTop = cm.getScrollerElement().getBoundingClientRect().top; const clickY = event.clientY - editorTop; // 计算点击位置对应的行号 const line = cm.lineAtHeight(clickY, "local"); console.log(`点击处的行数是: ${line + 1}`); const obj = this.errorsLists.find( (item) => item.lineNumber == line + 1 ); if (obj) { if ( ["/developLowCode", "/sourceCodePreview"].includes(this.$route.path) ) { this.developLowCodeIndex.$refs.dialogue.sendText(obj.errorMsg); } else if (this.$route.path == "/develop_LowCode") { this.developLowCodeIndex.developLowCodeIndex.$refs.dialogue.sendText( obj.errorMsg ); } } }); }); }, methods: { addErrorMarkers(errors) { if (errors?.length) { this.error_Msg = ""; const nolineNumber = errors.filter((item) => !item.lineNumber); nolineNumber.forEach((list) => { this.error_Msg += list.errorMsg; }); const havelineNumber = errors.filter((item) => item.lineNumber); this.errorsLists = havelineNumber; if (this.errorsLists.length) { const cm = this.$refs.editor.codemirror; this.errorsLists.forEach((error) => { cm.setGutterMarker( +error.lineNumber - 1, "CodeMirror-lint-markers", this.makeCircleMarker( `行号:${error.lineNumber}\n错误信息:${error.errorMsg.replace( /\n/g, "" )}` ) ); this.addRedBackground(cm, +error.lineNumber); }); } } }, addRedBackground(cm, lineNumber) { const start = { line: lineNumber - 1, ch: 0 }; const end = { line: lineNumber, ch: 0 }; cm.markText(start, end, { className: "red-background", }); }, makeCircleMarker(msg) { const circle = document.createElement("div"); circle.style.backgroundColor = "red"; circle.style.borderRadius = "50%"; circle.style.width = "8px"; circle.style.height = "8px"; circle.style.marginTop = "4px"; circle.style.marginLeft = "15px"; circle.style.cursor = "pointer"; circle.style.opacity = "0.7"; circle.title = msg; return circle; }, markText(val) { let str = ""; const filterSpace = val.replace(/^\s+|\s+$/g, ""); const index1 = filterSpace.indexOf("\r"); const index2 = filterSpace.indexOf("\n"); if (index1 > 0) { str = filterSpace.slice(0, index1); } else { if (index2 > 0) { str = filterSpace.slice(0, index2); } else { str = filterSpace; } } const newVal = str.split("").map((v) => { if ( [ "$", "(", ")", "*", "+", ".", "[", "]", "?", "/", "^", "{", "}", ].includes(v) ) { return `\\${v}`; } else { return v; } }); const reg = new RegExp(newVal.join("").trim(), "g"); this.marks.forEach((item) => item.clear()); this.marks = []; let index = 0; this.$refs.editor.codemirror?.eachLine((line) => { Array.from(line.text.matchAll(reg)).forEach((item) => { //this.codeEditor 为ready事件返回的编辑器实例 在另一篇文章中有获取方式 const mark = this.$refs.editor.codemirror?.markText( { line: index, ch: item.index }, { line: index, ch: item.index + item[0].length }, { className: "custom-keyword", } ); mark && this.marks.push(mark); }); index++; }); }, changeCodeTheme(theme) { this.cmOptions.theme = theme; this.setAttr(TEMPLATE_CODE_THEME, theme); }, }, }; </script> <style scoped lang="scss"> ::v-deep .CodeMirror { height: inherit !important; border: 1px solid #eee !important; } .isfullscreen { position: absolute; right: 50px; top: 15px; } ::v-deep .CodeMirror-wrap { // pointer-events: none; } ::v-deep .cm-s-neat span.custom-keyword { color: rgb(255, 186, 0) !important; font-weight: 600; } ::v-deep .red-background { background-color: red !important; cursor: pointer; } .el-icon-warning { font-size: 15px; margin-top: -10px; } </style>

Reproduction

.

System Info

win11,Google Chrome,"vue-codemirror": "^4.0.6"

Used Package Manager

npm

Validations

  • Read the the documentation in detail.
  • Check that there isn't already an issue that reports the same bug to avoid creating a duplicate.
  • Check that this is a concrete bug. For Q&A open a GitHub Discussion or join our Discord Chat Server.
  • The provided reproduction is a minimal reproducible example of the bug.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions