新建项目
项目配置
1.开启 PreBundle 配置
开发环境热更新占用内存可以大大降低,热更新所需时间也将大幅减少;生产模式也可以通过提前编译依赖,大幅提升部署效率。
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 
 | const config = {
 compiler: {
 type: 'webpack5',
 
 prebundle: {
 enable: true,
 },
 },
 }
 
 | 
生产预渲染
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 
 | export default{
 mini: {
 prerender: {
 match: 'pages/**',
 
 exclude: []
 }
 },
 }
 
 | 
预渲染会增加包体积,所以除非万不得已,否则不应该使用,而且有可以替代预渲染的方案:
| 12
 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>
 )
 }
 }
 
 | 
持久化缓存功能,提升二次编译速度,提升开发效率
同时打包多端代码,多端项目同时调试
| 12
 3
 4
 5
 
 | const baseConfig = {
 ...
 outputRoot: `dist/${process.env.TARO_ENV}`,
 }
 
 | 
半编译模式 —— CompileMode 通常用于节点较多的列表
| 12
 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>
 )
 }
 
 | 
常见问题:
- 编译出的模板文件会增加包体积
- 只能优化部分语法
优化主包体积大小
| 12
 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文件中添加对应环境变量字段:
| 12
 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 在 初始渲染后以及依赖项变更的重新渲染后 运行;
| 12
 3
 
 | useEffect(() => {
 }, [a, b]);
 
 | 
传空数组,Effect 仅在 初始渲染后 运行;
| 12
 3
 4
 5
 6
 7
 8
 
 | useEffect(() => {
 }, []);
 
 
 
 
 
 
 | 
如果完全不传递依赖数组,则 Effect 会在组件的 每次单独渲染(和重新渲染)之后 运行。
alias
用于配置目录别名,从而方便书写代码引用路径。
| 12
 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能定位到引用文件并打开):
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 
 | {
 "compilerOptions": {
 "baseUrl": ".",
 "paths": {
 "@/components/*": ["./src/components/*"],
 "@/utils/*": ["./src/utils/*"],
 }
 }
 }
 
 | 
mobx中请求异步赋值警告
| 12
 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
 })
 }
 
 | 
这是由于引用组件顺序不同,打包时会多打包一次,就会发出警告
| 12
 3
 4
 5
 6
 7
 8
 9
 
 | export default {
 mini: {
 miniCssExtractPluginOptions: {
 ignoreOrder: true,
 },
 }
 
 };
 
 | 
上滑加载page不更新问题
| 12
 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被挤出了页面,掉在最下面,虽然还能看到,导致点不到
原因应该是我这个小程序其他页面都是自定义头部,就这个点不到的页面是原生头部,切换过快计算错误,导致掉下去
| 12
 3
 4
 5
 6
 7
 
 | useDidShow(() => {
 
 Taro.pageScrollTo({
 scrollTop: 1
 })
 })
 
 | 
跳过编译某个css属性
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 
 | div{
 -webkit-box-orient: vertical;
 
 
 
 
 -webkit-box-orient: vertical;
 
 }
 
 | 
适配小程序和H5安全距离的tabbar
小程序:
| 12
 3
 
 | .tabbar{padding-bottom: calc(10px + env(safe-area-inset-bottom));
 }
 
 | 
H5:
| 12
 3
 4
 5
 6
 7
 
 | <meta name="viewport" content="width=device-width,initial-scale=1.0,viewport-fit=cover">
 
 
 
 
 
 
 | 
解决移动端设置放大字体,导致页面也被放大显示不全
| 12
 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 文件的绝对路径。| 12
 3
 4
 5
 6
 
 | module.exports = {
 sass: {
 resource: path.resolve(__dirname, '..', 'src/styles/variable.scss'),
 },
 }
 
 |  
 
 当只有 resource 字段时,也可以传入一个路径数组。| 12
 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里滑动弹层禁止弹层下面的页面滚动
| 12
 3
 4
 5
 6
 7
 
 | const touchMove = (e) => {e.preventDefault()
 }
 <View catchMove={true} onTouchMove={(e) => touchMove(e)}>
 
 </View>
 
 
 |