概要

提示:通过使用"vue-codemirror": "^4.0.6",实现输入提示,类似于vscode提示效果

效果图:

实现原理

 1.得到光标位置,定义提示内容

    handleShowHint() {
      // 获取输入框实例
      const cmInstance = this.$refs.mySql.codemirror
      // 得到光标
      let cursor = cmInstance.getCursor()
      // 得到行内容
      let cursorLine = cmInstance.getLine(cursor.line)
      // 得到光标位置
      let end = cursor.ch
      this.list = []
      // 得到光标标识
      let token = cmInstance.getTokenAt(cursor)
      this.getListHint(cursorLine, end)
      return {
        list: this.list, // 自定义提示内容
        // ch:选择提示内容替换的开始位置,line: 光标所在行
        from: { ch: token.start, line: cursor.line }, 
        to: { ch: token.end, line: cursor.line }
      }
    },

2.设置分隔符,得到光标与分隔符之间的搜索内容

    getListHint(cursorLine, cursorIndex) {
      let indexList = []
      for (let i = 0; i < cursorIndex; i++) {
        // 获取所有分隔符小于当前光标的位置
        if (this.splitRules.includes(cursorLine[i])) indexList.push(i)
      }
      // 得到当前距离光标最近且小于光标位置的字符位置
      const earlayRightIndex = indexList[indexList.length - 1]
      // 截取光标与最近且位置坐标小于光标的内容
      const str = cursorLine.substring(earlayRightIndex + 1, cursorIndex)
      // 遍历自定义提示数组,得到满足条件的提示内容
      this.hintList.forEach(item => {
        if (item[this.hintLabel].indexOf(str) !== -1 && str) {
          this.list.push(item[this.hintLabel])
        }
      })
    }

核心原理:

获取当前光标与最近分隔符之间的内容

 可以设置多种分隔符,例如:,. _ ( ),空格等

通过截取到的内容来遍历数组获取符合条件的自定义提示 

     this.hintList.forEach(item => {

        if (item[this.hintLabel].indexOf(str) !== -1 && str) {

          this.list.push(item[this.hintLabel])

        }

      })

全部代码

封装好的代码

<template>
  <div class="sqlTemplate">
    <codemirror
      ref="mySql"
      v-model="sql"
      :options="sqlOptions"
    ></codemirror>
  </div>
</template>

<script>
import 'codemirror/lib/codemirror.css'
import 'codemirror/mode/sql/sql.js' // 引入mode
import 'codemirror/theme/solarized.css' // 引入theme
import { codemirror } from 'vue-codemirror'
import 'codemirror/theme/idea.css'
import 'codemirror/mode/shell/shell'
// 代码提示功能 具体语言可以从 codemirror/addon/hint/ 下引入多个
import 'codemirror/addon/hint/show-hint.css'
import 'codemirror/addon/hint/show-hint'
// 高亮行功能
import 'codemirror/addon/selection/active-line'
import 'codemirror/addon/selection/selection-pointer'
// 全屏功能 由于项目复杂,自带的全屏功能一般不好使
import 'codemirror/addon/display/fullscreen.css'
import 'codemirror/addon/display/fullscreen'
export default {
  components: { codemirror },
  props: {
    // 回显code
    code: {
      type: String
    },
    // 自定义提示列表
    hintList: {
      type: Array
    },
    // 自定义提示列表中对应的字段标识
    hintLabel: {
      type: String
    },
    // 字段分隔符,根据字段分隔符做出截取需要提示的字段
    splitRules: {
      type: Array
    },
    // 是否开启输入提示
    isHint: {
      type: Boolean,
      default: false
    }
  },
  data() {
    return {
      sql: '',
      list: [],
      sqlOptions: {
        tabSize: 4,
        lineNumbers: true,
        line: true,
        mode: 'text/x-mssql', // SQL SERVER
        smartIndent: true,
        indentUnit: 4,
        autoRefresh: true,
        theme: 'default',
        lineWrapping: true,
        // 高亮行功能
        styleActiveLine: true,
        hintOptions: {
          completeSingle: false,
          hint: this.handleShowHint
        }
      }
    }
  },
  mounted() {
    this.sql = this.code
    // 代码提示功能 当用户有输入时,显示提示信息
    this.$refs.mySql.codemirror.on('inputRead', (mySql) => {
      if (!this.isHint) return
      mySql.showHint()
    })
    // 设置输入区域高度
    this.$refs.mySql.codemirror.setSize('auto', 100 + 'px')
    // this.$nextTick(() => {
    //   window.addEventListener('resize', () => {
    //     // 监听浏览器窗口大小改变
    //     // 浏览器变化执行动作
    //     this.$refs.mySql.codemirror.setSize('auto', 100 + 'px')
    //   })
    // })
  },
  methods: {
    handleShowHint() {
      // 获取输入框实例
      const cmInstance = this.$refs.mySql.codemirror
      // 得到光标
      let cursor = cmInstance.getCursor()
      // 得到行内容
      let cursorLine = cmInstance.getLine(cursor.line)
      // 得到光标位置
      let end = cursor.ch
      this.list = []
      // 得到光标标识
      let token = cmInstance.getTokenAt(cursor)
      this.getListHint(cursorLine, end)
      return {
        list: this.list, // 自定义提示内容
      // ch:选择提示内容替换的开始位置,line: 光标所在行
        from: { ch: token.start, line: cursor.line }, 
        to: { ch: token.end, line: cursor.line }
      }
    },
    getListHint(cursorLine, cursorIndex) {
      let indexList = []
      for (let i = 0; i < cursorIndex; i++) {
        // 获取所有分隔符小于当前光标的位置
        if (this.splitRules.includes(cursorLine[i])) indexList.push(i)
      }
      // 得到当前距离光标最近且小于光标位置的字符位置
      const earlayRightIndex = indexList[indexList.length - 1]
      // 截取光标与最近且位置坐标小于光标的内容
      const str = cursorLine.substring(earlayRightIndex + 1, cursorIndex)
      // 遍历自定义提示数组,得到满足条件的提示内容
      this.hintList.forEach(item => {
        if (item[this.hintLabel].indexOf(str) !== -1 && str) {
          this.list.push(item[this.hintLabel])
        }
      })
    }
  }
}
</script>

<style>

</style>

具体使用

<template>
  <div class="databaseModelingOnLogic">
    <span class="mt10 mb10">聚合逻辑:</span>
    <div class="main">
      <sql-template
        ref="cm"
        :hintList="hintList"
        :code="code"
        :hintLabel="label"
        :splitRules="splitRules"
        :isHint="true"
      ></sql-template>
    </div>
  </div>
</template>

<script>
import SqlTemplate from '@/components/page/sql_template'

export default {
  components: {
    SqlTemplate
  },
  data() {
    return {
      code: '',
      source_table: '',
      label: 'name',
      list: [],
      selectData: [],
      splitRules: ['(', ')', '.', ' '],
      hintList: [
        {
          name: 'xiaohong'
        },
        {
          name: 'count'
        },
        {
          name: 'select'
        },
        {
          name: 'from'
        }
      ]
    }
  }
}
</script>

<style lang="scss">
.databaseModelingOnLogic {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
}
.CodeMirror-hints{
  z-index: 3000 !important;
}
</style>

小结

这就是vue-codemirror设置自定义提示功能的全部内容了,欢迎大家讨论。

Logo

前往低代码交流专区

更多推荐