index.vue 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. <template>
  2. <textarea ref="codeMirrorRef"></textarea>
  3. </template>
  4. <script>
  5. import { ref, onMounted, watch, markRaw, nextTick } from 'vue'
  6. import CodeMirror from 'codemirror'
  7. import 'codemirror/lib/codemirror.css'
  8. import 'codemirror/mode/javascript/javascript'
  9. import 'codemirror/mode/xml/xml'
  10. import 'codemirror/mode/sql/sql'
  11. import 'codemirror/addon/hint/show-hint'
  12. import 'codemirror/addon/hint/sql-hint'
  13. import 'codemirror/addon/hint/show-hint.css'
  14. import 'codemirror/theme/dracula.css'
  15. import 'codemirror/theme/3024-day.css'
  16. export default {
  17. name: 'CipCodeMirror',
  18. inheritAttrs: false,
  19. props: {
  20. modelValue: [String, Object],
  21. readonly: {
  22. type: Boolean,
  23. default: false
  24. },
  25. type: {
  26. type: String,
  27. default: 'json'
  28. },
  29. height: {
  30. type: String,
  31. default: 'auto'
  32. },
  33. theme: { // 主题,需要额外引入
  34. type: String,
  35. default: 'dracula'
  36. }
  37. },
  38. emits: ['update:modelValue'],
  39. setup (props, { emit }) {
  40. const codeMirrorRef = ref()
  41. const codeMirror = ref()
  42. const getCodeMirrorInstance = () => {
  43. const instance = CodeMirror.fromTextArea(codeMirrorRef.value, {
  44. value: formatterValue(props.modelValue),
  45. mode: `text/${props.type === 'json' ? 'javascript' : props.type}`,
  46. theme: props.theme,
  47. indentUnit: 4,
  48. lineNumbers: true,
  49. lineWrapping: false,
  50. readOnly: props.readonly,
  51. singleCursorHeightPerLine: false,
  52. extraKeys: {}
  53. })
  54. instance.setSize(props.width ?? '100%', props.height ?? 'auto')
  55. instance.on('change', (instance, obj) => {
  56. const { origin } = obj
  57. const value = instance.getValue()
  58. codeMirror.value.save()
  59. if (origin !== 'setValue') { // 非setValue导致的更新才emit
  60. emit('update:modelValue', value)
  61. }
  62. })
  63. return instance
  64. }
  65. const formatterValue = (val) => {
  66. if (props.type === 'json' && val) {
  67. let data = val
  68. if (typeof val === 'string') {
  69. data = JSON.parse(data)
  70. }
  71. return JSON.stringify(data, null, 2) ?? ''
  72. } else {
  73. return val
  74. }
  75. }
  76. onMounted(() => {
  77. codeMirror.value = markRaw(getCodeMirrorInstance())
  78. watch(() => props.modelValue, (val, oldVal) => {
  79. const codeMirrorValue = codeMirror.value?.getValue()
  80. if (codeMirrorValue === val) return
  81. console.log(formatterValue(val))
  82. codeMirror.value.setValue(formatterValue(val))
  83. nextTick(() => {
  84. codeMirror.value.refresh()
  85. })
  86. }, {
  87. immediate: true
  88. })
  89. })
  90. return {
  91. codeMirrorRef
  92. }
  93. }
  94. }
  95. </script>