Hybrid簡介

現在的中大型app中,為了滿足快速迭代以及動態更新的需求,就往往需要使用混合架構,來達到動態更新的目的。這里就來簡單介紹下目前比較主流的混合框架及其優劣。

目前的框架我大致將他歸為為3種:

  • X-native
  • web-native
  • template / DSL

X-native

這個目前最具有代表性的就是js-native了,還有一些像lua-native等,由于很久沒有人維護了,就不做介紹了。

自從前端框架出現了virtual dom這個技術,就給我們的native化創造了先決條件,下面的技術都是根據virtual dom來驅動的。

react-native

這是一個非常熱門的項目了,貢獻者就達到了1.4k,是其他項目無法比擬的,可以說是目前世界上最熱門的項目之一了。

功能強大,可以說項目本身就基本包含了所有app功能。你可以不用寫一行native代碼,就能寫一整個應用。也可以單獨去渲染部分頁面,非常靈活。作為一個需要快速迭代和動態更新的頁面,往往也不需要特別高的交互性,所以單純的展示已經足夠了,react-native本身所提供的功能其實已經遠大于渲染一個頁面了。目前我嘗試下來也沒遇到什么坑。

正因為熱門,所以社區支持非常完善,遇到什么問題,google、Stack Overflow上都有答案。所以不用擔心遇到什么無法解決的問題。文檔和例子也非常完善,有大量優秀的開源組件支持,很多功能都被封裝為單獨的組件,不需要自己去重新寫了。

debug功能非常強大,而且非常好用。而且有非常多第三方的debug tools。比如專門對redux的react-dev-tools。

但是react本身就是一個非常大的話題,需要一定的學習成本。同時react-native的目標并不是統一多平臺實現,而是把多平臺實現轉化到react,所以難以只寫一份代碼就能兼容所有平臺,所以還是需要很多的兼容代碼。這樣就需要寫代碼的人對多平臺都有所了解,同時又要理解前端技術,可以說這樣的人才其實還是很少的。當然,如果只是寫比較簡單的頁面,使用各平臺通用的一些組件,還是比較簡單的。

這里就有一個例子,之后也會用這個列子來驗證:

react-1.png
react-2.png

這里的圖片是動態顯示的,有才會顯示。布局如下

 ------------------
| Title    |       |
| SubTitle | Image |
 ------------------
| name             |
 ------------------

實現如下:

import React from 'react'
import {
  View, Text, Image, StyleSheet
} from 'react-native'
import Sep from './seperator'

export default class Answer extends React.Component {
  render() {
    let {data} = this.props
    return (
      <View style={style.container}>
        <View style={style.content}>
          <View style={style.textContent}>
            <Text style={style.title} numberOfLines={2}>{data.question.title}</Text>
            <Text style={style.subTitle} numberOfLines={3}>{data.description}</Text>
          </View>
          {
            data.images && data.images.length &&
            <Image style={style.image} source={{uri: data.images[0]}} />
          }
        </View>
        <View style={style.textSep}></View>
        <Text style={style.nickName}>{data.author.nickname}</Text>
        <Sep style={style.sep}/>
      </View>
    )
  }
}

let style = StyleSheet.create({
  container: {
    marginLeft: 20,
    marginRight: 20,
    alignItems: 'stretch'
  },
  content: {
    marginTop: 20,
    width: '100%',
    flexDirection: 'row'
  },
  textContent: {
    flexDirection: 'column',
    flexShrink: 1
  },
  image: {
    marginLeft: 10,
    width: 100,
    borderRadius: 2,
    aspectRatio: 1
  },
  textSep: {
    height: 1,
    width: 20,
    backgroundColor: '#ccc',
    marginTop: 10
  },
  title:{
    fontSize: 16,
    lineHeight: 20,
    fontWeight: '600',
    marginTop: 0
  },
  subTitle: {
    marginTop: 8,
    fontSize: 13,
    lineHeight: 17,
    color: '#999'
  },
  nickName: {
    marginTop: 14,
    fontSize: 12,
    color: '#999'
  },
  sep: {
    marginTop: 20
  }
})

在使用下來,沒有任何的問題,不論布局還是元素內容。由于使用的是js和jsx,和前端的編碼非常類似,所以如果從前端轉過來的學習成本會非常低。同時css布局使用的是flex,幾乎完全兼容web端的布局方式。

官方的debug工具:

ReactDevToolsInspector.gif

weex

現在來看下非常相似的weex,由阿里出品。號稱能多平臺使用一份代碼。那么真實情況是怎么樣的呢?我也去嘗試了下。

weex使用的是vue框架,所以更像web的編碼方式,所以學習成本會低一些。

weex的文檔也比較完整,但是開源組件顯然就少了很多。

雖然weex號稱能夠統一多平臺,但是能夠使用的特性只有多平臺共有的特性,這一點其實react-native也能做到。這樣就導致weex被限定在一個比較小的方面了。

同時weex說能夠無縫降級為h5實現,然而我實踐下來發現其實并不能做到完全的無縫,因為兩者之間有些東西并不能等價。react-native降級會更為麻煩一些,還要考慮多平臺的原生組件。所以實際上weex的降級方案并沒有他說的那么好用。

布局系統,雖然三方(h5,weex,react-native)都可以使用flex布局來實現,但還是有部分出入。react-native和web的flex兼容的最好,上面就是按照web的方式來寫的,但是有部分是web沒有的。weex比較奇怪,他實現了部分flex功能,同時又自己自創了幾個,所以說降級并沒有那么好用。下面的例子就是就可以看出來,如果按照web的寫法會有一些錯亂。

可以這么認為:

react-native flex (Yoga) > web flex > weex flex

weex的社區支持比較小,也就國內的幾個廠家在使用,所以能獲得的幫助也會少一些。

下面就是使用weex來實現的例子,css和上面的保持一致,發現有些布局已經發生錯亂:

weex.png
<template>
  <div class='container'>
    <div class='content'>
      <div class='textContent'>
        <text class='title'>{{answer.question.title}}</text>
        <text class='subTitle'>{{answer.description}}</text>
      </div>
      <image v-show="cover" class='image' :src='cover' ></image>
    </div>
    <div class='textSep'></div>
    <text class='nickName'>{{answer.author.nickname}}</text>
    <div class='sep'/>
  </div>
</template>

<script>
export default {
  props: {
    answer: Object
  },
  computed: {
    cover() {
      return this.answer.images && this.answer.images.length && this.answer.images[0]
    }
  }
}
</script>

<style>
  .container {
    margin-left: 40;
    margin-right: 40;
    align-items: stretch;
  }
  .content {
    margin-top: 40;
    flex-direction: row;
  }
  .textContent {
    flex-direction: column;
    flex-shrink: 1;
    flex-grow: 1;
  }
  .image {
    margin-left: 20;
    width: 200;
    height: 200;
    border-radius: 4;
    flex-shrink: 0;
    /* aspect-ratio: 1; */
  }
  .textSep {
    height: 2;
    width: 40;
    background-color: #ccc;
    margin-top: 20;
  }
  .title {
    lines: 2;
    font-size: 32;
    line-height: 40;
    font-weight: 600;
    margin-top: 0
  }
  .subTitle {
    lines: 3;
    margin-top: 16;
    font-size: 26;
    line-height: 34;
    color: #999;
  }
  .nickName {
    margin-top: 28;
    font-size: 24;
    color: #999;
  }
  .sep {
    margin-top: 40;
    height: 2;
    background-color: #ccc;
  }
</style>

官方的debug工具:

weex-dev-tools1.png
weex-dev-tools2.png
weex-dev-tools3.png

js-native

如果你要問我選用哪個框架,根據上面的兩個例子,心里應該就有選擇了。react-native是一個非常大型的完善的項目,如果你不想折騰,那么就選擇react-native吧。如果你想要極致的選擇,你可以嘗試下weex。而多平臺支持并不是你選擇的理由,react-native的子集完全可以做到多平臺支持。

H5

這是一個非常古老,但是非常有效的策略了。而且不需要更多的學習成本。缺點當然就是沒有native那么的高效。

最有名的當然就是cordova這個開源項目了。他把很多native的功能通過module的方式暴露給web,讓web能夠使用很多的原生功能。而事實上很多情況下web只是作為一個app的附加功能,并不會給web如此多的權限。所以如果整個app是架構在web的基礎上的話,可以嘗試下cordova這類的項目。而僅僅是內嵌web,則需要考慮到控制不同的web需要擁有不同的權限。

cordova.png

另外一個非常有名的項目是JSWebviewBridge,他可以讓我們定制化的注入幾個功能,提供web端調用。這種定制比較簡單,也沒有module的概念,不能夠構建復雜的功能。

h5最為常用和成熟,而且和原生系統關系不大,所以這里就簡單介紹下。

Template / DSL

剩下的基本就可以概括為模板技術和DSL技術了。這兩者的應用面更加狹窄,往往作為并不要求那么靈活多變的場景。但是這種方式更為穩定和搞笑。

Tangram

淘寶首頁的模塊化技術。可以想到,淘寶首頁對動態化的要求沒有那么高,首頁的運營都是非常穩定的,樣式也是非常穩定的,只有內容變化非常大,那么模板技術就是最適合的了。

其實很多app都在用這種方案,只是做的更加的簡單些,比如:

[
    {
      "type": 1,
      "data": {}
    },
    {
      "type": 2,
      "data": {}
    }
]

這種數據結構,type所對應的就是模板的代號。只是Tangram將這個更加的泛化了而已,并且增加了很多后臺配置和管理的功能。

官方的例子:

tangram-example1.gif
tangram-example2.gif

Jasonette

這是一個依賴于JSON的DSL,包括布局、事件處理都可以在JSON中配置完成。

布局使用UITableViewUICollectionViewUIStackView來實現,所以也有部分的兼容問題。

同時對于新的DSL,學習成本比較大,也缺乏debug和開發工具,手寫JSON太不友好了。

這是我用Jasonette寫的例子:

json.png

基本的布局可以實現,但有些布局還是不能很好的完成。

官方的例子:

json-example1.gif
json-example2.gif

samurai-native / BeeFramework

這是利用xml或者html來布局的框架,雖然可以做到綁定事件,但并不能處理事件,所以局限非常大。這兩者已經很久沒人維護了。

總結

可以看到目前這類想法除了模板技術,其他的都已經被X-native所替代了,因為這種技術的局限性實在是太大了。所以也建議大家慎重考慮這種局限比較大的方案。

最后

以上介紹了目前比較熱門的幾種hybrid方案,就目前的情況來說,除了h5,其他都在向javascript-native方向發展,可能因為javascript這門語言的火熱,同時又有大量前端開發。可見一個方案的優劣還是需要從更大的方面來看待,而不是從功能的實現上來看待,易用和學習成本還是非常重要的。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容