如何禁用 VueJS 观察器?

问题描述

我在后端使用 CoreUI 和 Laravel,并添加了一些翻译功能,让我可以直接翻译 CRUD 中的值。

首先,这是我将在此处尝试描述的行为的超短视频 - https://streamable.com/0ejdyu

我在数据库中有可翻译的模型,它们以 json 表示形式保存翻译,并在前端输出它们,这是 1 个字段的示例 -

    @foreach($locales as $locale)
        <div class="col-md" v-show="shouldShowLangGroup('{{ $locale }}')" v-cloak>
            <div class="form-group row align-items-center" :class="{'has-danger': errors.has('Meta_description_{{ $locale }}'),'has-success': fields.Meta_description_{{ $locale }} && fields.Meta_description_{{ $locale }}.valid }">
                <label for="Meta_description_{{ $locale }}" class="col-md-2 col-form-label text-md-right">{{ trans('admin.article.columns.Meta_description') }}</label>
                <div class="col-md-9" :class="{'col-xl-8': !isFormlocalized }">
                    <input type="text" v-model="form.Meta_description.{{ $locale }}" v-validate="'required'" @input="validate($event)" class="form-control" :class="{'form-control-danger': errors.has('Meta_description_{{ $locale }}'),'form-control-success': fields.Meta_description_{{ $locale }} && fields.Meta_description_{{ $locale }}.valid }" id="Meta_description_{{ $locale }}" name="Meta_description_{{ $locale }}" placeholder="{{ trans('admin.article.columns.Meta_description') }}">
                    <div v-if="errors.has('Meta_description_{{ $locale }}')" class="form-control-Feedback form-text" v-cloak>{{'{{'}} errors.first('Meta_description_{{ $locale }}') }}</div>
                </div>
            </div>

        </div>
    @endforeach
</div>

页面本身看起来像这样 -

enter image description here

现在,当我单击“翻译”按钮时 - 我与翻译 API 进行通信,并在已翻译的文本框中简单地返回结果,使用简单的 jQuery 并在填充表单后附加单击处理程序。这是按钮的代码 -

$(document).ready(function($) {

    //add translate buttons to all fields
    $(".form-edit input[type=text],.form-create input[type=text] ").each(function()  {
        let attr = $(this).attr('id');
        if( typeof(attr) !== typeof undefined && attr !== false)
            if( !(($(this).attr('id')).includes("_en")) )
                $(this).parent().after('<button name="'+$(this).attr('id').substr(0,$(this).attr('id').lastIndexOf("_"))+'" id="translate_btn_'+$(this).attr('id')+'">Translate</button>');
    });
    //add translate buttons to text areas (wysiwygs)
    $("textarea").each(function() {
        let attr = $(this).attr('id');
        if( typeof(attr) !== typeof undefined && attr !== false) {
            if (!(($(this).attr('id')).includes("_en"))) {
                $(this).parent().after('<button name="' + $(this).attr('id').substr(0,$(this).attr('id').lastIndexOf("_")) + '" id="translate_btn_' + $(this).attr('id') + '">Translate</button>');
            }
        }
    });
    //add event listeners the buttons
    $('[id^=translate_btn_]').each(function() {
      $( this ).click(function (e) {
          $.ajaxSetup({
              headers: {
                  'X-CSRF-TOKEN': jQuery('Meta[name="csrf-token"]').attr('content')
              }
          });
          e.preventDefault();
          let source_language = 'en';
          let original_content_field = $(this).attr('name') + '_' + source_language;
          let original_content = $('#'+original_content_field).val();
          let target_language = $(this).attr('id').substr($(this).attr('id').lastIndexOf("_")+1,$(this).attr('id').length);
          var translated_field_name = $(this).attr('name') + '_' + target_language;
          var formData = {
              original_content: original_content,source_language: source_language,target_language: target_language,};
          var type = "POST";
          var ajaxurl = '/get-translation';
          $.ajax({
              type: type,url: ajaxurl,data: formData,dataType: 'json',success: function (data) {
                  let new_field = $('#'+translated_field_name);
                  if(new_field.is("textarea") ) {
                      document.getElementById(translated_field_name).innerHTML = data;
                      original_content_field = '';
                      original_content = '';
                      translated_field_name = '';
                  }
                  else {
                      let translated = $("input[name=" + translated_field_name + "]");
                      let translated_val = translated.val();
                      translated.val(data);
                  }
              },error: function (data) {
                  console.log(data);
                  console.log('error!');
              }
          });
      })
    });
});

当我手动开始在其他文本框之一中键入文本和/或点击“保存”按钮时,问题就开始了,因为后台一个 VueJS 观察器可以将 DOM 设置为“认值”( ?) 状态。遗憾的是,我没有太多的 Vue 经验(我主要是后端开发人员)所以我发现很难跟踪交换本身,但我肯定知道它发生在 Vue 核心的这一部分,也就是 Vue 的核心部分差异算法 -

while (oldStartIdx <= oldEndIdx && newStartIdx <= newEndIdx) {
      if (isUndef(oldStartVnode)) {
        oldStartVnode = oldCh[++oldStartIdx]; // Vnode has been moved left
      } else if (isUndef(oldEndVnode)) {
        oldEndVnode = oldCh[--oldEndIdx];
      } else if (sameVnode(oldStartVnode,newStartVnode)) {
        patchVnode(oldStartVnode,newStartVnode,insertedVnodeQueue,newCh,newStartIdx);
        oldStartVnode = oldCh[++oldStartIdx];
        newStartVnode = newCh[++newStartIdx];
      } else if (sameVnode(oldEndVnode,newEndVnode)) {
        patchVnode(oldEndVnode,newEndVnode,newEndIdx);
        oldEndVnode = oldCh[--oldEndIdx];
        newEndVnode = newCh[--newEndIdx];
      } else if (sameVnode(oldStartVnode,newEndVnode)) { // Vnode moved right
        patchVnode(oldStartVnode,newEndIdx);
        canMove && nodeOps.insertBefore(parentElm,oldStartVnode.elm,nodeOps.nextSibling(oldEndVnode.elm));
        oldStartVnode = oldCh[++oldStartIdx];
        newEndVnode = newCh[--newEndIdx];
      } else if (sameVnode(oldEndVnode,newStartVnode)) { // Vnode moved left
        patchVnode(oldEndVnode,newStartIdx);
        canMove && nodeOps.insertBefore(parentElm,oldEndVnode.elm,oldStartVnode.elm);
        oldEndVnode = oldCh[--oldEndIdx];
        newStartVnode = newCh[++newStartIdx];
      } else {
        if (isUndef(oldKeyToIdx)) { oldKeyToIdx = createKeyToOldIdx(oldCh,oldStartIdx,oldEndIdx); }
        idxInOld = isDef(newStartVnode.key)
          ? oldKeyToIdx[newStartVnode.key]
          : findIdxInOld(newStartVnode,oldCh,oldEndIdx);
        if (isUndef(idxInOld)) { // New element
          createElm(newStartVnode,parentElm,false,newStartIdx);
        } else {
          vnodetoMove = oldCh[idxInOld];
          if (sameVnode(vnodetoMove,newStartVnode)) {
            patchVnode(vnodetoMove,newStartIdx);
            oldCh[idxInOld] = undefined;
            canMove && nodeOps.insertBefore(parentElm,vnodetoMove.elm,oldStartVnode.elm);
          } else {
            // same key but different element. treat as new element
            createElm(newStartVnode,newStartIdx);
          }
        }
        newStartVnode = newCh[++newStartIdx];
      }
    }
    if (oldStartIdx > oldEndIdx) {
      refElm = isUndef(newCh[newEndIdx + 1]) ? null : newCh[newEndIdx + 1].elm;
      addVnodes(parentElm,refElm,newStartIdx,newEndIdx,insertedVnodeQueue);
    } else if (newStartIdx > newEndIdx) {
      removeVnodes(oldCh,oldEndIdx);
    }
  }

我想我不应该简单地使用经典的 jQuery 方法 ($("selector").val(data)) 更新文本框,因为在添加翻译后,Vue 不会保存新状态。

这是我试图描述的行为的超短视频 - https://streamable.com/0ejdyu

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)