fix(hover-nav): 修复H5端语言切换时导航跟随页面位移的问题
1. 将H5端的hover-nav组件通过Teleport方式挂载到document.body,避开页面transform的影响 2. 同步store中的主题色变量到组件根元素样式,修复样式继承失效问题 3. 在组件销毁前将DOM元素移回原父节点避免内存泄漏 4. 简化当前语言显示逻辑,统一展示当前选中语言的短码
This commit is contained in:
@@ -221,32 +221,12 @@ export default {
|
||||
const info = this.$store && this.$store.state ? (this.$store.state.shopInfo || this.shopInfo) : this.shopInfo;
|
||||
return !!(info && info.ischina) && Array.isArray(this.langList) && this.langList.length >= 2;
|
||||
},
|
||||
// 按钮上显示的文案:
|
||||
// - ≥3 种语言(选择器模式):展示"当前选中语言"的短码(选择器里有 ✓ 标识)
|
||||
// - =2 种语言(原循环模式):展示"下一个要切到的语言"的短码(原 hover-nav 行为)
|
||||
// 按钮上显示的文案:始终展示当前选中语言的短码
|
||||
// 短码来源:initLanguage 已用合并后的 langDisplayMap 填充到 langList[i].name,
|
||||
// 优先用后端 langDisplayNames,否则用前端 LANG_DISPLAY_NAMES
|
||||
currentLangDisplayName() {
|
||||
const list = this.langList;
|
||||
if (!Array.isArray(list) || list.length === 0) return '';
|
||||
const len = list.length;
|
||||
|
||||
// ≥3 种语言:展示当前
|
||||
if (len >= 3) {
|
||||
const currentItem = list[this.currentLangIndex];
|
||||
if (!currentItem) return '';
|
||||
return currentItem.name || getLangShortCode(currentItem.value, this.langDisplayMap);
|
||||
}
|
||||
|
||||
// =2 种语言:展示下一个(原逻辑)
|
||||
if (len === 2) {
|
||||
const nextIndex = (this.currentLangIndex + 1) % len;
|
||||
const nextItem = list[nextIndex];
|
||||
if (!nextItem) return '';
|
||||
return nextItem.name || getLangShortCode(nextItem.value, this.langDisplayMap);
|
||||
}
|
||||
|
||||
// =1 种语言(理论不会显示按钮,但兜底):展示当前
|
||||
const currentItem = list[this.currentLangIndex];
|
||||
if (!currentItem) return '';
|
||||
return currentItem.name || getLangShortCode(currentItem.value, this.langDisplayMap);
|
||||
@@ -462,6 +442,56 @@ export default {
|
||||
// #ifdef H5
|
||||
this.readLayoutVars();
|
||||
// #endif
|
||||
|
||||
// ============================================================
|
||||
// H5 下把 hover-nav 从页面 DOM 树搬到 document.body(Teleport)
|
||||
// ------------------------------------------------------------
|
||||
// 问题: 切换语言时 $langConfig.change() 内部调用 uni.reLaunch(),
|
||||
// H5 的 reLaunch 会触发页面过渡动画(给页面容器加 transform)。
|
||||
// CSS 规范: position: fixed 在 transform 父级下会失效,
|
||||
// 变成相对于被 transform 的父级定位,导致 hover-nav 跟着
|
||||
// 页面过渡一起"上移-下移"。
|
||||
//
|
||||
// 解决: 在 mounted() 中把 this.$el 搬到 document.body 下。
|
||||
// 这样 hover-nav 不再是页面组件的子元素,页面过渡的 transform
|
||||
// 完全不影响它。position: fixed 相对于 body(viewport) 正常工作。
|
||||
//
|
||||
// 副作用: 搬家后,页面根元素上的 CSS 变量(themeColor,如
|
||||
// --hover-nav-bg-color)不再通过继承传递给 hover-nav,
|
||||
// 因为 body 不在页面的 DOM 子树里。
|
||||
// 修复: 把 $store.state.themeColor 同步到 this.$el 的 inline style,
|
||||
// 让 hover-nav 自己持有这些 CSS 变量,不再依赖页面继承。
|
||||
//
|
||||
// 注意: this.$el 是 Vue 组件的根元素(模板最外层的 <view>),
|
||||
// 搬走它后 Vue 的响应式、事件、生命周期**完全不受影响**,
|
||||
// 因为 Vue 的虚拟 DOM 与真实 DOM 位置解耦。
|
||||
// 这是 Vue 2 的合法模式,等同于 Vue 3 的 <Teleport to="body">。
|
||||
// ============================================================
|
||||
// #ifdef H5
|
||||
if (typeof document !== 'undefined' && document.body && this.$el) {
|
||||
this._origParent = this.$el.parentNode;
|
||||
document.body.appendChild(this.$el);
|
||||
|
||||
// 搬家后,把页面根元素上的 CSS 变量同步到 hover-nav 自己身上
|
||||
// 主题系统把 themeColor 挂到页面根元素(如 index.vue 的 <view :style="themeColor">),
|
||||
// 搬家后 hover-nav 不在页面子树里,继承不到这些变量。
|
||||
// 这里直接从 store 读 themeColor 写到 this.$el 的 style 上,
|
||||
// 让 .btn-item .common-bg 能正常读到 --hover-nav-bg-color 等变量。
|
||||
const tc = this.$store && this.$store.state && this.$store.state.themeColor;
|
||||
if (tc && this.$el.style) {
|
||||
this.$el.style.cssText = (this.$el.style.cssText || '') + ';' + tc;
|
||||
}
|
||||
}
|
||||
// #endif
|
||||
},
|
||||
beforeDestroy() {
|
||||
// H5 Teleport 还原:把元素从 body 移回原父节点,避免内存泄漏
|
||||
// #ifdef H5
|
||||
if (this._origParent && this.$el && this.$el.parentNode === document.body) {
|
||||
this._origParent.appendChild(this.$el);
|
||||
this._origParent = null;
|
||||
}
|
||||
// #endif
|
||||
},
|
||||
methods: {
|
||||
// #ifdef H5
|
||||
|
||||
Reference in New Issue
Block a user