跳到主要内容

taro

taro原理​

  • 1、语法转换, 底层会将这些语法转换为各个端所支持的语法
  • 2、定制api标准化, 对各个端的 API 进行了封装,提供了一致的 API 接口
  • 3、虚拟DOM,可以更好的进行跨平台渲染对对应的组件

Taro 是一个跨端开发框架,其原理可以分为以下几个方面:

  1. 语法转换:Taro 支持使用类 React 语法进行开发,但是其底层会将这些语法转换为各个端所支持的语法。例如,对于小程序端,Taro 会将 JSX 转换为小程序模板语言 WXML,将 CSS 转换为小程序样式文件 WXSS。

Taro 在开发过程中,会先将使用类 React 语法编写的代码进行解析和转换,转换成对应端所支持的代码。对于小程序端,Taro 会将 JSX 转换为 WXML,将 CSS 转换为 WXSS,将 JavaScript 转换为小程序所支持的 JavaScript。这个过程主要使用了类似 Babel 的语法转换工具进行转换。

  1. API 封装:Taro 对各个端的 API 进行了封装,提供了一致的 API 接口,开发者无需了解每个端的具体实现细节,可以通过 Taro 提供的 API 接口来调用对应端的功能。

Taro 为了让开发者可以在不同端上调用相同的 API,对各个端的 API 进行了封装。例如,Taro 提供了 Taro.navigateTo 函数来跳转到下一个页面,这个函数在小程序端会调用 wx.navigateTo,在 H5 端会调用 window.location.href,在其他端会调用相应的 API。

  1. 虚拟 DOM:Taro 使用了虚拟 DOM 的概念来进行跨端渲染,将 React 组件在各个端进行渲染时,先将组件转换为一棵虚拟 DOM 树,再根据具体端的渲染规则将其渲染为对应端的组件。

Taro 在跨端渲染过程中,会先将 React 组件转换为一棵虚拟 DOM 树,再根据各个端的实际渲染规则将其渲染为对应端的组件。这个过程使用了虚拟 DOM 的概念,可以避免直接操作 DOM 带来的性能问题

  1. 打包构建:Taro 通过类似 Webpack 的打包构建方式,将各个端的代码打包为对应端的代码,并且提供了一些优化方式,例如 tree shaking、code splitting 等,可以减小包体积,提高应用性能。

Taro 在构建过程中,会将各个端的代码打包为对应端的代码,并且提供了一些优化方式,例如 tree shaking、code splitting 等,可以减小包体积,提高应用性能。在打包构建时,Taro 会根据开发者所选择的端来选择对应的构建工具进行构建。例如,对于小程序端,Taro 会使用微信小程序原生的构建工具进行构建,而对于 H5 端,Taro 则会使用 Webpack 进行构建。

taro2和taro3的区别​

Taro 2 和 Taro 3 是同一个跨端开发框架 Taro 的不同版本,它们之间存在以下一些区别:

  1. React 版本:Taro 2 默认使用 React 16.x 版本,而 Taro 3 默认使用 React 17.x 版本。React 17.x 版本主要改进了事件系统和组件渲染,提高了应用程序的性能。
  2. 支持的平台:Taro 2 支持的平台包括微信小程序、百度智能小程序、支付宝小程序、QQ 小程序、京东小程序、快应用、H5 和 RN 等,而 Taro 3 新增了对字节跳动小程序和 QQ 轻应用的支持,同时去除了对快应用的支持。
  3. 构建工具:Taro 3 将 Taro CLI 的构建工具从 Webpack 替换为了 Vite,可以提供更快的构建速度和更好的开发体验。
  4. TypeScript 支持:Taro 3 对 TypeScript 的支持更加完善,提供了更好的类型推导和类型检查。
  5. 生命周期:Taro 3 增加了一些生命周期函数,例如 componentDidCatch 和 getSnapshotBeforeUpdate 等。

常用api​

环境判断​

  • Taro.getEnv(), Taro.ENV_TYPE
    • **Taro.getEnv()获取当前环境值,具体值如 **Taro.ENV_TYPE
    • 常用于判断h5以及小程序,根据环境来指定组件以及方法
text
Taro.ENV_TYPE.WEAPP 微信小程序环境
Taro.ENV_TYPE.WEB WEB(H5)环境
.....

参考资料

具备taro开发多端经验

taro​

配置​

  • defineConstants : 全局变量配置

config/index​

text
const config = {
  h5: {
   publicPath: process.env.NODE_ENV === "production" ? "./" : "/",
   staticDirectory: "static",
   output: {
     filename: "js/[name].[hash:8].js",
     chunkFilename: "js/[name].[chunkhash:8].js",
  },
   postcss: {
     autoprefixer: {
       enable: true,
       config: {
         overrideBrowserslist: [
           "last 3 versions",
           "Android >= 4.1",
           "ios >= 8",
        ],
      },
    },
     cssModules: {
       enable: false, // 默认为 false,如需使用 css modules 功能,则设为 true
       config: {
         namingPattern: "module", // 转换模式,取值为 global/module
         generateScopedName: "[name]__[local]___[hash:base64:5]",
      },
    },
  },
   miniCssExtractPluginOption: {
     filename: "[name].css",
     chunkFilename: "[name].css",
  },
   esnextModules: ["taro-ui", "@taroify"],
},
}

自定义tabbar​

  • h5不支持自定义tabbar,可在custom-tab-bar返回null,为了兼容h5和小程序,【这样就不会导致2个tabbar】,额外写一个自定义的tabbar组件在需要的页面引入
text
//隐藏tabbar
.taro-tabbar__tabbar-bottom {
  display: none;
}

问题

h5生产环境出现白屏

  • 在config/index.js配置
    • **配置publicPath为 **./
text
const config = {
   h5:{
       publickPath:process.env.NODE_ENV === 'production'?'./':'/'
  }
}

监听路由​

text
import Taro, { eventCenter } from '@tarojs/taro';
eventCenter.on("__taroRouterChange", ({ toLocation: { path } }) => {
 console.log("目标路由path:" + path);
});

携带参数跳转tabbar​

  • 注意以下方式会出现问题:
    • switchTab:需要跳转的 tabBar 页面的路径(需在 pages.json 的 tabBar 字段定义的页面),路径后****不能带参数
    • reLaunch
      • 需要跳转的应用内页面路径 , 路径后可以带参数。可以跳转到tabBar页面但是跳转到t****abBar页面拿不到传递的参数
    • navigateTo
      • 需要跳转的应用内****非 tabBar 的页面的路径 , 路径后可以带参数。** **注:页面跳转路径有层级限制,不能无限制跳转新页面

小程序页面栈最多十层!

解决方案:

  • 利用缓存,把跳转参数放到数据缓存中,setStorage

使用 H5 标签编写 Taro 应用​

Web 端沉淀了大量优秀的库和组件,希望能直接在小程序端进行复用,解放生成力

希望能减少 H5 应用迁移到小程序端的成本,甚至能够直接运行在小程序端。

配置插件:

  • @tarojs/plugin-html

实现索引选择器​

参考

思路:

  • 1、获取左侧每个列表区块的高度
  • 2、计算每个列表区块的高度区间
  • 3、在dom元素加载完,计算右侧每个索引导航的高度:
  • 4、在dom元素加载完,调用计算列表区块的高度区间的方法
  • 5、onScroll 监听左侧 ScrollView 组件纵向滚动的值 e.detail.scrollTop ,计算 e.detail.scrollTop 落在 DOMHeight 数据的哪个区间,获取索引值,设置右侧索引导航的高亮:
  • **6、右侧索引导航添加 **touchStart、touchMove 事件,监听并计算出在索引导航上移动的距离和移动了几个索引值

**获取 **DOM 元素的兼容方法:

  • H5、微信小程序 :Taro.createSelectorQuery()
  • **支付宝小程序 **my.createSelectorQuery()

小程序如何实现sessionStorage功能?​

  • 1、使用数据存储,在小程序退出后台的时候onHide,就清除变量
    • 使用storage(),在小程序App onHide()时或者App重新启动时,上使用clearStorage(),清除存储
  • 2、使用App中的globalData属性,作为一个全局变量缓存在App中,当App销毁时会自动垃圾回收

如何获取DOM节点?​

多端同步调试​

**可以在 dist 目录下创建一个与编译的目标平台名同名的目录,并将结果放在这个目录下,例如编译到微信小程序,最终结果是在 dist/weapp 目录下,这样做的好处是,各个平台使用独立的目录互不影响,从而达到多端同步调试的目的,在 **config/index.js 配置如下:

/config/index.js

text
outputRoot: `dist/${process.env.TARO_ENV}`

Input组件触发键盘事件​

通常输入框,输入完之后,希望通过按回车键/搜索键就能直接进行搜索

  • onKeyDown事件
    • event.detail.keyCode

键盘码:

  • 回车键: 13

收起键盘:

参考:https://segmentfault.com/a/1190000021622684

text
document.activeElement.blur()

自定义导航栏Navbar​

taro的导航栏,在微信浏览器可以看到每个页面的导航标题,但是在钉钉上打开h5,发现导航标题没有更新,刷新才会更新,所以只能自己自定义导航栏了。。

  • 1、在components文件夹定义Navbar导航组件
  • 2、在需要的页面引入

小程序​

注意事项​

  • Text不能嵌套View可能会有问题,用View嵌套View即可

开发小程序准备工作​

  • 1、申请账号,微信公众平台注册一个账号,因为无论是前期的开发,还是后期的发布、运营都需要使用到这个账号
  • 2、获取AppID和Secrect,并获取token及存储刷新token
  • 3、域名配置

appid按环境自动切换​

微信的appid在正式环境和测试环境不同,需要手动切换appid,比较容易出错。最好实现执行指令的时候直接自动处理

  • 利用cross-env

Taro打包小程序体积优化​

  • optimizeMainPackage:优化主包的体积大小

自定义hooks​

useHeight​

  • 获取高度,用于动态获取高度
    • 可用于赋值给ScrollView组件来指定高度
text
import { useRef, useEffect, useState } from 'react';
import Taro from '@tarojs/taro';
import { forEach, sumBy, map } from 'lodash-es';

// 获取高度,【用于动态高度来兼容不同设备】
export default function useHeight(domList = []) {
 const query = Taro.createSelectorQuery();
 const { windowHeight } = Taro.getSystemInfoSync();
 const [heightMap, setHeightMap] = useState({});
 const restHeight = useRef(0);
 useEffect(() => {
   Taro.nextTick(() => {
     forEach(domList, (item, index) => {
       query
        .select(item)
        .boundingClientRect(res => {
           setHeightMap(state => ({ ...state, [item]: res.height }));
        })
        .exec();
    });
  });
}, []);

 useEffect(() => {
   restHeight.current = windowHeight - sumBy(map(heightMap));
}, [heightMap, windowHeight]);

 return {
   heightMap,
   restHeight: restHeight.current, //页面剩余高度
   windowHeight
};
}

接入腾讯有数无痕埋点能​

腾讯有数无痕: 全自动埋点 【 全自动埋点则是不管需不需要,将所有的点都埋了】

腾讯和 Taro 团队共同推出 腾讯有数自动化埋点,接入超级简单。比如配置 proxyPage 为 true 即可 “上报所有页面的 browse 、leave、share 等事件”,配置 autoTrack 为 true 即可 “自动上报所有元素的 tap、change、longpress、confirm 事件

h5:文档:https://mp.zhls.qq.com/youshu-docs/develop/sdk/es6.html

  • 安装SDK

taro小程序生命周期​

  • componentDidShow | useDidShow
    • 组件展示出来时触发,与原生小程序的 onShow 生命周期相对应。
  • componentDidHide | useDidHide
    • 组件被隐藏时触发,与原生小程序的 onHide 生命周期相对应
  • onUnload | useUnload
    • 在小程序环境中对应页面的 onUnload。

问题总结​

1、移动端表格问题​

在移动端中很少有表格方案由于场景比较少,组件库也没有提供,尤其在taro多端的,需要兼容H5和小程序,可以自己写一个table

2、esnextModules​

配置需要额外的编译的源码模块,比如 taro-usi:

  • 让taro去通过postcss编译处理 taro-ui 模块
  • **配置之后,代码中引入的处于 **node_modules/taro-ui/ 路径下的样式文件均会经过 postcss 的编译处理

3、下拉刷新/上拉加载问题​

注意:

  • ScrollView的下拉刷新只支持微信小程序
    • onRefresherPulling、onRefresherRefresh、onRefresherRestore等下拉相关api都只在小程序有效,h5不支持
  • ScrollView的上拉加载,onScrollToLower回调事件的支持度

3、在弹出层中,usePageScroll不触发​

  • 如果要触发滚动事件,可在弹出层里面使用ScrollView组件的onScroll事件

4、弹出层,popup出现抖动,可把动画去掉

4、ios 低版本 出现 Cant find variable: globalThis​

  • 参考:https://blog.csdn.net/weixin_44176432/article/details/117257826

  • 解决方法:

    • 1、在html文件引入
    text
    <script src="https://unpkg.com/@ungap/global-this@0.4.4/min.js"></script>
    • 或在html引入script脚本
    text
    <script>
    //兼容低版本ios
       !function(t){function e(){var e=this||self;e.globalThis=e,delete t.prototype._T_}"object"!=typeof globalThis&&(this?e():(t.defineProperty(t.prototype,"_T_",{configurable:!0,get:e}),_T_))}(Object);
    </script>

5、解决 ios10 及以上 Safari 无法禁止缩放的问题​

text
<script>
     window.onload = function () {
       var isIOS = navigator.userAgent.match(/(iPhone\sOS)\s([\d_]+)/);
       if (isIOS) {
         document.addEventListener("touchstart", function (event) {
           if (event.touches.length > 1) {
             event.preventDefault();
          }
        });
         var lastTouchEnd = 0;
         document.addEventListener(
           "touchend",
           function (event) {
             var now = new Date().getTime();
             if (now - lastTouchEnd <= 300) {
               event.preventDefault();
            }
             lastTouchEnd = now;
          },
           false
        );
         document.addEventListener("gesturestart", function (event) {
           event.preventDefault();
        });
      }
    };
     let _ENV = window.location.host;
     console.log(_ENV);
     // 非生产环境,额显示调试窗口
     // if (_ENV !== 'minishop.by-health.com') {
     //   const vconsole = new VConsole();
     // }
   </script>

6、底部tabbar切换,不刷新问题​

  • 使用onShow/useDidShow

7、taro3 使用formType='submit'可能会有兼容问题​

  • 解决方式: 使用onClick, 建议不要使用Button的formType

8、样式加载问题,部分浏览器,加载不完整​

  • 可能由于缓存问题,清一下缓存

9、首页样式无法加载​

  • 首页样式,可以放在app.js引入来解决

10、缓存问题太严重,无法看到最新页面​

参考:https://www.jianshu.com/p/1672ba03acb4

问题:​

我们每次发布H5更新的时候总会遇到这样的问题,用户在微信中看到的H5页面是没有改动过的,但是我们明明已经更新了H5,只能清理缓存才能看到最新的修改。

原因:​

因为微信官方的web-view 是会缓存页面静态资源的比如:js、css、图片等,优先显示的缓存中的资源,过一段时间(时间不定,一天或者几小时,无明显规律)是可以自动进行缓存清除的,但是对于当时用户来说想要第一时间就看到正确的页面。

text
const config = {
 ...
 h5: {
   publicPath: '/',
   staticDirectory: 'static',
   output: {
     filename: 'js/[name].[hash].js',
     chunkFilename: 'js/[name].[chunkhash].js'
  },
   imageUrlLoaderOption: {
     limit: 5000,
     name: 'static/images/[name].[hash].[ext]'
  },
   miniCssExtractPluginOption: {
     filename: 'css/[name].[hash].css',
     chunkFilename: 'css/[name].[chunkhash].css',
  },
   ...
},
}

静态文件的目录,然后每次通过 npm run build:h5命令打包程序的时候,会自动将静态资源文件后面追加hash数值,这样静态文件发生变化的时候会生成新的hash值,这样每次发包的静态文件路径就是不同的了,所以升级版本就避免了缓存的问题

  • 静态文件发生变化了,这样浏览器就不会去请求缓存的资源了

11、安卓手机加载报错: 'super' keyword unexpected here​

  • **看看报错信息是出自那个文件,哪里有 **super 关键词
  • super关键词可能没有被编译,可以使用babel进行转换。或者修改代码把super去掉

12、尺寸单位问题​

  • **在 Taro 中尺寸单位建议使用 **px、 百分比 %,Taro 默认会对所有单位进行转换
  • **即从设计稿上量的长度 **100px,那么尺寸书写就是 100px,当转成微信小程序的时候,尺寸将默认转换为 100rpx,当转成 H5 时将默认转换为以 rem 为单位的值

rpx单位是微信小程序中css的尺寸单位,rpx可以根据屏幕宽度进行自适应

1rpx = 0.5px = 1物理像素

**Taro 会帮你对样式做尺寸转换操作,但是如果是在 JS 中书写了行内样式,那么编译时就无法做替换了,针对这种情况,Taro 提供了 API **Taro.pxTransform 来做运行时的尺寸转换

注意:

  • pxTransform 是根据设备的宽度进行转换,如果要计算高度的话用pxTransform会出现问题,在h5端,高度的话可用px解决

13、h5和小程序高度沾满的问题​

h5中:

  • body,html{height:100%};将body和html设置为100%,这样我们就可以在他们的子元素中使用height:100%来使的我们的容器元素占满屏幕的高度

小程序中:

  • 小程序没用dom对象,通过调试发现小程序的根节点是page, 那么将page的高度设置height:100%即可
text
//h5
body,html{height:100%}
//小程序
page{height:100%}

14、小程序不存在root根元素,如何动态改变css变量​

  • 小程序不存在root根元素,如果需要动态改变css变量,
    • **小程序只能在 **page 根元素里覆盖 CSS 变量。
text
// h5
:root {
   --primary-color: #ff4847;
   --loading-color:#ff4847;
}
// 小程序
page{
   --primary-color: #ff4847;
   --loading-color:#ff4847;
}

15、h5在钉钉导航标题问题​

text
//如果是钉钉平台,修改钉钉标题
    if (dd.env.platform != 'notInDingTalk') {
      //根据iOS的设计规范,iOS的标题在导航栏正中央。根据Android的设计规范,标题显示在导航栏左侧
      dd.ready(() => {
        dd.biz.navigation.setTitle({title:'标题'})
      })
    }

16、ScrollView在ios滚动加载数据,出现闪烁问题​

  • 利用scrollview组件,在下拉加载数据时候,在ios设备会出现闪烁问题

可能产生原因:

  • 1、组件里嵌套子组件,这个子组件直接写在了父组件里,这写法可能会出现兼容问题。在安卓是没有问题的
    • 建议:子组件写在另外文件里,通过导入方式来加载组件,不要直接写在父组件里包裹

17、获取屏幕高度 【100vh在ios兼容问题】​

  • 由于100vh在ios的safari上有问题,因为100vh 在safari和chrome浏览器中,100vh是指去掉地址栏和工具的高度,所以会出现滚动条
  • 可以使用window.innerHeight来替代100vh
    • 由于是跨端,为了兼容H5和小程序可以使用Taro.getSystemInfoSync()

18、小程序使用scroll-view中使用sticky吸顶问题​

参考:https://developers.weixin.qq.com/community/develop/article/doc/000202ebeb046859fc99548c756813

text
<ScrollView scrollY style={{height:'400px'}}>
   <View style="position: sticky"> 1 </View>
   <View> 2</View>
</ScrollView>

因为平台scroll-view的特性问题,sticky元素在离开了原定的scroll-view的height距离后,就不能识别scroll-view的距顶高度了,所以用一个无样式的view撑开整个scroll-view中元素的高度,让这个view以能够替代scroll-view被获取高度,从而达到样式正常

解决:

text
<ScrollView scrollY style={{height:'400px'}}>
   <View>
       <View style="position: sticky"> 1 </View>
       <View> 2</View>
   </View>
</ScrollView>

19、小程序的windowHeight的高度包不包括tabBar高度的问题​

  • Android系统,windowHeight包含tabBar的高度
  • iOS系统, windowHeight不包括tabBar的高度

20、小程序tabbar的icon图片限制大小问题​

  • icon 大小限制为40kb,建议尺寸为 81px * 81px,不支持网络图片

21、微信浏览器iphone,底部tabbar横线适配​

在钉钉打开h5,底部tabbar没有问题,在钉钉自动适配了,在微信浏览器需要自己去适配

通过css去设置:

viewport-fit-descriptor env() 和 constant() iOS11 新增特性,Webkit 的一个 CSS 函数,用于设定安全区域与边界的距离,有四个预定义的变量:

text
padding-bottom: constant(safe-area-inset-bottom);
padding-bottom: env(safe-area-inset-bottom);

第一步:设置网页在可视窗口的布局方式 新增 viweport-fit 属性,使得页面内容完全覆盖整个窗口:

H5网页设置viewport-fit=cover的时候才生效,小程序里的viewport-fit默认是cover

text
<meta name="viewport" content="width=device-width, viewport-fit=cover">

js如何获取底部安全区域是多少?

  • 利用css变量

env()和constant(),是IOS11新增特性,Webkit的css函数,用于设定安全区域与边界的距离,有4个预定义变量:

  • safe-area-inset-left:安全区域距离左边边界的距离
  • safe-area-inset-right:安全区域距离右边边界的距离
  • safe-area-inset-top:安全区域距离顶部边界的距离
  • safe-area-inset-bottom :安全距离底部边界的距离

constant:兼容 IOS<11.2

env: 兼容 IOS>11.2

text
:root {
  // iOS < 11.2
   --sat: constant(safe-area-inset-top);
   --sar: constant(safe-area-inset-right);
   --sab: constant(safe-area-inset-bottom);
   --sal: constant(safe-area-inset-left);
  // iOS >= 11.2
   --sat: env(safe-area-inset-top);
   --sar: env(safe-area-inset-right);
   --sab: env(safe-area-inset-bottom);
   --sal: env(safe-area-inset-left);
}

在JavaScript中,通过以下方法,读取到css自定义变量

  • 注意:返回的是带有px单位的
text
getComputedStyle(document.documentElement).getPropertyValue("--sat")

22、node-sass问题【使用dart-sass替换】​

  • taro已经从node-sass替换成dart-sass了
  • taro对sass默认使用dart-sass,只需要安装sass即可

dart-sass是node-sass的替代品

Dart Sass 是 Sass 的主要实现,这意味着它在其他实现之前先获得了新功能,它快速,易于安装,并且可以编译为纯 JavaScript,从而可以轻松集成到现代 Web 开发工作流中。

Sass 官方目前主力推 dart-sass,最新的特性都会在这个上面先实现。

23、taro打包出来体积大,如何优化?​

小程序编译优化指南

24、useReady/onReady使用问题​

  • useReady 只能用于最顶层的页面组件中。在子组件中不会调用。

https://github.com/NervJS/taro/issues/7879