Use CodeMirror format in Vue to display wrong line number & code behind

The project needs to display and edit Json files online, so we need to find a code editor, because our project directly uses the vueAdmin-template template, and the json editor is also directly picked up from the vue-element-admin project...

Article reprinted: https://www.cnblogs.com/wenruo/p/8274958.html

Encounter problems

first question

A page has multiple tab pages, and the json display is not in the first tab page, then jump to the page and click on the tab page where the json is located...um...the default is not displayed...the strange thing is that
when you click , the data came out...

second question

The line number display is misaligned...it becomes normal when the line number increases to 10 lines...

analyze

It is suspected that when the page is rendered for the first time, the editor cannot correctly calculate the display properties such as width and height, and when the click or the number of rows changes, a refresh is triggered so the display becomes normal.

So find the refresh function of codemirror, when the tab is switched, manually trigger the refresh.

solution

1. Manual refresh

Add a function to the component

methods: {
    
    
    refresh() {
    
    
        this.jsonEditor && this.jsonEditor.refresh();
    }
},
需要刷新时去触发该函数。

this.$nextTick(() => {
    
    
    this.$refs.jsonEditor.refresh();
});
2. Add configuration item autoRefresh: true

However, the pro-test can only trigger an automatic update in this way. If you still encounter problems, you should consider manual refresh.

Complete code (two solutions are used in the code at the same time, all commented out can reproduce the bug):

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>test vue json editor</title>
  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.32.0/codemirror.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jsonlint/1.6.0/jsonlint.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.48.4/addon/lint/lint.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.48.4/addon/lint/json-lint.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.48.4/mode/javascript/javascript.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.48.4/addon/display/autorefresh.min.js"></script>
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.48.4/theme/darcula.min.css">
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.48.4/addon/lint/lint.min.css">
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.32.0/codemirror.min.css" />
</head>
<body>
<div id="app">
  {
   
   { title }}
  <button @click="handleVisibleChange">显示/隐藏</button>
  <div v-show="show">
    <json-editor ref="jsonEditor" v-model="jsonData"></json-editor>
    <button @click="handleReset">重置</button>
    <button @click="handleSave">保存</button>
  </div>
</div>

<script>
  // 注册编辑器组件
  Vue.component('json-editor', {
      
      
    template: `<div class="json-editor"><textarea ref="textarea"></textarea></div>`,
    data() {
      
      
      return {
      
      
        jsonEditor: null
      }
    },
    props: {
      
      
      value: String,
      input: Function
    },
    watch: {
      
      
      // 监听 value 的变化
      value(value) {
      
      
        const editorValue = this.jsonEditor.getValue();
        if (value !== editorValue) {
      
      
          this.jsonEditor.setValue(JSON.stringify(JSON.parse(value), null, 2));
        }
      }
    },
    mounted() {
      
      
      this.jsonEditor = CodeMirror.fromTextArea(this.$refs.textarea, {
      
      
        lineNumbers: true,
        mode: 'application/json',
        gutters: ['CodeMirror-lint-markers'],
        theme: 'darcula',
        lint: true,
        autoRefresh: true // 自动触发刷新
      });
      // 将json文件格式化显示
      this.jsonEditor.setValue(JSON.stringify(JSON.parse(this.value), null, 2));
      // 当输入框内容发生变化 更新value值
      this.jsonEditor.on('change', cm => {
      
      
        this.handleInput(cm);
        this.$emit('changed', cm.getValue());
        this.$emit('input', cm.getValue());
      });
    },
    methods: {
      
      
      getValue() {
      
      
        return this.jsonEditor.getValue()
      },
      handleInput(e) {
      
      
        if (this.changeFn) {
      
      
          this.changeFn(e.getValue())
        }
      },
      refresh() {
      
      
        /*
         * refresh: Fires when the editor is refreshed or resized.
         *          Mostly useful to invalidate cached values that depend on the editor or character size.
         */
        this.jsonEditor && this.jsonEditor.refresh();
      }
    }
  });

  var app = new Vue({
      
      
    el: '#app',
    data: {
      
      
      title: 'JSON 编辑器',
      jsonData: '{"key":"value"}',
      show: false
    },
    methods: {
      
      
      handleReset() {
      
      
        this.jsonData = '{"key":"value"}';
      },
      handleSave() {
      
      
        alert(this.jsonData);
      },
      // 当切换视图为显示json编辑器时 手动刷新
      handleVisibleChange() {
      
      
        if (this.show = !this.show) {
      
      
          this.$nextTick(() => {
      
      
            this.$refs.jsonEditor.refresh(); // 手动触发刷新
          });
        }
      }
    }
  });
</script>
</body>
</html>

Others:
Note that all used themes, addons, and modes need to be imported separately, and the configuration will take effect only after importing

codemirror documentation https://codemirror.net/doc/manual.html

Finally, put my own configuration in the project

<template>
    <div class="json-editor">
        <textarea ref="textarea"></textarea>
    </div>
</template>
<script>
    import CodeMirror from 'codemirror';
    import 'script-loader!jsonlint';
    import 'codemirror/addon/lint/lint.css';
    import 'codemirror/addon/lint/lint.js';
    import 'codemirror/addon/lint/json-lint';
    import 'codemirror/mode/javascript/javascript';
    import 'codemirror/addon/display/autorefresh';
    import 'codemirror/lib/codemirror.css';
    import 'codemirror/addon/edit/matchbrackets';
    import 'codemirror/addon/fold/foldcode.js';
    import 'codemirror/addon/fold/foldgutter.js';
    import 'codemirror/addon/fold/brace-fold.js';
    import 'codemirror/addon/fold/foldgutter.css';

    export default {
      
      
        name: 'index',
        data() {
      
      
            return {
      
      
                jsonEditor: null
            }
        },
        props: {
      
      
            value: String,
            input: Function
        },
        watch: {
      
      
            // 监听 value 的变化
            value(value) {
      
      
                const editorValue = this.jsonEditor.getValue();
                if (value !== editorValue) {
      
      
                    this.setValue(value);
                }
            }
        },
        mounted() {
      
      
            this.jsonEditor = CodeMirror.fromTextArea(this.$refs.textarea, {
      
      
                lineNumbers: true,
                mode: 'application/json',
                foldGutter: true,
                gutters: ['CodeMirror-lint-markers', 'CodeMirror-foldgutter'],
                lint: true,
                autoRefresh: true, // 自动触发刷新
                tabSize: 4,
                matchBrackets: true,
                indentUnit: 4
            });
            // 将json文件格式化显示
            this.setValue(this.value);
            // 当输入框内容发生变化 更新value值
            this.jsonEditor.on('change', cm => {
      
      
                this.handleInput(cm);
                this.$emit('changed', cm.getValue());
                this.$emit('input', cm.getValue());
            });
        },
        methods: {
      
      
            getValue() {
      
      
                return this.jsonEditor.getValue()
            },
            setValue(value) {
      
      
                try {
      
      
                    let newVal = JSON.stringify(JSON.parse(value), null, 4);
                    this.jsonEditor.setValue(newVal);
                } catch (e) {
      
      
                    this.jsonEditor.setValue(value);
                }
            },
            handleInput(e) {
      
      
                if (this.changeFn) {
      
      
                    this.changeFn(e.getValue())
                }
            },
            refresh() {
      
      
                /*
                 * refresh: Fires when the editor is refreshed or resized.
                 *          Mostly useful to invalidate cached values that depend on the editor or character size.
                 */
                this.jsonEditor && this.jsonEditor.refresh();
            },
        }
    }
</script>

<style scoped>

</style>

Guess you like

Origin blog.csdn.net/weixin_52755319/article/details/124825667