• 在Vue中使用CodeMirror 格式显示错误 行数错乱 & 代码隐藏


    项目需要在线展示和编辑Json文件,所以需要找一个代码编辑器,因为我们的项目直接使用的 vueAdmin-template 这个模板,json编辑器也是直接从 vue-element-admin 项目扒下来的……

    遇到问题

    第一个问题,一个页面有多个tab页,而json显示不在第一个tab页中,那么跳转到页面再点击json所在tab页……

    嗯……默认显示不出来……奇怪的事情是,当你点击一下,数据就出来了……

    第二个问题

    行数显示错位……当行数增加为10行时即变为正常……

    分析

    怀疑是由于当页面第一次渲染时,编辑器没有能正确的计算宽高等展示属性,当点击或者行数变化时触发了刷新所以显示变为正常。

    所以找到 codemirror 的刷新函数,当 tab 切换的时候,手动触发刷新即可。

    解决方案

    1、手动刷新

    在组件中新增一个函数 

    methods: {
        refresh() {
            this.jsonEditor && this.jsonEditor.refresh();
        }
    },

    需要刷新时去触发该函数。

    this.$nextTick(() => {
        this.$refs.jsonEditor.refresh();
    });

    2、增加配置项  autoRefresh: true 

    但是亲测这样只能触发一次自动更新,如果还是遇到问题的话还是要考虑手动刷新。

    完整代码(代码里同时使用了两种解决方案,全部注释掉可以复现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>

    其他:

    注意所有用到的 theme,addon,mode 都需要单独引入,引入之后配置才会生效

    codemirror 文档 https://codemirror.net/doc/manual.html 

    最后放一下我自己在项目中的配置

    <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>
  • 相关阅读:
    BestCoder Round #32
    USACO Runaround Numbers
    USACO Subset Sums
    USACO Sorting a Three-Valued Sequence
    USACO Ordered Fractions
    USACO 2.1 The Castle
    Codeforces Round #252 (Div. 2)
    Codeforces Round #292 (Div. 2)
    BZOJ 1604: [Usaco2008 Open]Cow Neighborhoods 奶牛的邻居
    BZOJ 1603: [Usaco2008 Oct]打谷机
  • 原文地址:https://www.cnblogs.com/wenruo/p/8274958.html
Copyright © 2020-2023  润新知