问题描述
我在后端使用 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>
页面本身看起来像这样 -
现在,当我单击“翻译”按钮时 - 我与翻译 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 (将#修改为@)