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

文章描述了一种在Vue项目中使用CodeMirror5x版本开发简洁版在线SQL编辑器的方法,特别是如何处理选中文本的同步显示和动态行号。通过cursorActivity事件和Vue的key属性来实现实时更新和组件刷新,解决选中值不更新的问题。
摘要由CSDN通过智能技术生成

一、业务需求

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

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

二、思路及功能实现

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

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

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

<codemirror-editor
        ref="myCm"
        :mode="cmMode"
        @input="onEditorInput"
        @selectRange="handleSelectChange">
</codemirror-editor>

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

 <FormDialog
            title="脚本转换"
            :dialogFlag.sync="showReplaceModal"
            width="50%"
            @cancel="replaceCancel">
            <div class="formDialog" slot="content">
              <el-form class="translateScriptForm">
                  <el-form-item label="选中的脚本:" class="selectedScriptItem" >
                      <codemirror-editor ref="replaceCodemirrorCm"  v-model="selectedText" @input="onSelectedInput"></codemirror-editor>
                  </el-form-item>
                  <el-form-item class="translateBtnTextItem">
                      <el-button type="text" @click="handleTranslate">转换</el-button>
                  </el-form-item>
                  <el-form-item label="脚本转换结果:" class="translateResultItem">
                      <el-input type="textarea" v-model="replacedText" readonly class="replaceTextarea"></el-input>
                  </el-form-item>
              </el-form>   
            </div>
            <div slot="footer" class="dataDialog-footer">
                <el-button class="confirmBtn " v-show="isFature" type="primary" @click="replaceConfirm">替换</el-button>
                <el-button class="confirmBtn singleSelectBtn" @click="replaceCancel">关闭</el-button>
            </div>
  </FormDialog>

 三、问题描述

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

四、原因分析

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

五、解决方案

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

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

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

emma~~

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

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

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

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

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

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值