当前位置:   article > 正文

解决Vue2x CodeMirror5x 编辑器子组件值显示还是旧值问题_codemirror5 vue

codemirror5 vue

一、业务需求

最近项目上有个需求是:开发一个简洁版的在线sql编辑器,其中一个要实现的功能是:当选中页面中一段sql语句,进行脚本转换,在弹窗里面也要显示选中的sql语句,并且可编辑,同时也要动态显示行号。

最终实现的效果如图所示:

二、思路及功能实现

本项目使用CodeMirror5x版本,因为用到编辑器的地方很多,所以我封装了一个CodeMirror编辑器组件,在需要引用的地方引入编辑器子组件就可以了。

要实现上述需求,我的思路是:在弹窗和页面中都引入了编辑器子组件。当选中页面中的编辑器子组件里的一段文本时、触发CodeMirror的cursorActivity事件,通过此事件把选中的代码、传入弹窗里的编辑器子组件v-model绑定的值,这样就会与之对应。编辑时如果想要获取实时代码、可通过CodeMirror的input事件给v-model绑定的值赋值。

页面中引入编辑器子组件如下所示:

  1. <codemirror-editor
  2. ref="myCm"
  3. :mode="cmMode"
  4. @input="onEditorInput"
  5. @selectRange="handleSelectChange">
  6. </codemirror-editor>

弹窗里引入编辑器子组件如下所示:

  1. <FormDialog
  2. title="脚本转换"
  3. :dialogFlag.sync="showReplaceModal"
  4. width="50%"
  5. @cancel="replaceCancel">
  6. <div class="formDialog" slot="content">
  7. <el-form class="translateScriptForm">
  8. <el-form-item label="选中的脚本:" class="selectedScriptItem" >
  9. <codemirror-editor ref="replaceCodemirrorCm" v-model="selectedText" @input="onSelectedInput"></codemirror-editor>
  10. </el-form-item>
  11. <el-form-item class="translateBtnTextItem">
  12. <el-button type="text" @click="handleTranslate">转换</el-button>
  13. </el-form-item>
  14. <el-form-item label="脚本转换结果:" class="translateResultItem">
  15. <el-input type="textarea" v-model="replacedText" readonly class="replaceTextarea"></el-input>
  16. </el-form-item>
  17. </el-form>
  18. </div>
  19. <div slot="footer" class="dataDialog-footer">
  20. <el-button class="confirmBtn " v-show="isFature" type="primary" @click="replaceConfirm">替换</el-button>
  21. <el-button class="confirmBtn singleSelectBtn" @click="replaceCancel">关闭</el-button>
  22. </div>
  23. </FormDialog>

 三、问题描述

需求是实现了,但是遇到一个问题:当我选中一段sql语句时,弹窗里初次显示的值是选中的,但是当我再次选中时,弹窗里的子组件值显示的还是上次选中的值。

四、原因分析

经过排查,发现弹窗里的子组件值改变了,视图没变化,所以需要刷新子组件视图,更新dom

五、解决方案

首先我想到了Vue.nextTick()回调函数

(1)监听编辑器子组件的值变化,使用Vue的nextTick异步更新dom

我以为子组件可以刷新视图了,结果还是没有

emma~~

突然想到选中的代码要在弹窗中相对应的显示,这是一个实时更新的过程,异步更新是不起作用的,soga

然后我就想到了第二种方案

(2)Vue有个特殊的attribute key,key的作用是:高效更新虚拟dom,可以强制替换元素/组件而不是重复的使用它。key值变化之后,会自动重新渲染组件。

于是我在弹窗编辑器子组件里加个key属性,key属性的值可以是字符串、时间戳、布尔值等,这里我设置的是时间戳timer。然后我在弹窗出现事件里给timer赋值,在弹窗关闭事件里给timer置空。这样问题就解决了,每次选中一段代码,弹窗中就实时显示选中的代码了。

  1. <codemirror-editor ref="replaceCodemirrorCm" :key="timer" v-model="selectedText" @input="onSelectedInput">
  2. </codemirror-editor>
  1. // 脚本转换按钮事件
  2. handleCodeTranslate(){
  3. this.showReplaceModal = true;
  4. //根据时间戳标识,刷新子组件
  5. this.timer = new Date().getTime();
  6. },
  1. // 脚本转换弹窗取消事件
  2. replaceCancel(){
  3. // 清空脚本转换弹窗里的数据
  4. this.selectedText = '';
  5. this.replacedText = '';
  6. this.timer = null;
  7. // 去除页面上编辑器选中的标记
  8. let editor = this.variableEditor;
  9. // 设置光标位置,取消原来的选中状态
  10. editor.setCursor({line:0,ch:0})
  11. // 关闭弹窗
  12. this.showReplaceModal = false;
  13. },

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/710247
推荐阅读
相关标签
  

闽ICP备14008679号