组件库选型
经过我的一系列实践,截止至2025年3月
WOT组件库对小红书小程序的兼容性极差,请谨慎使用!!!
WOT组件库对小红书小程序的兼容性极差,请谨慎使用!!!
WOT组件库对小红书小程序的兼容性极差,请谨慎使用!!!
登录流程,code2Session接口报错
前端:通过xhs.login获取 code 传给后端
后端:
- 首先通过app_id和app_secret调用
https://miniapp.xiaohongshu.com/api/rmp/token获取access_token应用调用凭证,access_token的有效时间为两小时 - 调用
code2Session的接口换取session_key和openid,这里需要传三个参数,但是值得注意的是官网文档说的code这个参数应该放在body中,但是实际上经过我的使用发现code 必须放在 query 中
另外还需要注意 code 的有效时间为 5分钟,过期后会报如下错
{
"success": false,
"msg": "应用访问令牌不匹配",
"data": null,
"code": 410101
}
小红书小程序i18n国际化TabBar、NavBar无效
该项目是基于uniapp开发的,框架上选择了unibest。
首先是在各家小程序中,uniapp的国际化对TabBar和NavBar无效应该都是通病,因为NavBar和TabBar的数据不是响应式的
针对NavBar国际化无效的解决方案
在每个页面的 onShow 生命周期中执行 uni.setNavigationBarTitle,其中t为unibest提供的国际化翻译函数
onShow(() => {
uni.setNavigationBarTitle({
title: t('app.name')
});
});
针对NavBar国际化无效的解决方案
首先是在APP组件的onLaunch生命周期中执行uni.setTabBarItem手动的切换到当前语言的tabbar,此处可以考虑条件编译因为uni.setTabBarItem在H5和APP端是不必要的
注意:这里除了文本设置进去之外,还需要将图标iconPath & selectedIconPath一起设置了,否则在真机调试中会出现切换语言后没有图标的情况
添加这个之后一定要使用hbuilder重新编译小程序,然后重启小红书开发者工具,否则很可能没有效果(小红书开发者工具至少在我用的windows端经常出问题)
// src/app.vue
onLaunch(async () => {
// #ifndef H5
await uni.setTabBarItem({
index: 0,
text: t('tabbar.home'),
iconPath: 'static/tabbar/home.png',
selectedIconPath: 'static/tabbar/homeHL.png'
});
await uni.setTabBarItem({
index: 1,
text: t('tabbar.profile'),
iconPath: 'static/tabbar/personal.png',
selectedIconPath: 'static/tabbar/personalHL.png'
});
await uni.setTabBarItem({
index: 2,
text: t('tabbar.about'),
iconPath: 'static/tabbar/example.png',
selectedIconPath: 'static/tabbar/exampleHL.png'
});
// #endif
});
然后是在切换国际化的地方每次切换都执行uni.setTabBarItem和uni.setNavigationBarTitle,这两个方法需要在存在TabBar或Navbar的页面中才会执行成功,参考如下代码
首先我将上文中提到的两个方法抽取到了函数中如下
// src/utils/common.ts
export const updateTabBarI18n = async () => {
// #ifndef H5
await uni.setTabBarItem({
index: 0,
text: t('tabbar.home'),
iconPath: 'static/tabbar/home.png',
selectedIconPath: 'static/tabbar/homeHL.png'
});
await uni.setTabBarItem({
index: 1,
text: t('tabbar.profile'),
iconPath: 'static/tabbar/personal.png',
selectedIconPath: 'static/tabbar/personalHL.png'
});
await uni.setTabBarItem({
index: 2,
text: t('tabbar.about'),
iconPath: 'static/tabbar/example.png',
selectedIconPath: 'static/tabbar/exampleHL.png'
});
// #endif
};
export const updateNavBarI18n = async (name: string) => {
await uni.setNavigationBarTitle({
title: t(name)
});
};
定义切换按钮组件
// src/components/i18n-switch.vue
<template>
<view
class="float-btn h-64rpx w-64rpx rounded-50% bg-#3A9A8F flex flex-justify-center flex-items-center cursor-pointer"
:style="{ bottom: safeAreaInsets.bottom + 24 + 'rpx' }"
draggable="true"
@click="handleClick">
<i class="iconfont text-44rpx text-white" :class="icon"></i>
</view>
</template>
<script setup lang="ts">
import { t } from '@/locale';
import { updateNavBarI18n, updateTabBarI18n } from '@/utils/common';
defineOptions({
name: 'I18nSwitch'
});
const props = defineProps<{
active?: boolean;
}>();
const emits = defineEmits<{
(event: 'update:active', value: boolean): void; // 定义一个名为 'update:active' 的事件,传递一个布尔值参数
}>();
const active = ref(props.active ?? false);
const icon = ref<string>(uni.getLocale() === 'zh-Hans' ? 'icon-i18n-zh' : 'icon-i18n-en');
const { safeAreaInsets } = uni.getSystemInfoSync();
const handleClick = async () => {
active.value = !active.value;
const nextLang = uni.getLocale() === 'zh-Hans' ? 'en' : 'zh-Hans';
uni.setLocale(nextLang);
if (nextLang === 'zh-Hans') {
icon.value = 'icon-i18n-zh';
} else {
icon.value = 'icon-i18n-en';
}
// 更新tabBar
await updateTabBarI18n();
// 更新navBar
await updateNavBarI18n('app.name');
uni.showToast({
title: t('home.i18n-switch'),
icon: 'none',
duration: 2000
});
};
watch(
() => props.active,
value => {
emits('update:active', value);
}
);
</script>
<style scoped lang="scss">
.float-btn {
position: fixed;
right: 24rpx;
transition: background-color 0.2s;
&:active {
background-color: darken($app-primary-color, 15%);
}
}
</style>
最终效果如下