Hybrid目前開發(fā)現(xiàn)狀
??目前主要有以下幾種方式的混合開發(fā):
- Native&H5:
??這種模式就是在原生頁面加入H5的頁面,將項(xiàng)目中重復(fù)使用又比較耗時(shí)的部分用H5頁面實(shí)現(xiàn)涌哲,在iOS始衅、Android和H5以及微信公眾號(hào)都可以使用推沸。
??優(yōu)點(diǎn):方便快捷,入侵性小,幾乎不改變?cè)鶤PP的框架使用成本較低卦停,容易上手向胡。
??缺點(diǎn):效果不如原生流暢,體驗(yàn)比較差沫浆;如果遇到多級(jí)的H5頁面在Native加載,那么實(shí)現(xiàn)的效果往往不如預(yù)期专执。
??Native和H5職責(zé)劃分:總的原則是H5提供內(nèi)容,Native提供容器本股。
??使用Native的場(chǎng)景——轉(zhuǎn)場(chǎng)動(dòng)畫攀痊、多線程操作(密集型任務(wù))、IO的調(diào)用拄显,當(dāng)然一些安全性比較高的界面苟径,比如:注冊(cè)躬审、登錄界面、支付界面承边。當(dāng)然,有些要考慮到終端性能的問題博助,有些動(dòng)畫H5雖然能夠?qū)崿F(xiàn),但是在低端機(jī)器上效果很差蛔糯,這個(gè)時(shí)候就要考慮用原生實(shí)現(xiàn)了拯腮。
??使用H5的場(chǎng)景——基本信息的展示蚁飒,簡(jiǎn)單圖表的展示。一句話總結(jié):H5負(fù)責(zé)需要快速迭代又不使用系統(tǒng)IO交互內(nèi)容的展示狼电。 - React Native
??RN 是什么:就是使用 JS 和 React 來構(gòu)建原生 APP弦蹂。而 RN 并不能算作是 Hybrid,它是通過 JS 來直接調(diào)用原生組件達(dá)到高性能的一種解決方案凸椿。
??RN 的優(yōu)點(diǎn):組件化、虛擬DOM脑漫、開發(fā)效率高,性能無限接近原生APP吨拍,當(dāng)然還包括死掉的 HotFix(手動(dòng)捂臉)网杆。
??RN 的缺點(diǎn):三方 SDK 開放的 RN 比較少 ,需要自己橋接碳却。如果想要開發(fā)高性能的應(yīng)用队秩,必須了解 Native 開發(fā)昼浦。 - Cordova
??Cordova 是一個(gè)開源的移動(dòng)開發(fā)框架。允許你使用標(biāo)準(zhǔn)的 web 技術(shù)HTML5鸟蟹、CSS3 和 JavaScript 做跨平臺(tái)開發(fā)使兔。應(yīng)用在每個(gè)平臺(tái)的具體執(zhí)行被封裝了起來建钥,并依靠復(fù)合標(biāo)準(zhǔn)的 API 綁定去訪問每個(gè)設(shè)備的功能火诸,比如說:傳感器荠察、數(shù)據(jù)奈搜、網(wǎng)絡(luò)狀態(tài)等。
??Cordova 優(yōu)點(diǎn):降低開發(fā)成本馋吗,一次開發(fā)多平臺(tái)套用秋秤,版本更新可動(dòng)態(tài)更新。
??Cordova 缺點(diǎn):Cordova的原理就是在原生 APP 上加了一個(gè) WebView灼卢,并提供一套 JS 與原生代碼交互的類庫。交互效果一般鞋真,并且訪問原生控件時(shí)受限。 - Weex
??Weex 是一套簡(jiǎn)單易用的跨平臺(tái)開發(fā)方案海诲,能以 web 的開發(fā)體驗(yàn)構(gòu)建高性能檩互、可擴(kuò)展的 Native 應(yīng)用。Weex 使用 Vue 作為上層框架闸昨,并遵循 W3C 標(biāo)準(zhǔn)實(shí)現(xiàn)了統(tǒng)一的 JSEngine 和 DOM API。
??Weex 優(yōu)點(diǎn):輕量級(jí)溉跃,簡(jiǎn)單的 DSL 語言易于上手;擴(kuò)展性好撰茎,可以對(duì)網(wǎng)絡(luò)打洼、圖片、存儲(chǔ)募疮、UT、組件他嚷、接口等根據(jù)自身 APP 和業(yè)務(wù)需求進(jìn)行擴(kuò)展;組件化筋蓖,Weex 本身編寫的界面就天然的支持組件化,同事支持大部分組件蚣抗;開發(fā)成本較低瓮下。
??Weex 的缺點(diǎn):Bug 很多,作為新推出的解決方案讽坏,Weex 還有很多需要改進(jìn);社區(qū)的規(guī)模較小路呜,知名度也相對(duì)較低。
Native&H5使用實(shí)例
- WKWebViewJavascriptBridge 關(guān)聯(lián) WKWebView
??我們使用了 WKWebViewJavascriptBridge 這個(gè)優(yōu)秀的第三方庫來橋接 WKWebView 和 H5党涕。
lazy var webView: WKWebView = {
let temp = WKWebView()
temp.isOpaque = false
temp.uiDelegate = self
temp.navigationDelegate = self
temp.addObserver(self, forKeyPath: "estimatedProgress", options: NSKeyValueObservingOptions.new, context: nil)
return temp
}()
lazy var webViewBridge: WKWebViewJavascriptBridge = {
let temp = WKWebViewJavascriptBridge.init(for: webView)
temp?.setWebViewDelegate(self)
return temp!
}()
- registerHandler
??我們通過 webViewBridge 注冊(cè) handle 綁定相應(yīng)的事件巡社,這樣 H5 可以通過這個(gè)事件告訴 APP 進(jìn)行相應(yīng)的操作和傳遞數(shù)據(jù)。以此實(shí)現(xiàn) H5 與 APP 的交互肥荔。
//注冊(cè)一個(gè)如果Token過期朝群,H5通過注冊(cè)的事件告訴Native
func registTokenHandle() {
webViewBridge.registerHandler("tokenDisabled") { (data, responseCallBack) in
//這里是登錄失效的代碼
}
}
- WKWebView-UserAgent設(shè)置
??要區(qū)分打開的 H5 是本地 APP 還是在手機(jī)的瀏覽器,就要修改默認(rèn)的 UserAgent
func setupUserAgent() {
let webView = UIWebView()
if var newUserAgent = webView.stringByEvaluatingJavaScript(from: "navigator.userAgent"){
newUserAgent.append(" XXX-iOS")
let dic = ["UserAgent": newUserAgent]
UserDefaults.standard.register(defaults: dic)
}
}
- 進(jìn)度條和title
??通過 WKWebView可以很方便的使用 addObserver 來 設(shè)置進(jìn)度條和 捕獲 H5 的title給 Native 的頁面誉帅。
??進(jìn)度條:
//1 設(shè)置 observer
temp.addObserver(self, forKeyPath: "estimatedProgress", options: NSKeyValueObservingOptions.new, context: nil)
//2 設(shè)置代理
class YourWebViewController: WKUIDelegate,WKNavigationDelegate{}
//3 實(shí)現(xiàn)代理方法
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
if keyPath == "estimatedProgress",
(object as? WKWebView) == webView{
let progress = Float(self.webView.estimatedProgress)
progressView.setProgress(progress, animated: true)
if progress >= 1.0 {
UIView.animate(withDuration: 0.3, delay: 0.1, options: .curveEaseOut, animations: {
self.progressView.alpha = 0
}, completion: { (finish) in
self.progressView.setProgress(0.0, animated: false)
})
}else{
self.progressView.alpha = 1
}
}
}
//4 記得 removeObserver
deinit {
self.webView.removeObserver(self, forKeyPath: "estimatedProgress")
}
??捕獲H5 的 Title:
//1 設(shè)置 observer
wkWebView.addObserver(self, forKeyPath: "title", options: NSKeyValueObservingOptions.new, context: nil)
//2 設(shè)置代理
class YourWebViewController: WKUIDelegate,WKNavigationDelegate{}
//3 實(shí)現(xiàn)代理方法
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
if keyPath == "title",(object as? WKWebView) == webView{
webViewTitle = self.webView.title
}else{
super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
}
}
//4 記得 removeObserver
deinit {
self.webView.removeObserver(self, forKeyPath: "estimatedProgress")
}
- 代碼重構(gòu)
??一兩個(gè) WebView 的頁面可以隨意些蚜锨,但是如果項(xiàng)目中很多頁面都通過 H5 實(shí)現(xiàn)慢蜓,那么我們就要統(tǒng)一規(guī)范配置需要跳轉(zhuǎn)的 URL亚再。
class YourJSBridge: NSObject {
static let baseUrl = YourAppManager.baseH5URL
var baseUrl: String{
return YourJSBridge.baseUrl
}
struct Event {
static let successButtonClick = "successButtonClick"
}
struct Path {
static let yourUrlPath = "yourUrlPath"
}
struct Url {
static func successMethod(parame successStr: String) -> String{
return baseUrl.your_appendingPathComponent(Path.yourUrlPath).token.parameter(key: "successStr", value: successStr)
}
}
}
fileprivate extension String{
var token: String{
let token = YourManager.shared.token?.token ?? "---"
return self+"?token=\(token)"
}
func parameter(key: String,value: Any) -> String{
return self+"&\(key)=\(value)"
}
func your_appendingPathComponent(_ path: String) -> String{
return self+"/"+path
}
}
參考鏈接:
Hybrid APP架構(gòu)設(shè)計(jì)思路
iOS原生混合RN開發(fā)最佳實(shí)踐
weex&ReactNative對(duì)比
RN 系列之--什么是 ReactNative
Weex在達(dá)人店的一年實(shí)踐
淺談一款移動(dòng)端開發(fā)框架Weex