新建项目
项目配置
1.开启 PreBundle 配置
开发环境热更新占用内存可以大大降低,热更新所需时间也将大幅减少;生产模式也可以通过提前编译依赖,大幅提升部署效率。
1 2 3 4 5 6 7 8 9 10
| const config = { compiler: { type: 'webpack5', prebundle: { enable: true, }, }, }
|
生产预渲染
1 2 3 4 5 6 7 8 9 10
| export default{ mini: { prerender: { match: 'pages/**', exclude: [] } }, }
|
预渲染会增加包体积,所以除非万不得已,否则不应该使用,而且有可以替代预渲染的方案:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| class SomePage extends Component { state = { mounted: false, }
componentDidMount() {
Taro.nextTick(() => { this.setState({ mounted: true, }) }) }
render() { return ( <View> <FirstScreen /> /* 假设我们知道这个组件会把用户的屏幕全部占据 */ {this.state.mounted && ( <React.Fragment> {' '} /* CompA, B, C 一开始并不会在首屏中显示 */ <CompA /> <CompB /> <CompC /> </React.Fragment> )} </View> ) } }
|
持久化缓存功能,提升二次编译速度,提升开发效率
同时打包多端代码,多端项目同时调试
1 2 3 4 5
| const baseConfig = { ... outputRoot: `dist/${process.env.TARO_ENV}`, }
|
半编译模式 —— CompileMode 通常用于节点较多的列表
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| const config = { mini: { experimental: { compileMode: true } } }
function GoodsItem () { return ( <View compileMode> ... </View> ) }
|
常见问题:
- 编译出的模板文件会增加包体积
- 只能优化部分语法
优化主包体积大小
1 2 3 4 5 6 7 8 9 10 11 12 13
|
module.exports = { mini: { optimizeMainPackage: { enable: true, }, }, }
|
添加环境字段
用taro init生成项目时,根目录下会发现有三个.env.xxx
文件。
因为默认打包时查找的文件是NODE_ENV
的值,所以需要把.env.dev
和.env.prod
文件改为.env.development
和.env.production
;
或者可以在package.json
文件中修改命令"dev:weapp": taro build --type weapp --watch --mode dev
;
可以发现命令中不加--mode dev
时默认mode
为development
;
两种方案皆可。
然后就可以在.env.xxx
文件中添加对应环境变量字段:
1 2 3
| # 配置文档参考 https: TARO_APP_ID="开发环境小程序APPID" TARO_APP_API="https://api-dev.com"
|
如果想用除development
和production
之外的环境变量,如test
,则需要在对应.env.test
环境变量配置文件中增加如TARO_APP_ENV
字段来区分。
请注意,只有以TARO_APP_
开头的变量将通过webpack.DefinePlugin
静态地嵌入到客户端侧的代码中。这是为了避免和系统内置环境变量冲突。
Uncaught Error: Rendered fewer hooks than expected. This may be caused by an accidental early return statement.
不要在循环,条件或嵌套函数中调用Hook。相反,始终在React函数的顶层使用Hooks。通过遵循此规则,您可以确保每次组件呈现时都以相同的顺序调用Hook。这就是允许React在多个useState和useEffect调用之间正确保留Hook状态的原因。
选择在没有判断条件的顶层使用useContext、useState、useEffect、userHistory、useTransaction等,将获取的值,作为参数传给子组件使用。
多个页面引用同一个自定义组件时,页面不显示
开启optimizeMainPackage
打包优化导致的。。。暂时不知道原因。。。估计是官方bug
useEffect
两个参数,第一个参数为函数,函数内执行初始化代码,可以返回一个函数,用来组件销毁时执行;
第二个参数为数组,传值则 Effect 在 初始渲染后以及依赖项变更的重新渲染后 运行;
1 2 3
| useEffect(() => { }, [a, b]);
|
传空数组,Effect 仅在 初始渲染后 运行;
1 2 3 4 5 6 7 8
| useEffect(() => { }, []);
|
如果完全不传递依赖数组,则 Effect 会在组件的 每次单独渲染(和重新渲染)之后 运行。
alias
用于配置目录别名,从而方便书写代码引用路径。
1 2 3 4 5 6 7 8 9 10
| module.exports = { alias: { '@/components': path.resolve(__dirname, '..', 'src/components'), '@/utils': path.resolve(__dirname, '..', 'src/utils'), }, }
import A from '@/components/A'
|
为了让编辑器(VS Code)不报错,并继续使用自动路径补全的功能(F12能定位到引用文件并打开):
1 2 3 4 5 6 7 8 9 10
| { "compilerOptions": { "baseUrl": ".", "paths": { "@/components/*": ["./src/components/*"], "@/utils/*": ["./src/utils/*"], } } }
|
mobx中请求异步赋值警告
1 2 3 4 5 6 7 8 9 10 11 12
| import { runInAction } from 'mobx'; getAdvData = async () => { const data = await api.http({ url: '/xjb/city/advList' }) runInAction(() => { this.banner = data.result.first_banner this.cipian = data.result.first_cipian this.jingang = data.result.first_jingang this.address = data.result.jiabo_adress[0].image_url this.yunying = data.result.first_yunying }) }
|
这是由于引用组件顺序不同,打包时会多打包一次,就会发出警告
1 2 3 4 5 6 7 8 9
| export default { mini: { miniCssExtractPluginOptions: { ignoreOrder: true, }, } };
|
上滑加载page不更新问题
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
|
const [list, setList] = useState([]); const [hasData, setHasData] = useState(true); const [pages, setPages] = useState(1); const getData = async (page = 1, refresh = true) => { setPages(page); let res = await api.http({ url: '/api/getdata', data: { page } }); if (refresh) { setList(res.data); } else { setList(list.concat(res.data)); } setHasData(res.data?.length < 10 ? false : true); }
useReachBottom(() => { if (hasData) { getData(currentTab, pages + 1, false); } })
|
ios小程序不支持直接写backdrop-filter,需要加上浏览器前缀-webkit-backdrop-filter
ios偶发自定义tabbar点击没反应问题
经过真机调试,发现自定义tabbar在来回切换,会有一定几率点不到,因为tabbar被挤出了页面,掉在最下面,虽然还能看到,导致点不到
原因应该是我这个小程序其他页面都是自定义头部,就这个点不到的页面是原生头部,切换过快计算错误,导致掉下去
1 2 3 4 5 6 7
| useDidShow(() => { Taro.pageScrollTo({ scrollTop: 1 }) })
|
跳过编译某个css属性
1 2 3 4 5 6 7 8 9 10
| div{ -webkit-box-orient: vertical;
-webkit-box-orient: vertical; }
|
适配小程序和H5安全距离的tabbar
小程序:
1 2 3
| .tabbar{ padding-bottom: calc(10px + env(safe-area-inset-bottom)); }
|
H5:
1 2 3 4 5 6 7
| <meta name="viewport" content="width=device-width,initial-scale=1.0,viewport-fit=cover">
|
解决移动端设置放大字体,导致页面也被放大显示不全
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| { h5: { postcss: { pxtransform: { enable: true, config: { baseFontSize: 50, maxRootSize: 100 } } } }, }
|
这样配置好处有2:
1.解决了手机设置了放大,页面也被放大显示不全的问题;
2.调试看元素尺寸清晰,设计稿标准尺寸下,比如元素350px,则布局中换算的为3.5rem,直观又不用手动换算。
compression-webpack-plugin开启gzip压缩(服务器端其实也可以开启gzip,无需前端配置)
Taro.setClipboardData
Taro.setClipboardData方法不能在异步回调中使用,ios浏览器H5会失效
全局注入 scss
- config/index.js文件中:
单文件路径形式
当只有 resource 字段时,可以传入 scss 文件的绝对路径。1 2 3 4 5 6
| module.exports = { sass: { resource: path.resolve(__dirname, '..', 'src/styles/variable.scss'), }, }
|
多文件路径形式
当只有 resource 字段时,也可以传入一个路径数组。1 2 3 4 5 6 7 8 9
| module.exports = { sass: { resource: [ path.resolve(__dirname, '..', 'src/styles/variable.scss'), path.resolve(__dirname, '..', 'src/styles/mixins.scss'), ], }, }
|
H5里滑动弹层禁止弹层下面的页面滚动
1 2 3 4 5 6 7
| const touchMove = (e) => { e.preventDefault() } <View catchMove={true} onTouchMove={(e) => touchMove(e)}>
</View>
|