zhb il y a 2 jours
Parent
commit
9c1c5869b0
1 fichiers modifiés avec 60 ajouts et 21 suppressions
  1. 60 21
      directives/v-t.js

+ 60 - 21
directives/v-t.js

@@ -2,6 +2,8 @@
 import { watch } from 'vue'
 import { watch } from 'vue'
 import { lang } from '@/composables/config'
 import { lang } from '@/composables/config'
 
 
+const TEXT_NODE_CLASS = 'v-t-node'
+
 /**
 /**
  * 解析绑定值
  * 解析绑定值
  * 支持:'key' 或 ['key', param]
  * 支持:'key' 或 ['key', param]
@@ -16,33 +18,67 @@ const parseBinding = (val) => {
   return { key: val, param: undefined }
   return { key: val, param: undefined }
 }
 }
 
 
+const isFormField = (el) => {
+  const tag = el?.tagName?.toUpperCase?.() || ''
+  return tag === 'INPUT' || tag === 'TEXTAREA'
+}
+
 /**
 /**
- * 更新元素的文本内容
+ * 在宿主内创建独立文本节点,避免直接改 button/view 的 textContent
+ * 导致 Vue patch 时清空子树、click 等事件失效
  */
  */
+const ensureTextNode = (el) => {
+  if (isFormField(el)) return el
+
+  if (el._vTTextEl?.parentNode === el) {
+    return el._vTTextEl
+  }
+
+  if (typeof document === 'undefined') {
+    return el
+  }
+
+  const node = document.createElement('span')
+  node.className = TEXT_NODE_CLASS
+  node.setAttribute('data-v-t', '')
+  node.style.pointerEvents = 'none'
+  el.appendChild(node)
+  el._vTTextEl = node
+  return node
+}
+
 const updateElementText = (el, text) => {
 const updateElementText = (el, text) => {
   if (!el) return
   if (!el) return
-  if (el.tagName === 'INPUT' || el.tagName === 'TEXTAREA') {
-    el.value = text
-  } else if ('textContent' in el) {
-    el.textContent = text
-  } else if ('innerText' in el) {
-    el.innerText = text
+  const target = ensureTextNode(el)
+
+  if (isFormField(target)) {
+    target.value = text
+    return
+  }
+
+  if ('textContent' in target) {
+    target.textContent = text
+  } else if ('innerText' in target) {
+    target.innerText = text
   }
   }
 }
 }
 
 
-/**
- * 获取全局 i18n 实例
- */
 const getI18n = () => {
 const getI18n = () => {
   return typeof globalThis !== 'undefined' && globalThis.__i18n ? globalThis.__i18n : null
   return typeof globalThis !== 'undefined' && globalThis.__i18n ? globalThis.__i18n : null
 }
 }
 
 
+const bindingSignature = (val) => {
+  if (Array.isArray(val)) return JSON.stringify(val)
+  return String(val ?? '')
+}
+
 export default {
 export default {
   mounted(el, binding) {
   mounted(el, binding) {
     const setState = (val) => {
     const setState = (val) => {
       const { key, param } = parseBinding(val)
       const { key, param } = parseBinding(val)
       el._vTKey = key
       el._vTKey = key
       el._vTParam = param
       el._vTParam = param
+      el._vTBindingSig = bindingSignature(val)
     }
     }
 
 
     const update = () => {
     const update = () => {
@@ -50,7 +86,6 @@ export default {
       const key = el._vTKey
       const key = el._vTKey
       const param = el._vTParam
       const param = el._vTParam
 
 
-      // 无 key 时显示 --
       if (!key) {
       if (!key) {
         updateElementText(el, '')
         updateElementText(el, '')
         return
         return
@@ -59,10 +94,7 @@ export default {
       let text = ''
       let text = ''
       if (i18n) {
       if (i18n) {
         const translated = i18n.global.t(key, param)
         const translated = i18n.global.t(key, param)
-        // 如果翻译结果等于 key 本身,说明未找到翻译,显示 --
         text = translated === key ? '' : translated
         text = translated === key ? '' : translated
-      } else {
-        text = ''
       }
       }
 
 
       updateElementText(el, text)
       updateElementText(el, text)
@@ -74,7 +106,6 @@ export default {
     el._vTSetState = setState
     el._vTSetState = setState
     el._vTUpdate = update
     el._vTUpdate = update
 
 
-    // 监听语言变化,更新文本
     el._vTStopWatch = watch(
     el._vTStopWatch = watch(
       () => lang.value,
       () => lang.value,
       () => {
       () => {
@@ -89,6 +120,9 @@ export default {
   },
   },
 
 
   updated(el, binding) {
   updated(el, binding) {
+    const sig = bindingSignature(binding.value)
+    if (sig === el._vTBindingSig) return
+
     if (el._vTSetState) el._vTSetState(binding.value)
     if (el._vTSetState) el._vTSetState(binding.value)
     if (el._vTUpdate) el._vTUpdate()
     if (el._vTUpdate) el._vTUpdate()
   },
   },
@@ -98,9 +132,14 @@ export default {
       el._vTStopWatch()
       el._vTStopWatch()
       delete el._vTStopWatch
       delete el._vTStopWatch
     }
     }
-    if (el._vTUpdate) delete el._vTUpdate
-    if (el._vTSetState) delete el._vTSetState
-    if (el._vTKey) delete el._vTKey
-    if (el._vTParam) delete el._vTParam
-  }
-}
+    if (el._vTTextEl?.parentNode === el) {
+      el.removeChild(el._vTTextEl)
+    }
+    delete el._vTTextEl
+    delete el._vTUpdate
+    delete el._vTSetState
+    delete el._vTKey
+    delete el._vTParam
+    delete el._vTBindingSig
+  },
+}