【粗暴直接】如果国际化切换涉及的手动修改太多,干脆切换语言的时候直接刷新页面重新渲染算了,以下都是不刷新页面的方法
data中的数据初始化一次之后,不手动修改是不会变化的,所以直接在 data中使用this.$t('xxx')
,只有页面首次加载是有效的,中途切换的话,是没办法跟着切换的。
解决方法 1: 将需要用到国际化的数据定义在computed
里面
<template>
<div>
<ul>
<li v-for="data in list">{
{ data.name }}li>
ul>
div>
template>
<script>
export defaut {
computed: {
list() {
return [
{
name: this.$t('common.title1')},
{
name: this.$t('common.title2')},
{
name: this.$t('common.title3')}
]
}
}
}
</script>
解决方法 2: 在 data中的属性值定义为国际化对应的key
,在 template中使用{ { $t(key) }}
的方式来引用
<template>
<div>
<ul>
<li v-for="data in list">{
{ $t(data.name)}}li>
ul>
div>
template>
<script>
export defaut {
data() {
return {
list: [
{
name: 'common.title1'},
{
name: 'common.title2'},
{
name: 'common.title3'}
]
}
}
}
</script>
// zh_CN.json
{
"common": {
"title1": "标题1",
"title2": "标题2",
"title3": "标题3"
}
}
在 watch中监听 '$i18n.locale'
,在语言切换时,重新配置 option
,使用 setOption()
方法。
(此方法对于echarts中所有配置项都适用,但是过于繁琐,有些配置项没有必要使用,比如有 formatter属性的配置项,可以对 formatter使用回调函数形式)
<script>
export defaut {
data() {
return {
myChart: null,
option: null,
}
},
watch: {
'$i18n.locale'(newValue) {
// 设置 option参数
this.option.series[0].data,forEach( data => {
data.tooltip.formatter = `${
this.$t('common.tipTitle')}
${
this.$t('common.tipName')}: ${
data.value}`;
})
this.option.series[0].markLine.tooltip.formatter = `${
this.$t('common.tipAverage')}
${
this.$t('common.tipContent')}: {c}`;
// 使用 setOption()方法重绘
this.myChart.setOption(this.option)
}
}
}
</script>
不管是全局的 tooltip
,还是 series
中单独定制的,(markline
在官网中没有提供 tooltip
属性,但是我添加生效了。。。)tooltip
中的 formatter
属性均使用回调函数形式,即可实现国际化自动切换
<script>
let option = {
tooltip: {
// 使用箭头函数,否则取不到 this
formatter: (params) => {
return `${
this.$t('common.tipTitle')}
${
this.$t('common.tipName')}: ${
params.name}`;
}
}
}
</script>
legend
的数据需要与 series
的数据中的 name
保持一一对应的关系,可以将这两处都传入国际化对应的 key
,在 legend.formatter
和 series.label.formatter
使用回调函数的形式返回国际化处理后的显示值
有个问题:在语言切换时,需要点击一个图例才会触发legend
和 series
的切换,所以还是需要通过 watch监听,手动触发一下 setOption(),不需要重新设置配置项
<script>
export defaut {
data() {
return {
myChart: null,
option: null,
}
},
mounted() {
let key = 'common.type.';
let legendData = [
`${
key}type1`,
`${
key}type2`,
`${
key}type3`,
`${
key}type4`,
];
let seriesData = [
{
value: 0, name: `${
key}key1` },
{
value: 0, name: `${
key}key2` },
{
value: 0, name: `${
key}key3` },
{
value: 0, name: `${
key}key4` }
];
this.option = {
legend: {
orient: 'vertical',
left: 'left',
data: legendData,
formatter: (params) => {
return this.$t(params);
}
},
series: [{
data: seriesData,
type:'pie',
radius: '60%',
center: ['60%', '60%'],
label: {
normal: {
formatter: (params) => {
return this.$t(params.name);
}
}
}
}]
}
this.myChart.setOption(this.option);
},
watch: {
'$i18n.locale'(newValue) {
// 不需要重新设置配置项,只需要手动触发一下setOption()
this.myChart.setOption(this.option)
}
}
}
</script>
data
中定义表头时,在 renderHeader回调函数中定义表头显示内容data () {
return {
column: [{
key: 'name',
renderHeader: (h, params) => {
return h('strong', this.$t('common.name'));
}
},
{
key: 'age',
renderHeader: (h, params) => {
return h('strong', this.$t('common.age'));
}
},
{
key: 'gender',
renderHeader: (h, params) => {
return h('strong', this.$t('common.gender'));
}
}]
}
}
grid
)grid: {
top: "40", // 预留y轴单位的展示空间
left: "40", // 预留y轴刻度数值的展示空间
right: "40", // 预留x轴单位的展示空间
bottom: "30" // 预留x轴类目名称的展示空间
}
问题原因: Tab
一开始是隐藏的,没有宽高,echarts在初始化时,没有获取到宽高导致图表显示不出来
解决方法: 每次设置完 option
调用 setOption()
之后,再手动调用一下 resize()
方法,或者每次都重新执行 echarts.init()
、setOption()
问题原因: webpack中配置了 url-loader
来处理字体文件,大小低于limit
属性限制的资源被转换成了 Base64
解决方法: 将这个 limit
设置为一个比较小的值
**问题原因:**嵌套的 Tabs
标签需要在 Tabs
中指定 name
属性来区分层级,在 TabPane
中设置 tab
属性指向对应 Tabs
的 name
字段。
<template>
// 在 Tabs上设置 name属性
<Tabs name="tab1" type="card" @on-click="tabChange">
// 在 TabPane上设置 tab属性
<TabPane :label="'标签1'" name="overview" tab="tab1">
// 子组件
<my-component>my-component>
TabPane>
<TabPane :label="'标签2'" name="transport" tab="tab1">
TabPane>
Tabs>
template>
<template>
// 在 Tabs上设置 name属性
<Tabs name="tab2" type="card" @on-click="tabChange">
// 在 TabPane上设置 tab属性
<TabPane :label="'标签1.1'" name="flow" tab="tab2">TabPane>
<TabPane :label="'标签1.2'" name="speed" tab="tab2">TabPane>
Tabs>
template>
问题原因: .ivu-tabs
设置了 overflow: hidden
解决方法: 将分页器的 placement
属性设置为 top
,下拉选项框就会在分页器上方展开
更新: 其他一些下拉框也会被挡住,比如作为查询条件的下拉框,直接在 css中设置 overflow: visible !important;
覆盖,暂时不知道这样会有什么问题
<template>
<div>
<Table
stripe
:max-height="maxHeight"
:columns="columns"
:data="tableData"
@on-selection-change="selectionChange" />
<div class="clearfix" style="margin: 10px;">
<div style="float: right;">
<Page
:total="pagination.total"
:current="pagination.current"
:page-size="pagination.size"
:placement="placement"
size="small"
show-elevator
show-sizer
@on-change="changePage"
@on-page-size-change="changePageSize" />
div>
div>
div>
template>
props: {
placement: {
type: String,
default () {
return 'top'
}
}
},
解决方法: 参考官方文档中 “异步关闭” ,给Modal添加属性loading后,点击确定按钮对话框不会自动消失,并显示 loading 状态,需要手动关闭对话框,常用于表单提交。
<template>
<div>
<Modal
v-model="modalhowFlag"
:loading="modalLoading"
:title="xxx"
:ok-text="保存'"
@on-ok="executeSaving"
width="60%">
<From ref="formValidate" :rules="ruleValidate">
...
From>
Modal>
div>
template>
methods: {
executeSaving() {
this.$refs.formValidate.validate((valid) => {
// 数据校验
if (valid) {
// 发送请求
axios({
...}).then(res => {
if (res.data.status == 'ok') {
this.$Message.success('Success!');
this.$emit('savingHandle', true);
} else {
this.$Message.error('Fail!');
this.$emit('savingHandle', false);
}
}).catch(err => {
this.$Message.error('Fail!');
this.$emit('savingHandle', false);
})
} else {
this.$Message.error('Fail!');
this.$emit('savingHandle', false);
}
}
},
// 保存结果
savingHandle(flag) {
// console.log(valid)
// 关闭 确定按钮的 loading
this.modalLoading = false;
if (flag) {
// 保存成功,关闭 Model
this.createShowFlag = false;
}
}
},
问题现象: 同时添加 必填 和 正则校验时,如果输入非数字,会提示必填。
解决思路1-实现有问题,只是记录一下,以后面的解决方法为准: 将“格式”校验写在“必填”校验之前,并且两者都要指定 type:number
,并且 也要指定
number
类型—— 页面无法显示必填标识*
<template>
<Form ref="createForm" :model="newObj" :rules="ruleValidate" :label-width="150">
<FormItem label="xx号码" prop="xxNumber">
<Input v-model="newObj.xxNumber" number/>
FormItem>
Form>
template>
computed: {
ruleValidate() {
return {
asNumber: [
// xxNumberPattern是自定义的正则
{
type: 'number', pattern: xxNumberPattern, message: '格式不正确。', trigger: 'blur' },
{
type: 'number', required: true, message: '该字段为必填。', trigger: 'blur' }
]
}
}
}
解决方法: 仍然默认
text
类型,“必填”校验使用默认方式,不指定number
,“格式”校验需要自定义
<template>
<Form ref="createForm" :model="newObj" :rules="ruleValidate" :label-width="150">
<FormItem label="xx号码" prop="xxNumber">
<Input v-model="newObj.xxNumber" />
FormItem>
Form>
template>
computed: {
ruleValidate() {
return {
asNumber: [
{
required: true, message: '该字段为必填。', trigger: 'blur' },
{
validator: this.xxNumberFormatValidate, trigger: 'blur' }
]
}
}
},
methods: {
xxNumberFormatValidate(rule, value, callback) {
// xxNumberPattern是自定义的正则
if (!xxNumberPattern.test(value)) {
callback('格式不正确。');
} else {
callback();
}
}
}
根据条件切换,切换后原先条件下的
的校验报错信息仍然显示在页面上问题原因: 根据 vue的渲染规则,切换条件会复用原先的
组件的 dom,只更新其中的数据,导致原先校验的报错信息还会保留在页面上
解决方法: 给不同条件下的
添加不同的 key
<template>
<Form ref="configForm" :model="config" :rules="ruleValidate" :label-width="150">
<FormItem label="选择条件" prop="condition">
<Select v-model="config.condition">
<Option v-for="o in conditionOptions" :value="o.id" :key="`o-${o.id}`">{
{ o.name }}Option>
Select>
FormItem>
<FormItem label="选择设备" prop="deviceIds" v-if="config.condition == 1" key="device">
<CheckboxGroup v-model="config.deviceIds">
<Checkbox v-for="o in deviceList" :label="o.id" :key="`o-${o.id}`">{
{ o.name }}Checkbox>
CheckboxGroup>
FormItem>
<FormItem label="选择A端设备" prop="deviceAIds" v-if="config.condition == 2" key="deviceA">
<CheckboxGroup v-model="config.deviceAIds">
<Checkbox v-for="o in deviceAList" :label="o.id" :key="`o-${o.id}`">{
{ o.name }}Checkbox>
CheckboxGroup>
FormItem>
<FormItem label="选择B端设备" prop="deviceBIds" v-if="config.condition == 2" key="deviceB">
<CheckboxGroup v-model="config.deviceBIds">
<Checkbox v-for="o in deviceBList" :label="o.id" :key="`o-${o.id}`">{
{ o.name }}Checkbox>
CheckboxGroup>
FormItem>
Form>
template>
computed: {
ruleValidate() {
return {
condition : [
{
type: 'number', required: true, message: '请选择条件', trigger: 'change' }
],
deviceIds: [
{
type: 'array', required: true, message: '请选择设备', trigger: 'change' }
],
deviceAIds: [
{
type: 'array', required: true, message: '请选择A端设备', trigger: 'change' }
],
deviceBIds: [
{
type: 'array', required: true, message: '请选择B端设备', trigger: 'change' }
]
}
}
}