vue 项目利用 vuex+mixins 实现全局换肤及多语言

项目中需要做一个全局换肤(主题色)以及多语言的需求,在通用页更改,全局生效。

我们都知道,vue是MVVM模式,即模型-视图-视图模型,视图更新,数据会跟着更新,反之也一样。但是仅仅在当前组件生效,那么:

如何在一处修改数据就能触发全局视图的更新呢

答案就是vuex状态管理。

有了状态管理,如何将主题色,语言数据等注入每一个组件呢?

我们可以用mixin(混入),单组件混入或全局混入都可,可以根据需要权衡是否使用全局混入,全局混入意味着每一个new出来的组件,都会拥有混入的方法和数据,并且优先级是组件内部所声明的数据或方法>混入的

 

下面我们就来进入正题,以uni-app为例

首先,在项目根路径下新建store文件夹,并在store目录下新建module文件夹,添加主题色theme.js和多语言lang.js的配置文件

lang.js

let userLang , lang = {};
try {
	// 1. 分析用户已经选择的语言 
	userLang = uni.getStorageSync("userLang");
	
	// 2. 如果用户没有选择过则设置默认语言
	if(!userLang){
		userLang = 'zh'
	}
	
	switch(userLang.substring(0, 2)) {
		case 'zh':
			lang = require('../../lang/zh.js');
			break;
		case 'en':
			lang = require('../../lang/en.js');
			break;
		case 'ja':
			lang = require('../../lang/ja.js');
			break;
		default:
			lang = require('../../lang/zh.js');
	}
} catch (e) {
	// error
}

const state = {
	lang : lang
}

const mutations={
     changeLang(state, lang) {
        state.lang = lang;
     }
 }

const actions = {
	changeLang: function(context){
		let lang = {};
		
		uni.showActionSheet({
			itemList:['简体中文', 'English', '日本語'],
			success: function(e){
				try {
					if (e.tapIndex == 0) {
						uni.setStorageSync('userLang', 'zh');
						lang = require('../../lang/zh.js');
					} else if (e.tapIndex == 1){
						uni.setStorageSync('userLang', 'en');
						lang = require('../../lang/en.js');
					} else {
						uni.setStorageSync('userLang', 'ja');
						lang = require('../../lang/ja.js');
					}
				} catch (e) {
					// error
				}
				
				context.commit('changeLang', lang);
			}
		});
	}
}

export default {
	namespaced: true, // 当你需要在别的文件里面使用( mapGetters、mapActions)时
	state,
	actions,
	mutations
}

theme.js

let defaultColor;

try {
	// 获取用户已设置的主题色
	defaultColor = uni.getStorageSync("themeColor");
	
	// 如果没有,设置默认色
	if(!defaultColor){
		defaultColor = '#40aee2';
	}
} catch (e) {
	// error
}

const state = {
	themeColor: defaultColor, // 初始化为配置的主题色
};

const mutations = {
	setThemeColor(state, color) {
		state.themeColor = color;
	}
};

const actions = {
	setThemeColor(context, color) { // 触发mutations里面的setThemeColor ,传入数据形参color
		let themeColor = '';
		
		uni.showActionSheet({
			itemList: ['红色', '橙色'],
			success: function(e) {
				if (e.tapIndex == 0) {
					themeColor = '#f25762';
				} else {
					themeColor = '#ff6600';
				}
				
				uni.setStorageSync('themeColor', themeColor);
				context.commit('setThemeColor', themeColor);
			}
		});
	}
};

export default {
	namespaced: true, // 当你需要在别的文件里面使用( mapGetters、mapActions)时
	state,
	actions,
	mutations
}

store/index.js

import Vue from 'vue'
import Vuex from 'vuex'
import themeColor from './modules/theme'
import lang from './modules/lang'

Vue.use(Vuex)
const debug = process.env.NODE_ENV !== 'production'

export default new Vuex.Store({
	modules: {
		themeColor,
		lang
	},
	//在严格模式下,无论何时发生了状态变更且不是由 mutation 函数引起的,将会抛出错误。这能保证所有的状态变更都能被调试工具跟踪到。
	strict: debug
})

然后在项目入口文件中引入并挂载

main.js

import Vue from 'vue'
import App from './App'
import store from "./store"
import { mapState } from 'vuex'

// 全局混入主题色,多语言
Vue.mixin({
	computed: {
		...mapState('lang', {
			lang: 'lang'
		}),
		...mapState('themeColor', {
			themeColor: 'themeColor'
		})
	}
})

Vue.config.productionTip = false
Vue.prototype.$store = store

App.mpType = 'app'

const app = new Vue({
	store,
    ...App
})
app.$mount()

在index.vue中使用

<template>
	<view class="content">
		<image class="logo" src="/static/logo.png"></image>
		<view class="text-area">
			<text class="title">{{lang.hello}}</text>
		</view>
		<navigator open-type="navigate" url="./test">
			<button class="button" :style="{background: themeColor}">去更换主题色和语言</button>
		</navigator>
	</view>
</template>

<script>
	export default {
		data() {
			return {}
		}
	}
</script>

在test.js中设置

<template>
    <view>
        <view class="list">
			<view class="items" @tap="changeLang">
				<view class="body">
					<view class="title">多语言<text>跟随系统</text></view>
				</view>
			</view>
			<view class="items" @tap="setThemeColor">
				<view class="body">
					<view class="title">使用默认皮肤<text>选择皮肤</text></view>
				</view>
			</view>
		</view>
    </view>
</template>
<script>
    import {mapActions} from 'vuex';

    export default {
        methods: {
            ...mapActions('lang', {
                'changeLang': 'changeLang'
            }),

            ...mapActions('themeColor', {
                'setThemeColor': 'setThemeColor'
            })
        }
    }
</script>

以上只是提供一个简单的示例,具体的实现细节可以自己修改。

其他文件:

lang/zh.js

module.exports = {
	hello: '你好'
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值