You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Redmi Note5的MIUI浏览器10.9.8-g中Vite+Vue3页面空白无DOM问题求助

问题:Redmi Note5的MIUI浏览器10.9.8-g中Vite+Vue3页面空白无DOM元素

在Redmi Note5真机的MIUI浏览器10.9.8-g版本中,使用Vite和Vue3开发的页面打开后完全空白,无DOM元素渲染,同时存在窗口打开相关Bug,相关截图如下:
bug console
bug vite and vue3 complie

以下是组件代码、Vite配置及路由配置:

组件代码

<script setup>
import RechargePhoneItem from '@/components/RechargePhoneItem.vue'
import { useGlobalStore } from '@/stores/global.js'
import { useOrderStore } from '@/stores/order.js'
import { isEmpty } from '@/lib/common.js'
import { checkCustomerV2 } from '@/api'
import { onMounted, ref, watch } from 'vue'
import router from '@/router'

const global = useGlobalStore()
const order = useOrderStore()

const dataUser = ref(null)

async function getUserInformation() {
  try {
    if (import.meta.env.MODE !== 'development') {
      global.showLoading()
      const data = await window.sdk.getUserInfo()
      const { id, phone } = data
      const {statusCode, data: dataRes} = await checkCustomerV2({
        phoneNumber: phone,
        fptplayId: id,
        customer_name: "",
        token: ""
      })

      if(statusCode === 200) {
        global.setUserInfo({
          ...data,
          phone: dataRes?.phone_number.trim(),
          id: dataRes?.uid
        })

        dataUser.value = {
          ...data,
          phone: dataRes?.phone_number.trim(),
          id: dataRes?.uid,
        }
        global.hideLoading()
      }
    } else {
      dataUser.value = {
        phone: '0968790025',
        id: '343'
      }
      global.setUserInfo(dataUser.value)
    }
  } catch (error) {
    global.hideLoading()
    if(error.code === 100) return
    order.setDataTransaction({message: error.message})
    router.push('/card/error-order')
    console.log(error);
  }
}

function handleEventKey(e) {
  if (import.meta.env.MODE !== 'development' && e.keyCode === window.sdk.keys.backspace && router?.currentRoute?.value?.name === 'RechargePhone' && !global.isModal) {
    window.sdk.destroy()
    return
  } else {
    global.showModal(false)
    return
  }
}

watch(
  () => global.userInfo,
  (val, oldVal) => {
    dataUser.value = val
    global.setUserInfo(val)
  },
  { deep: true }
)

onMounted(() => {
  if (!window.sdk) alert('close')
  if (!dataUser.value || isEmpty(dataUser.value)) getUserInformation()
  global.setService('Nạp tiền điện thoại')
  document.addEventListener("keydown", handleEventKey)
})
</script>

<template>
  <RechargePhoneItem v-if="dataUser" :dataUser="dataUser" />
</template>
<style lang="scss"></style>

Vite配置

import { fileURLToPath, URL } from 'node:url'

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueJsx from '@vitejs/plugin-vue-jsx'

// https://vitejs.dev/config/
process.env.BROWSER = "chrome"
export default defineConfig({
  plugins: [
    vue(),
    vueJsx(),
  ],
  resolve: {
    alias: {
      '@': fileURLToPath(new URL('./src', import.meta.url))
    }
  }
})

路由配置

import { createRouter, createWebHistory } from 'vue-router'
import HomeView from '../views/HomeView.vue'

const router = createRouter({
  history: createWebHistory(import.meta.env.BASE_URL),
  routes: [
    {
      path: '/',
      name: 'home',
      component: HomeView
    },
    {
      path: '/card/nap-tien-dien-thoai',
      name: 'RechargePhone',
      // route level code-splitting
      // this generates a separate chunk (About.[hash].js) for this route
      // which is lazy-loaded when the route is visited.
      component: () => import('@/views/RechargePhone.vue')
    },
    {
      path: '/card/history-transaction',
      name: 'HistoryTransaction',
      // route level code-splitting
      // this generates a separate chunk (About.[hash].js) for this route
      // which is lazy-loaded when the route is visited.
      component: () => import('@/views/HistoryTransaction.vue')
    },
    {
      path: '/card/order-confirm',
      name: 'DetailTransaction',
      // route level code-splitting
      // this generates a separate chunk (About.[hash].js) for this route
      // which is lazy-loaded when the route is visited.
      component: () => import('@/views/DetailTransaction.vue')
    },
    {
      path: '/card/payment-methods',
      name: 'PaymentMethods',
      // route level code-splitting
      // this generates a separate chunk (About.[hash].js) for this route
      // which is lazy-loaded when the route is visited.
      component: () => import('@/views/PaymentMethods.vue')
    },
    {
      path: '/card/payment-manages',
      name: 'PaymentManages',
      // route level code-splitting
      // this generates a separate chunk (About.[hash].js) for this route
      // which is lazy-loaded when the route is visited.
      component: () => import('@/views/PaymentManages.vue')
    },
    {
      path: '/card/success',
      name: 'SuccessOrder',
      // route level code-splitting
      // this generates a separate chunk (About.[hash].js) for this route
      // which is lazy-loaded when the route is visited.
      component: () => import('@/views/SuccessOrder.vue')
    },
    {
      path: '/card/error-order',
      name: 'ErrorOrder',
      // route level code-splitting
      // this generates a separate chunk (About.[hash].js) for this route
      // which is lazy-loaded when the route is visited.
      component: () => import('@/views/ErrorOrder.vue')
    },
    {
      path: '/card/pending-order',
      name: 'PendingOrder',
      // route level code-splitting
      // this generates a separate chunk (About.[hash].js) for this route
      // which is lazy-loaded when the route is visited.
      component: () => import('@/views/PendingOrder.vue')
    },
    {
      path: '/card/error-network',
      name: 'ErrorPage',
      // route level code-splitting
      // this generates a separate chunk (About.[hash].js) for this route
      // which is lazy-loaded when the route is visited.
      component: () => import('@/views/ErrorPage.vue')
    },
    {
      path: '/card/support',
      name: 'Support',
      // route level code-splitting
      // this generates a separate chunk (About.[hash].js) for this route
      // which is lazy-loaded when the route is visited.
      component: () => import('@/views/Support.vue')
    },
    {
      path: '/card/credit-card',
      name: 'CreditCard',
      // route level code-splitting
      // this generates a separate chunk (About.[hash].js) for this route
      // which is lazy-loaded when the route is visited.
      component: () => import('@/views/CreditCard.vue')
    },
    {
      path: '/card/receiver',
      name: 'ReceiverCard',
      // route level code-splitting
      // this generates a separate chunk (About.[hash].js) for this route
      // which is lazy-loaded when the route is visited.
      component: () => import('@/views/ReceiverCard.vue')
    },
    {
      path: '/card/check-transaction',
      name: 'CheckTransaction',
      // route level code-splitting
      // this generates a separate chunk (About.[hash].js) for this route
      // which is lazy-loaded when the route is visited.
      component: () => import('@/views/CheckTransaction.vue')
    }
  ]
})

export default router

期望:页面能正常渲染DOM元素,恢复正常显示。


解决建议

1. 适配旧浏览器内核

MIUI浏览器10.9.8-g基于老旧Chromium内核,对ES6+语法支持有限,修改Vite配置降低构建目标:

export default defineConfig({
  // ...原有配置
  build: {
    target: ['es2015', 'chrome60', 'android6'] // 适配旧安卓浏览器
  },
  optimizeDeps: {
    esbuildOptions: {
      target: 'es2015'
    }
  }
})

2. 更换路由模式

createWebHistory依赖HTML5 History API,旧浏览器可能不兼容,换成哈希模式:

import { createRouter, createHashHistory } from 'vue-router'

const router = createRouter({
  history: createHashHistory(import.meta.env.BASE_URL),
  // ...路由配置
})

3. 修复组件潜在问题

  • 模板添加兜底内容,避免dataUser为空时完全空白:
<template>
  <RechargePhoneItem v-if="dataUser" :dataUser="dataUser" />
  <div v-else>加载中...</div>
</template>
  • 移除watch中的循环更新逻辑,避免无限触发状态更新:
watch(
  () => global.userInfo,
  (val) => {
    dataUser.value = val
    // 移除 global.setUserInfo(val) 这行代码
  },
  { deep: true }
)

4. 调试错误根源

在关键位置添加日志,确认代码执行状态:

  • 在onMounted开头添加console.log('组件已挂载'),检查组件是否正常初始化
  • 扩展getUserInformation的catch逻辑,打印完整错误信息,确认是否是SDK或接口请求失败导致dataUser未赋值

5. 确保SDK提前加载

在入口文件(如main.js)中等待SDK加载完成后再初始化Vue:

// main.js
function initApp() {
  createApp(App)
    .use(router)
    .use(pinia) // 若使用Pinia状态管理
    .mount('#app')
}

if (window.sdk) {
  initApp()
} else {
  // 监听SDK加载完成事件(需根据SDK文档调整)
  window.addEventListener('sdkReady', initApp)
}

内容的提问来源于stack exchange,提问作者Sang Phan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 04:18:11