1、中英文语言切换
1.1 定义多语言json文件
1.2 在main.js中引入
import { createApp } from 'vue'
import App from './App.vue'
import { createI18n } from 'vue-i18n';
import en from './locals/en.js';
import zh from './locals/zh.js';
// 组合语言包对象
const messages = {
en,
zh
}
// 创建i18n实例
const i18n = createI18n({
legacy: false, // 启用 composition API 模式
messages,
locale: navigator.language === 'zh-CN' ? 'zh' : 'en',
})
const app = createApp(App)
app.use(i18n)
1.3 在vue组件中使用
<template>
<div class="header-right">
<el-dropdown>
<span class="el-dropdown-link">
<!-- 在模板使用多语言变量需要使用 $t() 包裹-->
{{ $t("Head.switch") }}
</span>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item @click="changeLocale('zh')"> 中 文 </el-dropdown-item>
<el-dropdown-item @click="changeLocale('en')">English</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</div>
</template>
import { useI18n } from "vue-i18n";
const { t, locale } = useI18n(); //t表示翻译函数,locale表示当前语言值
// 切换语言
const changeLocale = (lang) => {
locale.value = lang;
};
//在js中定义多语言变量,需要用 t() 包裹
const buttons = computed(() => {
return [
{ type: "info", category: 1, text: t('Head.category.device') },
{ type: "info", category: 2, text: t('Head.category.food') },
{ type: "info", category: 3, text: t('Head.category.decoration') },
...
];
})
2、pinia简单使用
3、按关键词和类别搜索
3.1 前端
<template>
<Box>
<div class="operate">
<el-col :span="4">
<el-button type="primary" @click="batchHandling">批量处理</el-button></el-col>
<el-col :span="6">
<div class="checkbox-group">
<!-- '待处理': 0,'已处理': 1 -->
<el-checkbox-group v-model="handleType">
<el-checkbox label="已处理" name="type" />
<el-checkbox label="待处理" name="type" />
</el-checkbox-group>
</div>
</el-col>
<el-col :span="6">
<el-input placeholder="输入反馈关键词" v-model="keyword" @keyup.enter="searchFeedback" /></el-col>
<el-button type="primary" @click="searchFeedback">
搜索</el-button>
</div>
</Box>
</template>
<script>
export default {
data(){
return{handleType: ['待处理'],}
}
computed: {
tansformHandleType() {
const mapping = {
'待处理': 0,
'已处理': 1
};
return this.handleType.map(item => mapping[item])
}
},
methods:{
searchFeedback() {
this.loading = true;
const param = {
keyword: this.keyword,
handleType: this.tansformHandleType
}
service.post("/user/feedback/search", param).then((response) => {
this.feedbacks = response;
this.loading = false;
}).catch(() => {
this.loading = false;
this.$message({
type: 'error',
message: '搜索出错'
});
});
},
}
}
3.2 后端
public List<UserFeedback> searchFeedback(String keyword, List<Integer> handleType) {
System.out.println("keyword:" + keyword);
System.out.println("handleType:" + handleType);
List<UserFeedback> resFeedback = new ArrayList<>();
if (handleType != null && !handleType.isEmpty()) {
for (Integer type : handleType) {
resFeedback.addAll(userMapper.searchFeedback(keyword, type));
}
} else {
// 如果处理类型列表为空,则只根据关键字进行搜索
resFeedback = userMapper.searchFeedback(keyword, null);
}
return resFeedback;
}
//----------------------
Mapper.xml
<select id="searchFeedback" resultType="com.example.mall.entity.UserFeedback">
SELECT *
FROM feedback
<if test="keyword != null and keyword != ''">
WHERE feedback LIKE CONCAT('%', #{keyword}, '%')
<if test="type != null">
AND status = #{type}
</if>
</if>
<if test="keyword == null or keyword == ''">
<if test="type != null">
WHERE status = #{type}
</if>
</if>
</select>
4、子传父组件通信
子传父
充值余额组件(子组件),向信息组件(父组件)传递充值的金额
import { defineEmits } from 'vue';
const emit = defineEmits(['updateAmount'])
let recharge = {
id: localStorage.getItem("userid"),
amount: selectedAmount.value || customAmount.value //选择金额或者输入金额
}
service.post("/user/recharge", recharge).then(res => {
if (res.data == 1) {
ElMessage.success(`充值成功¥${recharge.amount}`);
// 父传子更新数据
emit('updateAmount', recharge.amount)
}
})
信息组件(父组件),接收来自子组件的 金额 信息
<el-dialog style="width: 500px" v-model="showRecharge">
<!-- 子传父自定义事件对应的函数不加参数!!! -->
<Recharge @updateAmount="handleAmount"></Recharge>
</el-dialog>
//通过自定义updateAmount事件触发handleAmount
const handleAmount = (amount) => {
console.log(amount)
profile.balance += amount;
showRecharge.value = false;
};
子父通信
<el-dialog style="width: 500px" v-model="showUpdate">
<!-- 父传子直接绑定值即可 -->
<updateInfo :info="profile" @updateData="handleUpdateInfo"></updateInfo>
</el-dialog>
const handleUpdateInfo = (data) => {
profile.username = data.username;
profile.address = data.address;
profile.balance = data.balance;
profile.password = data.password;
profile.phone = data.phone;
showUpdate.value = false;
};
const emit = defineEmits(['updateData'])
const { info } = defineProps(['info']);
//潘顿原始值和修改值是否相同
const modified = Object.keys(originalUser).some(key => originalUser[key] !== user.value[key]);
if (!modified) {
return; // 不提交数据
}
//如果修改了密码,则hash 未修改则使用原密码的hash
if (user.value.password == '') {
user.value.password = info.password;
} else {
user.value.password = md5(user.value.password);
}
const response = await service.post(`/user/update/${user.value.user_id}`, user.value);
// 更新成功,传递给父组件
if (response.data === "ok") {
service.get(`/user/id=${localStorage.getItem("userid")}`)
.then((res) => {
emit('updateData', res.data);
ElMessage.success("修改成功")
//改了密码则跳转到登录页
if (user.value.password != info.password) {
router.push("/login")
}})
.catch((e) => {
ElMessage.error("修改失败")
})
}
5、对ref reactive的误会
以前只觉得ref处理简单的,reactive处理复杂的;突发奇想用reactive去包裹一个字符串
<input type="text" v-model="a">{{ a }}
let a = reactive("111")
onMounted(() => {
console.log(1, a)
a = "222"
console.log(2, a)
}
如下所示,并非响应式,必须嵌套在对象属性里才可以是响应式
ref
可以处理任意类型的值,包括对象。但是ref处理复杂对象需要用.value去访问,略显复杂。