前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >第二十一期:基于Taro的多端(小程序+H5)开发实践

第二十一期:基于Taro的多端(小程序+H5)开发实践

作者头像
terrence386
发布2022-07-15 10:05:36
3.4K0
发布2022-07-15 10:05:36
举报

背景

通过一套代码,一套业务代码,构建成不同的端(H5/小程序),满足代理人平台多端的业务场景,并为接下来的要开发的项目积累经验。

多端开发方式

  • 混合开发 cordova/uniapp
  • 原生体验开发 flutter/react-native
  • 优缺点 优点:可以快速开发跨ios和andriod两端的应用。降低开发成本 缺点:无法适配小程序端。

Taro相比之下的优势

  • 跨框架

可以同时支持 vue/react/nerv 等框架

  • 跨端

可以编译成不同的端形式。H5/小程序/RN

需要注意的H5和小程序的区别

H5和小程序的运行环境有本质上的差别,导致两者在很多方面有不同的地方。

H5主要与运行在浏览器及web-view的浏览器环境。简单来说,浏览器环境主要有window对象,Bom, Dom 等API构成,同时可操作的系统API不多,这里的系统API比如: 拍照,图片上传,位置服务等等。

小程序主要运行在以微信为代表的平台环境中。平台环境提供了一套能够操作系统权限的API,同时由于小程序架构的特点,小程序的js运行在平台封装的jsCore中,并没有一个完整浏览器对象,因而缺少浏览器中相应的Dom 及Bom操作。

另外,H5的渲染机制和小程序也有所不同。H5的js和dom是在一个线程中同时进行,小程序则分了渲染层和逻辑层两个线程,两个线程通过原生的消息机制进行通信。渲染层在IOS中使用【WKWebView】进行渲染,在Android中使用【chromium定制内核】进行渲染。

因此,在开发过程中对这些差异有所了解,能够预判这些差异给我们带来的影响。这些差异主要有以下几点:

  • 客户端环境
  • 运行机制
  • 系统权限
  • 更新机制
  • 其他

客户端环境

H5的宿主环境是浏览器以及web-view中的浏览器环境。

小程序的宿主环境是特定的应用平台(微信/支付宝...)。

导致小程序脚本中无法使用浏览器常用的window对象及dom,bom相关的api,以及两者的缓存机制略有不同,H5可以使用cookie进行设置,小程序虽然有Storage但是没有cookie。所以,在使用Taro进行开发时,需要注意以下问题:

  • 客户端运行宿主环境判断
  • 登录流程的控制
客户端运行环境判断

以往基于H5的移动端开发时,通常时用navigator.userAgent这个API来获取浏览器信息,判断是ios/android/浏览器。

代码语言:javascript
复制
let browser={
    versions:function(){
        var u = navigator.userAgent, app = navigator.appVersion;
        return {
            trident: u.indexOf('Trident') > -1, //IE内核
            presto: u.indexOf('Presto') > -1, //opera内核
            webKit: u.indexOf('AppleWebKit') > -1, //苹果、谷歌内核
            gecko: u.indexOf('Gecko') > -1 && u.indexOf('KHTML') == -1,//火狐内核
            mobile: !!u.match(/AppleWebKit.*Mobile.*/), //是否为移动终端
            ios: !!u.match(/(i[^;]+;( U;)? CPU.+Mac OS X/), //ios终端
            android: u.indexOf('Android') > -1 || u.indexOf('Adr') > -1, //android终端
            iPhone: u.indexOf('iPhone') > -1 , //是否为iPhone或者QQHD浏览器
            iPad: u.indexOf('iPad') > -1, //是否iPad
            webApp: u.indexOf('Safari') == -1, //是否web应该程序,没有头部与底部
            weixin: u.indexOf('MicroMessenger') > -1, //是否微信 (2015-01-22新增)
            qq: u.match(/sQQ/i) == " qq" //是否QQ
        };
    }(),
    language:(navigator.browserLanguage || navigator.language).toLowerCase()
}

但是在Taro中,Taro提供了getEnv()方法,可以直接获取所在端信息。比如:

代码语言:javascript
复制
const isWeb = Taro.getEnv() === 'WEB'
const isWeapp = Taro.getEnv() === 'WEAPP'
登录流程的控制

小程序的登录机制是,wx.login获取code传给服务端, 服务端接收code同时调用微信的凭证校验接口,微信服务返回seccion_key/openid给服务端,服务端根据返回的信息生成一个token返给前端,前端缓存token,以后的每次请求都写到请求头中。

H5的登录情况有两种,一种是调用login接口后,服务端根据接受到的用户信息生成token/cookie返回给前端,前端缓存后,每次请求都写到请求头中。另外一种是服务端直接设置cookie。

注意:本次开发时,H5的登录是由服务端直接设置cookie, 在测试环境调试的时候需要手动将cookie设置到对应的域名下。同时小程序的登录用了中台的登录插件,登录成功后可以直接使用回调函数

代码语言:javascript
复制
plugin.loginSuccess((data)=>{
 // 登录成功后的操作
  ...
})

假设小程序登录不用插件,H5登录也不是服务端直接设置cookie,那么可以做如下封装:

代码语言:javascript
复制
const loginMethods = {
 WEB:()=>{
   // h5登录流程
    ...
  },
  WEAPP:()=>{
   // 小程序登录流程
    ...
  }
}
  const currentEnv = Taro.getEnv()
  
  // 执行登录方法
  loginMethods[currentEnv]()
运行机制

H5的运行机制/运行过程通常是加载Dom树,加载渲染树Css,绘制页面这样一个过程。

小小程序的运行机制分为热启动和冷启动。【热启动】:如果用户已经打开过某小程序,在一定时间内再次打开该小程序,此时无需重新启动,只需将后台态的小程序切换到前台。【冷启动】: 如果用户首次打开或小程序被微信主动销毁后再次打开的情况,此时小程序需要重新加载启动。

这里对我们造成的影响主要是:【数据请求时机】。

数据请求时机

H5的请求通常在document.ready即可调用。vue框架在created()函数中,react在componentDidMount()中。

小程的热启动在调用数据请求时可能会遇到以下问题:小程序的onShow函数,页面每次展示时都会请求数据,如果请求的数据是列表。手机息屏,重新点亮屏幕会出现重复数据,需要对这个现象进行处理。

系统权限

小程序可以直接调用系统的【保存图片】【拍照】【音频】【位置】【转发】等权限。H5则无法直接获取这写权限。这里的差异主要表现在:

  • 交互效果
分享转发

小程序可以直接使用wx.shareAppMessage方法及<button type="share">调起分享。H5则需要借助jsBridage进行实现。

小程序的实现

代码语言:javascript
复制
// 小程序的转发
page({
 data:{},
  // 分享
  onShareAppMessage(){
   return {
      title: "转发的标题",        // 默认是小程序的名称(可以写slogan等)
    path: '/pages/share/share',        // 默认是当前页面,必须是以‘/’开头的完整路径
    imageUrl: '',     //自定义图片路径,可以是本地文件路径、代码包文件路径或者网络图片路径,支持PNG及JPG,不传入 imageUrl 则使用默认截图。显示图片长宽比是 5:4
    success: function(res){
      // 转发成功之后的回调
    },
    fail: function(){
      
    },
    complete: fucntion(){
      // 转发结束之后的回调(转发成不成功都会执行)
    }
    }
  }
})
代码语言:javascript
复制
// H5 的实现需要  导入JsBridge中的Api
  import { InviteFriendDesc, PromotionShareDesc, shareInJrApp } from '@src/utils/jsbridge';
  
  // 调用Api
   shareInJrApp(
      `url`,
      cardText || PromotionShareDesc,
      cardUrl,
      shortUrl,
      shareImg,
    );
上传图片
  • 小程序上传图片及图片预览可以直接调用相应的Api从相册中获取图片进行上传。
  • H5则需要特定的上传组件,或借用jsBridge使用原生应用的能力。
更新机制

小程序每次 【冷启动】时,都会检查有无更新版本,如果发现有新版本,会异步下载新版本代码包,并同时用客户端本地包进行启动,所以新版本的小程序需要等下一次 冷启动 才会应用上,当然微信也有wx.getUpdateManager 可以做检查更新。这个对我们的影响主要在发布项目的过程。

发布项目

H5打包后可以直接发布实时更新。小程序需要打包后上传到小程序后台进行审核后,才能正常发布。

其他开发过程中需要注意的问题

除了以上列举的差异外,还有几个问题需要注意。

  • 组件化
  • 多端组件
  • 接入中台服务
  • 开发调试
  • 代码优化
组件化开发

前端项目基本上都采用组件化开发的形式。组件化开发的优势明显,将复杂业务逻辑拆分,解耦。组件内逻辑清晰。可以复用性强。同时便于后期维护。

多端组件

组件的封装过程中可能遇到不同端展示的效果不一致。这时候可以用环境判断进行相应的布局。

代码语言:javascript
复制
// 多端组件
renderName(){
 const {name,role} = props
  return (
    <View className="nickName">
     <View>{name}<View>
    {Taro.getEnv()==='WEAPP'?null:<View className="role">{role}<View>}
    </View>
}

虽然Taro提供了根据文件后缀名编译不同端页面的能力,但是基于组件进行开发,就没必要创建那么多不同后缀名的文件了。

接入中台服务

接入流程一般是: 申请业务ID-->服务提供方开发排期-->双方联调测试-->服务提供方发布生产。

沟通成本略高,不可控因素较多【开发环境】【测试环境】...

开发调试

H5使用【vconsole】,小程序使用【微信开发者工具】

代码优化
  • 设计模式【策略】【迭代器】...
代码语言:javascript
复制
// 上传文件
// 例如上传文件

const uploadH5 = () => {...}

const uploadWx = () => {...}

const uploadNative () => {...}

export const uploadFile = () => {
  let uploadlist = [uploadH5,uploadWx,uploadNative]
  for(let i in uploadList){
    let success = uploadList[i]()
    if(success){
      return 'upload success'
    }
  }
}
复用代码

某些代码需要多处用到,则可以将之封装起来,甚至直接添加到全局对象上或者Taro的实例上。比如实名状态判断

其他扩展

  • 跨框架组件
  • 开发真正的跨端组件

虽然Taro支持将代码打包成不同的端,同时也有相应的trao-ui组件库,但是该UI库目前只支持react框架,假如我们使用vue进行迭代,则需要引入基于vue的另一个组件库。同时目前的Taro-UI不支持ReactNative。

有没有什么方法,可以同时兼容两种框架?有没有什么方法可以同时支持ReactNative? 简单介绍下 web-componentstyled-component

web-component

web-component是一种自定义可重用元素的技术。其主要概念有以下三个:

  • 自定义元素
  • temlate / slot 模板和插槽
  • shadow Dom
自定义元素

我们可以使用customElements.define()方法,自定义一个元素。该方法接受两个参数:

  • 自定义的元素名称 自定义元素名称需要用连字符 - 进行连接
  • 一个用于定义元素行为的类
  • 一个可选参数,个包含 extends 属性的配置对象,是可选参数。它指定了所创建的元素继承自哪个内置元素,可以继承任何内置元素。

自定义元素示例:

代码语言:javascript
复制
class MyButton extend HTMLElement {
 // ....
}
// 注册自定义元素
customElements.define('my-button', HTMLElement);

// 使用自定义元素 和 平时写html一样

<div>
 <my-button></my-button>
</div>
Shadow Dom

Shadow Dom的主要作用是将标记结构、样式和行为隐藏起来,并与页面上的其他代码相隔离,保证不同的部分不会混在一起,可使代码更加干净、整洁。

Shadow DOM 不是一个新事物——在过去的很长一段时间里,浏览器用它来封装一些元素的内部结构。以一个有着默认播放控制按钮的 <video> 元素为例。你所能看到的只是一个 <video> 标签,实际上,在它的 Shadow DOM 中,包含来一系列的按钮和其他控制器。Shadow DOM 标准允许你为你自己的元素(custom element)维护一组 Shadow DOM。

Shadow Dom有以下几个重要的概念:

  • shadow host : 一个常规 DOM节点,Shadow DOM 会被附加到这个节点上。
  • Shadow tree:Shadow DOM内部的DOM树。
  • Shadow root: Shadow tree的根节点。

我们可以使用 Element.attachShadow() 方法来将一个 shadow root 附加到任何一个元素上。它接受一个配置对象作为参数,该对象有一个 mode 属性,值可以是 open 或者 closed:open 表示可以通过页面内的 JavaScript 方法来获取 Shadow DOM。

同时,可以使用模板字符串给shadow dom 添加样式。这里有几个伪类选择器

  • :host 表示当前shadow dom的宿主节点
  • : slotted 表示插槽内容中的dom节点
代码语言:javascript
复制
// web-components写法  换成图片
// footer 页脚
// 布局容器
const layout = `
<style>
    :host{
        display:flex;
        flex-direction: column;
        height:100%;
        background: #f0f2f5;
    }
    ::slotted(app-layout.inner){
        flex-direction: row;
    }
    ::slotted(app-content){
        height:100%;
    }
    ::slotted(app-sider){
        width:200px;
        flex-direction:column;
    }
    ::slotted(app-footer){
        width:100%;
        height:64px;
        background:#fff;
    }
</style>

class AppFooter extends HTMLElement {
    constructor() {
        super();
        const shadowRoot = this.attachShadow({ mode: 'open' });
        shadowRoot.innerHTML = `
        ${layoutStyle.footer}
        <slot></slot>
        `
    }

    connectedCallback() {
       
    }

    attributeChangedCallback (name, oldValue, newValue) {
       
    }
}

styled-component

简单介绍下如何使用styled-component

组件时代的视觉原语。

Use the best bits of ES6 and CSS to style your apps without stress 💅🏾

它可以让我们毫无压力的使用ES6和CSS中最好的部分来设计应用程序。

创建附带样式的组件(react)
代码语言:javascript
复制
const Title = styled.h1`
  font-size: 1.5em;
  text-align: center;
  color: palevioletred;
`;

// Create a Wrapper component that'll render a <section> tag with some styles
const Wrapper = styled.section`
  padding: 4em;
  background: papayawhip;
`;

// Use Title and Wrapper like any other React component – except they're styled!
render(
  <Wrapper>
    <Title>
      Hello World!
    </Title>
  </Wrapper>
);
基于Props的适配

可以将函数(“插值”)传递给已设置样式的组件的模板文本,以便根据其属性对其进行调整。

比如下面的组件可以更改其颜色的主状态。当将primary为true时,将切换其背景和文本颜色。

扩展样式

有时候我们需要多次使用某个组件,但样式不一定一样,这时候我们只需要将原有的组件用styled函数包装一下,就可以实现。

除此之外,还可以用as将组件A的特性表现为组件B的特性

props的传递

如果styled方法接受的目标是一个简单的html元素,styled-component会将与之对应的属性传递给它,如果目标是一个自定义的组件,那么会将我们定义的props传给它。

支持React Native

styled-components 可以用相同的写法同步React Native

这里引入的styled.View应该是对react-native的组件或者meterial-UI做了一层转化或者封装。

总结

了解了H5和小程序的差异以后,基于已有的设计规范使用web-component及styled-components可发一套框架依赖底,写出能够适配ReactNative的UI库是可行的。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-10-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 JavaScript高级程序设计 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 背景
  • 多端开发方式
  • Taro相比之下的优势
  • 需要注意的H5和小程序的区别
  • 客户端环境
    • 客户端运行环境判断
      • 登录流程的控制
        • 运行机制
          • 数据请求时机
            • 系统权限
              • 分享转发
              • 上传图片
              • 更新机制
              • 发布项目
          • 其他开发过程中需要注意的问题
            • 组件化开发
              • 多端组件
                • 接入中台服务
                  • 开发调试
                    • 代码优化
                      • 复用代码
                      • 其他扩展
                        • web-component
                          • 自定义元素
                            • Shadow Dom
                            • styled-component
                              • 创建附带样式的组件(react)
                                • 基于Props的适配
                                  • 扩展样式
                                    • props的传递
                                      • 支持React Native
                                      • 总结
                                      相关产品与服务
                                      云开发 CloudBase
                                      云开发(Tencent CloudBase,TCB)是腾讯云提供的云原生一体化开发环境和工具平台,为200万+企业和开发者提供高可用、自动弹性扩缩的后端云服务,可用于云端一体化开发多种端应用(小程序、公众号、Web 应用等),避免了应用开发过程中繁琐的服务器搭建及运维,开发者可以专注于业务逻辑的实现,开发门槛更低,效率更高。
                                      领券
                                      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档