一. 项目搭建
1. 安装@tarojs/cli
npm i -g @tarojs/cli @3.4.9
npm i @nutui/nutui-taro@3.1.20 //ui框架,看需要安装
2. 项目初始化
$ taro init myApp
3. 相关文档
二. 多端开发配置
1. config.index.js
const config = {
...
outputRoot: `dist/${process.env.TARO_ENV}`,
...
}
2. project.config.json
{
...
"miniprogramRoot": "dist/weapp/",
...
}
三. 多端编译问题
1. weapp -> alipay
编译
1.1 <rich-text>
nodes
属性兼容
解决办法:
// 通过mini-html-parser2对string进行处理
import parse from 'mini-html-parser2';
parse(nodes, (err, nodes) => {
if (!err) {
// nodes
}
});
1.2 页面自定义导航栏
// page.config.js
let config = {};
if (process.env.TARO_ENV === 'weapp') {
config = { navigationStyle: 'custom'};
}
if (process.env.TARO_ENV === 'alipay') {
config = { transparentTitle: 'always'};
}
export default config;
1.3 getSystemInfoSync().safeArea
兼容
作用:通过getSystemInfoSync().screenHeight
与 getSystemInfoSync().safeArea.bottom
对比,判断是否存在safeArea
,但alipay
的getSystemInfoSync()
不存在safeArea
该属性
解决办法:
- 1.
webapp
保持原有逻辑 - 2.
alipay
通过model
(手机型号)参数 直达地址
export const isIPhoneX = () => {
if (process.env.TARO_ENV === 'weapp') {
const screenHeight = getSystemInfoSync().screenHeight;
const bottom = getSystemInfoSync().safeArea.bottom;
return screenHeight !== bottom;
}
if (process.env.TARO_ENV === 'alipay') {
const model = getSystemInfoSync().model;
const [num, index] = model.split(',');
const phoneNum = num.replace('iPhone', '');
if (phoneNum >= '11' && model !== 'iPhone14,6') {
return true;
}
if (phoneNum === '10' && (index === '3' || index === '6')) {
return true;
}
return false;
}
};
1.4 alipay
中 <input/>
设置 background-image
存在显示bug
解决办法: 背景图设置在父容器上
1.5 <input/>
标签display
属性
weapp
<input/>
->block
alipay
<input/>
->inline-block
1.6 <map>
标签display
属性
weapp
map
->block
alipay
map
->inline-block
1.7 openLocation()
- 使用内置地图查看位置
alipay
多个必填参数address
直达地址
openLocation({
latitude: '',
longitude: '',
name: '',
scale: 14,
address: '' //支付宝参数必填
});
1.8 关联公众号/生活号
weapp
->official-account
直达地址
alipay
->lifestyle
直达地址
- 注意:
1.
生活号
如果升级为生活号+
,public-id
不在支持
2.需要小程序后台运营中心配置小程序横幅组件,点击应用生成一下代码
<lifestyle scene-id="d7e1ed36211c4a52861cb99" />
但taro编译存在问题,会过滤lifestyle的scene-id属性,导致页面组件不显示
- 解决办法:
a.配置关注按钮组件,前端自己写样式。
<life-follow scene-id="0cb2c4ad8a22439ea4c91b70838d339f" />
b.
dist/alipay/pages/index/index.axml
- 该组件页面
找到lifestyle标签,手动增加属性sceneId【需要每次编译,都会被覆盖】
c. 修改npm包,打补丁
1.9 login()
获取登录凭证
weapp
-login
->openId
【用户唯一标识】及unionid
【用户在开放平台的唯一标识符,若当前小程序已绑定到微信开放平台帐号下会返回】直达地址alipay
-getAuthCode
-> user_id【支付宝用户的唯一标识】 直达地址
1.10 获取定位兼容
getSetting({
success: function (res) {
if (process.env.TARO_ENV === 'weapp') {
if (!res.authSetting['scope.userLocation']) {
authorize({
scope: 'scope.userLocation',
success: async () => {
const { location, city } = await getMap();
that.location = location;
that.curCity = city;
}
});
} else {
getMap().then(({ location, city }) => {
console.log(location, city);
that.location = location;
that.curCity = city;
});
}
} else if (process.env.TARO_ENV ==='alipay') {
getLocation({
type: '1',
success({ longitude, latitude, city }) {
that.location = {
lng: longitude,
lat: latitude
};
that.curCity = city;
}
});
}
}
});
1.11 <button>
样式 显示不同
-
webapp
存在默认行高
-
alipay
无默认行高
解决办法:1.固定行高 2.flex居中
1.12 获取元素宽高兼容
weapp
写法如下,但是alipay
不支持该写法
createSelectorQuery()
.select('.rich-text')
.boundingClientRect(function (rect) {
isOver.value = rect.height > 70;
})
.exec();
统一处理如下
createSelectorQuery()
.select('.rich-text')
.boundingClientRect()
.exec(([{ height }]) => {
isOver.value = height > 70;
});
1.13 http方法
enableCookie 默认 false,开启后可在headers中编辑cookie(10.2.33版本开始支持)
1.14 image
长按识别
-
weapp
-show-menu-by-longpress="true"
-
alipay
- 不支持
1.15 enableAlertBeforeUnload
&disableAlertBeforeUnload
返回拦截
alipay
- 基础库 2.7.17 及以上版本,客户端 10.2.60 及以上版本及本地IDE不支持
- 本地开发IDE需要操作如下,否则报错
- 根目录新建文件
project.alipay.json
{
"enableAppxNg": true,
"enableNodeModuleBabelTransform": true
}
1.17 <picker>
- event.detail.value
数据类型不一致 event
对象如下图所示
weapp
- string
alipay
- number
1.18 uploadFile
上传文件
需要新增必填参数
fileName
&fileType
直达地址
fileName = res.tempFiles[0].path.split(‘/’).reverse()[0] 这是临时文件名【原文件名无法获取】
fileType = ‘image’
1.19 分享
weapp
不配置enableShareAppMessage: true
的话,不支持alipay
默认支持 需调用hideShareMenu
禁用
1.20 picker mode='date'
的change事件
返回event.detail.value时间格式不一致。
weapp
-> ‘2022-04-01’alipay
-> 1.IDE
-‘2022-04-01’ 2.真机
-‘2022/04/01’
1.21 跳转问题
a. 公众号或生活号文章
weapp
官方公众号文章 - 可直接webview打开alipay
生活号文章 - navigateToAlipayPage
if (jumpUrl.startsWith('https://render.alipay.com')) {
my.ap.navigateToAlipayPage({
path: encodeURIComponent(jumpUrl)
});
}
b.其他
weapp
跳转tabbar page,只可用switchTab
,navigateTo
会报错
//当无法区分url是否为tabbar page(比如路径动态配置)时,兼容写法如下
navigateTo({
url,
fail: function (res) {
switchTab({ url })
}
})
aliapy
里navigateTo
和switchTab
都可以用,两个api区别是navigateTo
左上角有返回按钮
兼容写法如下
//通过获取app.config.js中的配置来判断url是否为tabbar page
import('@/app.config.js').then(({ default: app }) => {
const isTabBar = app.tabBar.list.some((item) => url.includes(item.pagePath));
isTabBar ? switchTab({ url }) : navigateTo({ url });
});
1.22 页面下拉刷新
//page.config.js
let config = {};
if (process.env.TARO_ENV === 'weapp') {
config = { enablePullDownRefresh: true};
}
if (process.env.TARO_ENV === 'alipay') {
config = { pullRefresh: true};
}
export default config;
支付宝需要额外配置app.config.js
export default {
window: {
...
allowsBounceVertical: 'YES' //是否允许向下拉拽
},
...
}
1.23 按需注入配置问题
weapp
配置app.config.js
export default {
lazyCodeLoading: 'requiredComponents',
...
}
alipay
存在分包的话需要额外添加参数subPackageBuildType
,否则上传版本会报错。
export default {
lazyCodeLoading: 'requiredComponents',
subPackageBuildType: 'shared',
...
}
1.24 build
打包报错
解决办法
//config/index.js mini下增加以下配置解决
webpackChain(chain, webpack) {
chain.merge({
module: {
rule: [
{
test: /.js$/,
loader: 'babel-loader'
}
]
}
});
}
2. weapp -> h5
编译
2.1 本地运行设置
//config/index.js
const config = {
...
devServer: {
https: true,
host: 'localhost.**.com',
port: 3000
}
...
}
2.2 http方法
credentials 设置 H5 端是否携带 Cookie
2.3 tabbar
背景色设置
默认背景色为
#f7f7fa
通过css设置
.weui-tabbar{
background-color: #fff;
}
2.4 不支持的API及功能
通用解决办法 -
process.env.TARO_ENV !== 'h5'
a. canIUse
- 检测小程序版本更新
b. getSetting
- 获取用户授权
c. getMenuButtonBoundingClientRect
- 获取胶囊信息,从而计算胶囊高度,如下图
解决办法:
/**
* 系统信息
*/
const systemInfo = getSystemInfoSync();
/**
* 导航栏高度
*/
const statusBarHeight = ref(systemInfo.statusBarHeight);
const navigationBar = ref(0);
if (process.env.TARO_ENV === 'h5') {
navigationBar.value = 60;
} else {
/**
* 获取胶囊信息
*/
const menu = getMenuButtonBoundingClientRect();
/**
* 胶囊高度
*/
navigationBar.value =
(menu.top - statusBarHeight.value) * 2 +
menu.height +
statusBarHeight.value;
}
d. enableAlertBeforeUnload
disableAlertBeforeUnload
- 返回提示拦截
解决办法:监听返回按钮事件
e. getOpenerEventChannel
- 页面间通信
const pages = getCurrentPages();// 获取当前页面栈
const current = pages[pages.length - 1];
const eventChannel = current.getOpenerEventChannel();
解决办法: 通过
vuex
、pinia
状态管理插件 注意及时销毁数据
f. button open-type="share"
分享不支持
g. 二维码长按不支持
h. <map>
标签
解决办法: 百度地图SDK
i. createVideoContext
不支持 - 创建 video 上下文 VideoContext 对象
解决办法
const videoContext = isH5 ? null : createVideoContext('myVideo');
videoContext && videoContext.play();
2.5 <nut-noticebar>
标签 margin
不生效
解决办法: 父标签包裹
margin
2.6 标签样式不生效
原因:
swiper
->taro-swiper-core
rich-text
->taro-rich-text-core
image
->taro-image-core
>img
text
->taro-text-core
解决办法:
class样式
2.7 input
高度100%不生效
原因:
input
->taro-input-core
>input
解决办法:
taro-input-core{
height: 100%;
}
taro-input-core input{
height: 100% !important;
}
2.8 h5
最小字体12px
注意内容串行样式兼容
2.9 编译后原生导航栏不存在
2.10 开放功能webview 兼容
目的: 承载网页的容器
原因: webview->iframe
解决办法:
// pages/out/index -->webview
>h5 window.location.href=jumpUrl
>weapp pages/out/index?url=${encodeURIComponent(jumpUrl)}
2.11 body
背景色不生效
原因:被遮盖
解决办法:
.taro_router .taro_page{
background-color: transparent !important;
}
2.12 100vh
影响:底栏遮盖内容区|| 套娃滚动
.taro-tabbar__container .taro_router{
min-height: 100%;
}
2.13 uploadFile
uploadFile
需要参数fileName
,后端由此判断文件格式
微信支付宝获取不到originalFileObj
if(isH5) fileName = res.tempFiles[0].originalFileObj.name
2.14 input
字数限制
h5
->vue指令实现
v-limit-num="curData.maxLength"
App.directive('limit-num', {
mounted(el, { value = 100 }, vnode) {
el.addEventListener('input', function () {
console.log(el.value, value);
if (el.value.length > value) {
el.value = el.value.substring(0, value);
}
});
}
});
weapp
&alipay
支持maxlength
属性
:maxlength="item.maxLength"
2.15 打包
// config/prod.js
module.exports = {
...
h5: {
publicPath: 'cdn目录',
output: {
filename: 'js/app.js',
chunkFilename: 'chunk/[name].[chunkhash:8].js'
}
...
}
...
}
//.gitgnore
dist/ -> /dist/*
!/dist/h5/
2.16 其他文件引入app.config.js
import app from '@/app.config.js'
提示
解决办法如下
if (isH5) {
//
} else {
import('@/app.config.js').then(({ default: app }) => {
});
}
2.17 html 设置
// src/index.html
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="format-detection" content="telephone=no,email=no" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-touch-fullscreen" content="yes" />
<meta name="screen-orientation" content="portrait" />
<meta name="x5-orientation" content="portrait" />
<meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=0,viewport-fit=cover" />
<meta name="theme-color" content="#000000" />
<meta name="HandheldFriendly" content="true" />
<meta name="x5-fullscreen" content="true">
<meta name="fullscreen" content="yes">
<meta http-equiv="x-dns-prefetch-control" content="on">
<link rel="dns-prefetch" href="j1.*.com">
<link rel="dns-prefetch" href="img.*.com">
<link rel="dns-prefetch" href="c.*.com">
<link rel="preconnect" href="j1.*.com">
<link rel="preconnect" href="img.*.com">
<link rel="preconnect" href="c.*.com">
<title>title</title>
<link rel="icon" href="https://*/favicon.ico">
<meta data-vue-meta="ssr" data-vmid="keyword" name="keyword" content="">
<meta data-vue-meta="ssr" data-vmid="description" name="description" content="">
四. 其他
1. page.config.js
不支持文件引入
2. 小程序引入lodash
会报错 - 解决办法
3.video
安卓视频过大,点击播放无效
- 解决办法:1.h5播放 2.上传腾讯视频,跳转腾讯小程序播放