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

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

文章转载:https://www.cnblogs.com/wenruo/p/8274958.html

遇到问题
第一个问题

一个页面有多个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>
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue 使用 CodeMirror 可以通过两种方式:使用官方的 Vue 组件或者手动在 Vue 创建 CodeMirror 实例。 无论哪种方式,都可以通过 CodeMirror 提供的 `autoFormatRange` 函数对文本进行格式化。下面以使用官方的 Vue 组件为例来说明如何在 Vue 使用 CodeMirror格式代码。 首先,在 Vue 项目安装 CodeMirrorCodeMirrorVue 组件: ``` npm install codemirror vue-codemirror --save ``` 然后,在 Vue 注册 CodeMirror 组件: ```javascript import Vue from 'vue' import VueCodemirror from 'vue-codemirror' import 'codemirror/lib/codemirror.css' // 引入 CodeMirror 样式文件 import 'codemirror/theme/material.css' // 引入 CodeMirror 主题文件 import 'codemirror/mode/javascript/javascript.js' // 引入 JavaScript 语法模式文件 Vue.use(VueCodemirror) ``` 在组件使用 CodeMirror: ```html <template> <div> <codemirror v-model="code" :options="options"></codemirror> </div> </template> <script> export default { data () { return { code: '', options: { tabSize: 2, // Tab 缩进大小为 2 mode: 'javascript', // 指定语言为 JavaScript theme: 'material' // 指定主题为 Material } } }, methods: { format () { const editor = this.$refs.myCodeMirror.getCodeMirror() const from = editor.getCursor(true) const to = editor.getCursor(false) editor.autoFormatRange(from, to) } } } </script> ``` 以上代码,`options` 是 CodeMirror 的配置项,`format` 方法调用了 `autoFormatRange` 函数对文本进行格式化。需要注意的是,需要通过 `this.$refs.myCodeMirror.getCodeMirror()` 获取 CodeMirror 实例才能调用 `autoFormatRange` 函数。 当然,以上只是一个简单的示例,实际使用可能需要根据具体需求进行调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值