Vite 4.2 和 TypeScript 5.02 上的 Vue 3 SPA。
点击选择发出 lang.value 并且在父组件 App.vue contentStore 中应该更新内容。在我的 Linux Ubuntu 桌面上完美运行的典型事物。在 Firefox 和 Chrome devtools 中同样完美,当我模拟任何移动设备 - iOS 或 Android 时也是如此。 但是,当部署在 Hostinger 上时,它不会在任何 Android 或 iOS 设备上切换语言。你可以在这里看到https://rybnikov.online.
这是我的 App.vue:
<script setup lang="ts">
import { RouterView } from 'vue-router'
import { useWindowSize } from '@vueuse/core'
import { ref, defineAsyncComponent, onUpdated } from 'vue'
import { useContentStore } from './stores/content'
import socialMedia from './data/social.json'
const contentStore = useContentStore()
const lang = ref(localStorage.getItem('lang') || navigator.language.slice(0, 2))
const social = Object.assign(socialMedia)
const LayoutDesktop = defineAsyncComponent(() => import('@/layouts/LayoutDesktop.vue'))
const LayoutMobile = defineAsyncComponent(() => import('@/layouts/LayoutMobile.vue'))
const NavigationDesktop = defineAsyncComponent(() => import('@/components/NavigationDesktop.vue'))
const NavigationMobile = defineAsyncComponent(() => import('@/components/NavigationMobile.vue'))
const BodyMobile = defineAsyncComponent(() => import('@/components/BodyMobile.vue'))
const FooterMobile = defineAsyncComponent(() => import('@/components/FooterMobile.vue'))
const FooterDesktop = defineAsyncComponent(() => import('@/components/FooterDesktop.vue'))
const { width } = useWindowSize()
const setLang = (newLang: string) => {
lang.value = newLang
localStorage.setItem('lang', lang.value)
contentStore.setContent(lang.value)
}
onUpdated(() => {
contentStore.setContent(lang.value)
contentStore.getContent
})
</script>
<template>
<LayoutMobile v-if="width < 769">
<template #header>
<NavigationMobile @changeLang="setLang" />
</template>
<template #default>
<BodyMobile :content="contentStore.getContent" />
</template>
<template #footer>
<FooterMobile :lang="lang" :social="social" />
</template>
</LayoutMobile>
<LayoutDesktop v-else>
<template #header>
<NavigationDesktop @changeLang="setLang" />
</template>
<template #asideLeft>
<h1></h1>
</template>
<template #default>
<RouterView :content="contentStore.getContent" />
</template>
<template #asideRight>
<h1></h1>
</template>
<template #footer>
<FooterDesktop :lang="lang" :social="social" />
</template>
</LayoutDesktop>
</template>
这是我的 NavigationLanguageSelect.vue
<script setup lang="ts">
import langSelection from '@/data/lang.json'
const emit = defineEmits<{ (e: 'changeLang', lang: string): void }>()
const langs = Object.assign(langSelection)
</script>
<template>
<div>
<select class="p-1 text-sm rounded-lg text-gray-700">
<option
class="block px-4 py-2 hover:bg-gray-100"
v-for="language in langs"
:key="language.text"
@click="emit('changeLang', language.value)"
@select="emit('changeLang', language.value)"
>
{{ language.flag }} {{ language.text }}
</option>
</select>
</div>
</template>
这里是 package.json
{
"name": "oleg",
"version": "0.0.0",
"private": true,
"scripts": {
"dev": "vite",
"build": "run-p type-check build-only",
"preview": "vite preview",
"build-only": "vite build",
"type-check": "vue-tsc --noEmit",
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore",
"format": "prettier --write src/"
},
"dependencies": {
"@vueuse/core": "^9.13.0",
"pinia": "^2.0.32",
"vue": "^3.2.47",
"vue-router": "^4.1.6"
},
"devDependencies": {
"@rushstack/eslint-patch": "^1.2.0",
"@types/node": "^18.14.2",
"@vitejs/plugin-vue": "^4.0.0",
"@vue/eslint-config-prettier": "^7.1.0",
"@vue/eslint-config-typescript": "^11.0.2",
"@vue/tsconfig": "^0.1.3",
"autoprefixer": "^10.4.14",
"eslint": "^8.34.0",
"eslint-plugin-vue": "^9.9.0",
"npm-run-all": "^4.1.5",
"postcss": "^8.4.21",
"prettier": "^2.8.4",
"tailwindcss": "^3.3.0",
"typescript": "^5.0.2",
"vite": "^4.2.0",
"vue-tsc": "^1.2.0"
}
}
请告知上述代码在任何移动设备上失败的性质。
我试过使用 onMounted、onUpdated 钩子、pinia 的 storeToRefs,但看起来 select 元素本身有一些问题。
问题实际上在于我尝试将 < select > 与 Vue v-for 指令一起使用的方式。 V 模型以及很可能类似的运算符在 < option > 标签内不起作用,必须在 < select > 本身内使用。然而,奇怪的是,整个事情都在桌面上运行并且没有抛出任何错误,即使这种情况有据可查。
尽管如此,这是最终代码。希望它能帮助有类似问题的人。
import { ref } from 'vue'
const lang = ref(localStorage.getItem('lang') || navigator.language.slice(0, 2))
lang
和选定的选项,并在更改时发出 lang: <select
@change="emit('changeLang', lang)"
v-model="lang"
class="p-1 text-sm rounded-lg text-gray-700"
>
<option class="block px-4 py-2 hover:bg-gray-100" disabled>
{{ currentFlag }} {{ currentText }}
</option>
<option
class="block px-4 py-2 hover:bg-gray-100"
v-for="language in langs"
:key="language.text"
:value="language.value"
>
{{ language.flag }} {{ language.text }}
</option>
</select>