03创建Vue项目并实现全球化
创建Vue项目
vue create client-vue
使用Vuex作为状态管理,用于保存从后台获取的应用程序配置ApplicationConfigurationDto
,该对象包含本地化的所有数据。
安装Vue-Cookies
npm install vue-cookies --force
vue-cookies
用于管理cookie,用户选择的语言类型存放在cookie中。
在main.ts
中添加以下代码:
import Cookies from 'vue-cookies'
.use(Cookies)
安装nswag
npm install nswag --force
配置nswag
使用nswag
生成客户端,在package.json
文件中添加以下代码
"scripts": {
"generate-client": "nswag openapi2tsclient /input:https://localhost:7027/swagger/v1/swagger.json /Template:Fetch /UseGetBaseUrlMethod:true /GenerateClientClasses:true /operationGenerationMode:MultipleClientsFromPathSegments /useTransformOptionsMethod:true /useTransformResultMethod:true /clientBaseClass:ClientBase /configurationClass:IConfig /ImportRequiredTypes:true /ExtensionCode:\"import { ClientBase, IConfig } from './clientBase'\" /output:src/api-client/client.ts"
},
/Key:value 为命令参数 详情请见
openapi2tsclient
:从Swagger/OpenAPI规范生成TypeScript客户端代码。
input
: 数据或JSON数据本身的文件路径或URL。
Template
: 异步处理的类型('JQueryCallbacks', 'JQueryPromises', 'AngularJS', 'Angular', 'Fetch', 'Aurelia')
UseGetBaseUrlMethod
:指定是否使用基类中的'getBaseUrl(defaultUrl: string)'方法(默认值:false)
GenerateClientClasses
:指定是否生成客户端类。
operationGenerationMode
:操作生成方式('SingleClientFromOperationId' or 'MultipleClientsFromPathSegments').")]
clientBaseClass
客户端代码的基类
configurationClass
客户端代码的配置类
ImportRequiredTypes
:指定是否应该导入所需的类型(默认值:true)。
ExtensionCode
生成的客户端TS文件中的扩展代码,参数为字符串或文件路径
useTransformOptionsMethod
启用请求参数转换方法
useTransformResultMethod
启用响应结果转换方法
output
:输出文件路径(可选)。
nswag 为node_modules\.bin
中的可执行程序,如果没有配置node_modules
文件夹的环境变量,则这里需要用node_modules/.bin/
替代nswag
执行命令
npm run generate-client
创建ClientBase.ts
在api-client
文件夹中创建ClientBase.ts
文件,添加以下代码
/**
* Configuration class needed in base class.
* The config is provided to the API client at initialization time.
* API clients inherit from #ClientBase and provide the config.
*/
import packageConfig from '../../package.json'
import Cookies from 'vue-cookies'
export class IConfig {
public static readonly acceptLanguageKey = 'acceptLanguage'
/**
* Returns a valid value for the Authorization header.
* Used to dynamically inject the current auth header.
*/
public getAuthorization (): string {
return ''
// return 'the-authentication-token'
}
// 从cookie中获取当前语言
public getAcceptLanguage (): string {
const cookies: any = Cookies
const acceptLanguage = cookies.get(IConfig.acceptLanguageKey)
return acceptLanguage || 'zh-Hans'
}
}
export class ClientBase {
private readonly config: IConfig;
protected constructor (config: IConfig) {
this.config = config
}
// 请求参数转换方法
protected transformOptions (options: RequestInit): Promise<RequestInit> {
options.headers = {
...options.headers,
Authorization: this.config.getAuthorization(),
myHeader: 'myValue',
'accept-language': this.config.getAcceptLanguage() || '' // 在请求头中添加当前语言
}
// 设置跨域请求发送cookie
options.credentials = 'include'
// 指示请求将使用CORS
options.mode = 'cors'
options.cache = 'default'
console.log('transformOptions', 'options:', options)
return Promise.resolve(options)
}
// 响应结果转换方法
protected transformResult (url: string, response: Response, processor: (response: Response) => Promise<any>): Promise<any> {
console.log('transformResult', 'url:', url, response)
if (response === null) return Promise.resolve()
// 判断响应头内容类型为 text/plain 则直接返回响应文本
const contentType = response.headers.get('content-type')
if (contentType != null && contentType.indexOf('text/plain') >= 0) {
return response.text()
}
// 调用回调函数
return processor(response)
}
// 基类中的 getBaseUrl 用于 client 类拼接API请求地址
protected getBaseUrl (defaultUrl: string, baseUrl?: string): string {
if (baseUrl && baseUrl.length > 0) return baseUrl
if (defaultUrl && defaultUrl.length > 0) return defaultUrl
// 从package.json文件中获取baseUrl
return packageConfig.baseUrl
}
}
从
.json
配置文件读取配置信息必须在shims-vue.ts
文件中添加以下配置declare module '*.json' { const value: any; export default value; }
实现状态管理
在store
文件夹中添加文件夹Modules\ApplicationConfiguration
。在store\Modules\ApplicationConfiguration
中添加文件interfaces.ts
,添加以下代码
import { ApplicationConfigurationDto } from '@/api-client/client'
export default interface Configuration{
applicationConfiguration: ApplicationConfigurationDto // 应用程序配置数据
}
在store\Modules\ApplicationConfiguration
中添加文件index.ts
,添加以下代码
import { AbpClient, ApplicationConfigurationDto } from '@/api-client/client'
import { IConfig } from '@/api-client/clientBase'
import RootStateTypes from '@/store/interfaces'
import { Module } from 'vuex'
import Configuration from './interfaces'
const ConfigurationModule: Module<Configuration, RootStateTypes> = {
namespaced: true,
state: {
applicationConfiguration: new ApplicationConfigurationDto()
},
getters: {
getLocalization (state) {
return state.applicationConfiguration.localization
},
l: (state) => (key:string) => { // 全球化的方法,通过该方法显示各国对应的语言
const localization = state.applicationConfiguration.localization
if (localization?.values && localization?.defaultResourceName) {
return localization?.values[localization.defaultResourceName][key]
}
return key
}
},
mutations: {
Set_ApplicationConfiguration (state, data: ApplicationConfigurationDto) {
state.applicationConfiguration = data
}
},
actions: {
// 初始化应用程序配置
initApplicationConfiguration (store): Promise<ApplicationConfigurationDto> {
if (store.state.applicationConfiguration.timing) {
return Promise.resolve(store.state.applicationConfiguration)
}
const client = new AbpClient(new IConfig())
// 获取应用程序配置,并更新状态
return client.applicationConfiguration()
.then(result => {
this.commit('ConfigurationModule/Set_ApplicationConfiguration', result)
return Promise.resolve(store.state.applicationConfiguration)
})
},
// 重置应用程序配置
resetApplicationConfiguration (store): Promise<ApplicationConfigurationDto> {
store.state.applicationConfiguration.timing = undefined
return this.dispatch('ConfigurationModule/initApplicationConfiguration')
}
}
}
export default ConfigurationModule
在store\interfaces.ts
文件的代码给为:
import Configuration from './Modules/ApplicationConfiguration/interfaces'
// 定义根状态类型
export default interface RootStateTypes {
isLogin: boolean
}
// 扩展更状态类型
export interface AllStateTypes extends RootStateTypes {
// 应用程序配置
ConfigurationModule: Configuration
// other state type
}
修改store\index.ts
文件的代码为:
import { InjectionKey } from 'vue'
import { createStore, Store, useStore as baseUseStore } from 'vuex'
import RootStateTypes, { AllStateTypes } from './interfaces'
import ConfigurationModule from './Modules/ApplicationConfiguration'
export default createStore<RootStateTypes>({
state: {
isLogin: false
},
getters: {},
mutations: {
//
},
actions: {},
modules: {
ConfigurationModule
}
})
export const key: InjectionKey<Store<RootStateTypes>> = Symbol('CA3227F5-D73C-4E65-AA3F-BA781CA32231')
export function useStore<T = AllStateTypes> (): Store<T> {
return baseUseStore<T>(key)
}
在main.ts
中添加以下代码:
import store, { key } from '@/store/index'
.use(store, key)
main.ts
完整代码:
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store, { key } from '@/store/index'
import Cookies from 'vue-cookies'
createApp(App)
.use(store, key)
.use(router)
.use(Cookies)
.mount('#app')
在App.vue
里初始化应用程序配置,添加以下代码:
<script lang="ts">
import { defineComponent } from 'vue'
import { useStore } from './store'
export default defineComponent({
mounted () {
const store = useStore()
store.dispatch('ConfigurationModule/initApplicationConfiguration')
}
})
</script>
修改AboutView.vue
文件的代码为:
<template>
<div class="about">
<h1>This is an about page</h1>
<div>
{{ l('LongWelcomeMessage') }} <!--显示对应的语言信息 -->
</div>
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue'
import { mapGetters } from 'vuex'
export default defineComponent({
components: {
//
},
data () {
return {
}
},
beforeMount () {
//
},
mounted () {
//
},
computed: {
// 从状态管理Vuex中映射Get方法到计算属性l中
// 对应的是 `store\Modules\ApplicationConfiguration\index.ts`中Getters中的 l
...mapGetters({
l: 'ConfigurationModule/l'
})
},
methods: {
//
}
})
</script>
到此Vue中实现全球化初步完成,还缺语言的切换,现在是默认的中文。
语言选择
在components\selects
文件夹中添加文件LanguageSelect.vue
,添加以下代码:
<template>
<select
@change="change">
<option
v-for="item in options"
:key="item.cultureName"
:value="item.cultureName"
:selected="isSelected(item)"
>
{{ item.displayName }}
</option>
</select>
</template>
<script lang="ts">
import { LanguageInfo } from '@/api-client/client'
import { IConfig } from '@/api-client/clientBase'
import { useStore } from '@/store'
import { defineComponent } from 'vue'
export default defineComponent({
setup () {
//
},
data () {
return {
data: this.value
}
},
emits: ['onchange'],
watch: {
//
},
computed: {
store () {
return useStore()
},
// 当前语言
currentCulture () {
return this.store.state.ConfigurationModule.applicationConfiguration.localization?.currentCulture?.cultureName
},
// 支持的语言项
options () {
return this.store.state.ConfigurationModule.applicationConfiguration.localization?.languages || new Array<LanguageInfo>()
},
isSelected () {
return (item: LanguageInfo) => {
return item.cultureName === this.currentCulture
}
}
},
mounted () {
//
},
methods: {
// 当选项更改时,将更改后的值保存进cookie中,并重置应用程序配置
change (event: any) {
console.log(event, this.store)
this.data = event.target.value
// 将选择的语言保存进cookie中
this.$cookies.set(IConfig.acceptLanguageKey, this.data)
// 状态管理重置应用程序配置
this.store.dispatch('ConfigurationModule/resetApplicationConfiguration')
this.$emit('onchange', this.data)
}
}
})
</script>
将LanguageSelect.vue
组件添加进AboutView.vue
,就可自由切换想显示的语言了。
如此全球化实现完成
标签:03,Vue,return,client,state,vue,import,全球化,store From: https://www.cnblogs.com/shipengfei/p/17015625.html