阐述如何使用unapp开发中vue方式实现移动端中列表点击弹出语言列表,然后进行选择语言!
bash
<!-- pages/index/index.vue -->
<template>
<view class="container">
<!-- 语言切换弹窗 -->
<LanguagePopup :visible="showLanguagePopup" @close="handlePopupClose" />
<!-- 顶部装饰 -->
<view class="top-decor">
<view class="decor-circle circle-1"></view>
<view class="decor-circle circle-2"></view>
<view class="decor-circle circle-3"></view>
</view>
<!-- 主要内容 -->
<view class="main-content">
<!-- Logo区域 -->
<view class="logo-container">
<image class="logo" src="/static/logo.png" mode="aspectFit"></image>
<view class="logo-glow"></view>
</view>
<!-- 欢迎语 -->
<view class="welcome-container">
<text class="welcome-text">{{ getTranslation('welcome') }}</text>
<text class="title-text">{{ currentTitle }}</text>
<view class="title-underline"></view>
</view>
<!-- 语言切换按钮 -->
<view class="button-container">
<view class="language-button" @tap="showLanguagePopup = true">
<view class="button-inner">
<text class="button-icon">🌐</text>
<text class="button-text">{{ currentLanguageName }}</text>
<view class="button-arrow">
<text>▼</text>
</view>
</view>
<view class="button-glow"></view>
</view>
<!-- 提示文本 -->
<!-- <text class="hint-text">点击按钮切换应用语言</text> -->
</view>
</view>
</view>
</template>
<script>
// 局部导入组件
import LanguagePopup from '@/components/LanguagePopup.vue'
export default {
// 注册组件
components: {
LanguagePopup
},
data() {
return {
showLanguagePopup: false,
currentTitle: 'Hello',
currentLanguageName: 'English',
languageCount: 3
}
},
onLoad() {
this.initLanguage()
// 监听语言变化
uni.$on('languageChanged', this.updateLanguage)
},
onUnload() {
uni.$off('languageChanged', this.updateLanguage)
},
methods: {
initLanguage() {
try {
const langModule = require('@/utils/language.js')
const lang = langModule.getCurrentLanguage()
this.currentTitle = lang.translations?.title || 'Hello'
this.currentLanguageName = lang.name || 'English'
// 获取语言数量
const allLangs = langModule.getAllLanguages()
this.languageCount = allLangs.length
} catch (error) {
console.log('语言模块加载失败:', error)
// 使用默认值
this.currentTitle = 'Hello'
this.currentLanguageName = 'English'
this.languageCount = 3
}
},
getTranslation(key) {
try {
const langModule = require('@/utils/language.js')
const translation = langModule.getTranslation(key)
return translation || key
} catch (error) {
// 默认翻译
const defaultTranslations = {
'welcome': 'Welcome to',
'title': 'Hello'
}
return defaultTranslations[key] || key
}
},
handlePopupClose() {
this.showLanguagePopup = false
},
updateLanguage() {
try {
const langModule = require('@/utils/language.js')
const lang = langModule.getCurrentLanguage()
this.currentTitle = lang.translations?.title || this.currentTitle
this.currentLanguageName = lang.name || this.currentLanguageName
} catch (error) {
console.log('更新语言失败:', error)
}
}
}
}
</script>
<style scoped>
.container {
min-height: 100vh;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
position: relative;
overflow: hidden;
}
/* 顶部装饰 */
.top-decor {
position: absolute;
top: -100rpx;
right: -100rpx;
width: 300rpx;
height: 300rpx;
}
.decor-circle {
position: absolute;
border-radius: 50%;
background: rgba(255, 255, 255, 0.1);
}
.circle-1 {
width: 200rpx;
height: 200rpx;
top: 0;
right: 0;
}
.circle-2 {
width: 120rpx;
height: 120rpx;
top: 40rpx;
right: 40rpx;
background: rgba(255, 255, 255, 0.15);
}
.circle-3 {
width: 60rpx;
height: 60rpx;
top: 70rpx;
right: 70rpx;
background: rgba(255, 255, 255, 0.2);
}
/* 主要内容 */
.main-content {
padding: 100rpx 40rpx 60rpx;
display: flex;
flex-direction: column;
align-items: center;
position: relative;
z-index: 1;
}
/* Logo区域 */
.logo-container {
position: relative;
margin-bottom: 80rpx;
}
.logo {
width: 240rpx;
height: 240rpx;
border-radius: 50%;
box-shadow: 0 20rpx 60rpx rgba(0, 0, 0, 0.2);
position: relative;
z-index: 2;
}
.logo-glow {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 280rpx;
height: 280rpx;
border-radius: 50%;
background: rgba(255, 255, 255, 0.1);
animation: pulse 2s infinite;
}
@keyframes pulse {
0%, 100% {
transform: translate(-50%, -50%) scale(1);
opacity: 0.3;
}
50% {
transform: translate(-50%, -50%) scale(1.1);
opacity: 0.2;
}
}
/* 欢迎语 */
.welcome-container {
text-align: center;
margin-bottom: 100rpx;
}
.welcome-text {
display: block;
font-size: 32rpx;
color: rgba(255, 255, 255, 0.9);
margin-bottom: 20rpx;
font-weight: 400;
letter-spacing: 2rpx;
}
.title-text {
display: block;
font-size: 72rpx;
color: white;
font-weight: 700;
margin-bottom: 20rpx;
letter-spacing: 1rpx;
text-shadow: 0 10rpx 20rpx rgba(0, 0, 0, 0.2);
}
.title-underline {
width: 120rpx;
height: 8rpx;
background: rgba(255, 255, 255, 0.8);
border-radius: 4rpx;
margin: 0 auto;
animation: underlineSlide 2s ease-in-out infinite;
}
@keyframes underlineSlide {
0%, 100% {
width: 120rpx;
opacity: 0.8;
}
50% {
width: 160rpx;
opacity: 1;
}
}
/* 按钮容器 */
.button-container {
width: 100%;
display: flex;
flex-direction: column;
align-items: center;
}
/* 语言切换按钮 */
.language-button {
position: relative;
width: 100%;
max-width: 500rpx;
margin-bottom: 40rpx;
}
.button-inner {
background: white;
border-radius: 50rpx;
padding: 30rpx 40rpx;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 15rpx 40rpx rgba(0, 0, 0, 0.2);
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
position: relative;
z-index: 2;
}
.language-button:active .button-inner {
transform: scale(0.98);
box-shadow: 0 8rpx 25rpx rgba(0, 0, 0, 0.15);
}
.button-icon {
font-size: 40rpx;
margin-right: 20rpx;
}
.button-text {
font-size: 36rpx;
font-weight: 600;
color: #333;
flex: 1;
text-align: center;
}
.button-arrow {
color: #999;
font-size: 24rpx;
transform: translateY(2rpx);
transition: transform 0.3s;
}
.language-button:active .button-arrow {
transform: translateY(2rpx) rotate(180deg);
}
.button-glow {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: calc(100% + 20rpx);
height: calc(100% + 20rpx);
border-radius: 55rpx;
background: rgba(255, 255, 255, 0.2);
filter: blur(15rpx);
animation: buttonGlow 2s ease-in-out infinite;
}
@keyframes buttonGlow {
0%, 100% {
opacity: 0.5;
transform: translate(-50%, -50%) scale(1);
}
50% {
opacity: 0.8;
transform: translate(-50%, -50%) scale(1.05);
}
}
/* 响应式调整 */
@media (max-width: 600rpx) {
.main-content {
padding: 80rpx 30rpx 40rpx;
}
.logo {
width: 200rpx;
height: 200rpx;
}
.logo-glow {
width: 240rpx;
height: 240rpx;
}
.title-text {
font-size: 60rpx;
}
.button-inner {
padding: 25rpx 35rpx;
}
.button-text {
font-size: 32rpx;
}
}
</style>
bash
// utils/language.js
import { getCurrentLanguage, setCurrentLanguage, getAllLanguages, t } from './languages/index.js'
export {
getCurrentLanguage,
setCurrentLanguage,
getAllLanguages,
t
}
bash
// utils/languages/index.js
// 导入所有语言文件
import zhCN from './zh-CN.js'
import zhTW from './zh-TW.js'
import enUS from './en-US.js'
import enGB from './en-GB.js'
import ja from './ja.js'
import ko from './ko.js'
import fr from './fr.js'
import de from './de.js'
import es from './es.js'
import ru from './ru.js'
import ar from './ar.js'
import pt from './pt.js'
import it from './it.js'
// 语言映射表
export const languages = {
'zh-CN': zhCN,
'zh-TW': zhTW,
'en-US': enUS,
'en-GB': enGB,
'ja': ja,
'ko': ko,
'fr': fr,
'de': de,
'es': es,
'ru': ru,
'ar': ar,
'pt': pt,
'it': it
}
// 默认语言
const DEFAULT_LANGUAGE = 'zh-CN'
// 获取当前语言
export function getCurrentLanguage() {
try {
const langCode = uni.getStorageSync('currentLanguage') || DEFAULT_LANGUAGE
return languages[langCode] || languages[DEFAULT_LANGUAGE]
} catch (error) {
console.error('获取语言失败:', error)
return languages[DEFAULT_LANGUAGE]
}
}
// 设置当前语言
export function setCurrentLanguage(langCode) {
if (languages[langCode]) {
try {
uni.setStorageSync('currentLanguage', langCode)
// 如果是RTL语言,设置页面方向
if (languages[langCode].rtl) {
uni.setNavigationBarStyle({
frontColor: '#ffffff',
backgroundColor: '#1AAD19',
animation: {
duration: 400,
timingFunc: 'easeIn'
}
})
}
return true
} catch (error) {
console.error('设置语言失败:', error)
return false
}
}
return false
}
// 获取所有语言列表
export function getAllLanguages() {
return Object.values(languages)
}
// 获取翻译文本
export function getTranslation(key, langCode = null) {
const lang = langCode ? (languages[langCode] || getCurrentLanguage()) : getCurrentLanguage()
return lang.translations[key] || key
}
// 简化的翻译函数
export function t(key) {
return getTranslation(key)
}
bash
// utils/languages/zh-CN.js
export default {
code: 'zh-CN',
name: '简体中文',
translations: {
title: '你好',
selectLanguage: '选择语言',
languageChanged: '语言切换成功',
hello: '你好世界',
welcome: '欢迎使用我们的应用',
settings: '设置',
about: '关于',
contact: '联系我们',
home: '首页',
profile: '个人资料',
logout: '退出登录'
}
}
bash
// utils/languages/en-US.js
export default {
code: 'en-US',
name: 'English (US)',
translations: {
title: 'Hello',
selectLanguage: 'Select Language',
languageChanged: 'Language changed successfully',
hello: 'Hello World',
welcome: 'Welcome to our app',
settings: 'Settings',
about: 'About',
contact: 'Contact Us',
home: 'Home',
profile: 'Profile',
logout: 'Logout'
}
}
bash
// utils/languages/ko.js
export default {
code: 'ko',
name: '한국어',
translations: {
title: '안녕하세요',
selectLanguage: '언어 선택',
languageChanged: '언어가 성공적으로 변경되었습니다',
hello: '안녕하세요 세계',
welcome: '우리 앱에 오신 것을 환영합니다',
settings: '설정',
about: '약',
contact: '문의하기',
home: '홈',
profile: '프로필',
logout: '로그아웃'
}
}
main:
bash
import App from './App'
// #ifndef VUE3
import Vue from 'vue'
import './uni.promisify.adaptor'
Vue.config.productionTip = false
App.mpType = 'app'
const app = new Vue({
...App
})
app.$mount()
// #endif
// #ifdef VUE3
import { createSSRApp } from 'vue'
export function createApp() {
const app = createSSRApp(App)
return {
app
}
}
// #endif
此时就完成了语言功能的切换~!nice