vue 에서 code Mirror를 쓰는 방법과

더나아가 MaxLength를 설정하는 방법을 알아보좌!

 

 

1. Code mirror 설치

npm install vue-codemirror --save

 그러면 package.json에 codemirror가 추가된걸 확인 할 수 있다.

 

2. main.js 에 선언

import Codemirror  from 'vue-codemirror';

Vue.use(Codemirror);

 

3. code mirror 컴포넌트 사용

<codemirror v-model="query" :options="options" ref="codeMirror" />

v-model에는 codemirror에 입력되는 값을 변수 선언한 뒤 넣어주고

다양한 모드와 옵션이 있는데 그건 부모 컴포넌트에서 options 로 선언해주고 props로 내려주면된다.

 

나같은 경우에는 query를 입력하는 창이라 관련되어서 옵션을 data에 선언해 주었다.

 

예)

                options: {
                    tabSize: 4,
                    styleActiveLine: true,
                    mode: 'text/x-sql',
                    lineNumbers: true,
                    line: true,
                    lineWrapping: true,
                    theme: 'default'
                },

 

더 다양한 옵션은 다음을 참고해보자

https://github.com/surmon-china/vue-codemirror#readme

 

GitHub - surmon-china/vue-codemirror: ⌨️ @codemirror component for @vuejs

⌨️ @codemirror component for @vuejs. Contribute to surmon-china/vue-codemirror development by creating an account on GitHub.

github.com

 

4. max Length 설정하기

options에 따로 max Length 관련 지원이 없어서 직접 구현하였다.

 

먼저 기존 options에 maxLength라고 선언해준다.

                options: {
                    tabSize: 4,
                    styleActiveLine: true,
                    mode: 'text/x-sql',
                    lineNumbers: true,
                    line: true,
                    lineWrapping: true,
                    theme: 'default',
                    maxLength: 4000,
                },

 

그 뒤 , 다음 링크를 참고하여 구현 하였다.

https://github.com/codemirror/CodeMirror/issues/821

 

MaxLength attribute · Issue #821 · codemirror/CodeMirror

Is there a way to set a MaxLength number of characters allowed?

github.com

 

 

codemirror 소스를 보니 모든 event가 발생하면 emit 해주고 있었다.

 

        const allEvents = [
          'scroll',
          'changes',
          'beforeChange',
          'cursorActivity',
          'keyHandled',
          'inputRead',
          'electricInput',
          'beforeSelectionChange',
          'viewportChange',
          'swapDoc',
          'gutterClick',
          'gutterContextMenu',
          'focus',
          'blur',
          'refresh',
          'optionChange',
          'scrollCursorIntoView',
          'update'
        ]
        .concat(this.events)
        .concat(this.globalEvents)
        .filter(e => (!tmpEvents[e] && (tmpEvents[e] = true)))
        .forEach(event => {
          // 循环事件,并兼容 run-time 事件命名
          this.cminstance.on(event, (...args) => {
            // console.log('当有事件触发了', event, args)
            this.$emit(event, ...args) // EMIT !!!!
            const lowerCaseEvent = event.replace(/([A-Z])/g, '-$1').toLowerCase()
            if (lowerCaseEvent !== event) {
              this.$emit(lowerCaseEvent, ...args)
            }
          })
        })

 

그래서 부모 컴포넌트에서 codeMirror를 사용하는쪽에서 emit 하는 function을 받아주었다.

<codemirror v-model="query" :options="options" ref="codeMirror" @beforeChange="enforceMaxLength" />

 그리고 다음과 같이 더이상 입력되지 않도록 function 을 선언해주었다. 

            enforceMaxLength(cm, change) {
                let maxLength = cm.getOption('maxLength');
                if (maxLength) {
                    let str = change.text.join('\n');
                    let delta = str.length - (cm.indexFromPos(change.to) - cm.indexFromPos(change.from));
                    this.cmLength = cm.getValue().length + delta;
                    if (this.cmLength > maxLength) {
                        this.cmLength = maxLength;
                    }
                    delta = cm.getValue().length + delta - maxLength;
                    if (delta >= 0) {
                        str = str.substr(0, str.length - delta);
                        change.update(change.from, change.to, str.split('\n'));
                    }
                }
                return true;
            },

 

그리고 현재 length를 세어주기 위해 cmLength를 선언해주고 length를 넣어주었다. 

 

+ Recent posts