A. 安卓jsbridge是全局的嗎
android.app.Application類和Activity,Service一樣是Android框架的一個系統組件,當Android程序啟動時系統會創建一個Application對象,用來存儲系統的一些信息。 Android系統自動會為每個程序運行時創建一個Application類的對象且只創建一個,所以Application可以說是單例(singleton)模式的一個類。 通常我們是不需要指定一個Application的,系統會自動幫我們創建,如果需要創建自己的Application,那也很簡單!創建一個類繼承Application並在AndroidManifest.xml文件中的application標簽中進行注冊(只需要給application標簽增加name屬性,並添加自己的 Application的名字即可)。 啟動Application時,系統會創建一個PID,即進程ID,所有的Activity都會在此進程上運行。那麼我們在Application創建的時候初始化全局變數,同一個應用的所有Activity都可以取到這些全局變數的值,換句話說,我們在某一個Activity中改變了這些全局變數的值,那麼在同一個應用的其他Activity中值就會改變。Application對象的生命周期是整個程序中最長的,它的生命周期就等於這個程序的生命周期。因為它是全局的單例的,所以在不同的Activity,Service中獲得的對象都是同一個對象。因此可以通過Application來進行一些,如:數據傳遞、數據共享和數據緩存等操作。 測試示例: 1.創建自定義的application類:package com.example.context; import android.app.Application; import android.util.Log; /** * @author Rowand jj * *整個應用的上下文對象 */ public class MyApp extends Application { private static final MyApp instance = new MyApp(); /** * 全局變數 */ private String name = "Rowandjj"; /* * android應用程序真正入口。 * 此方法在所有activity,servie,receiver組件之前調用 * */ @Override public void onCreate() { super.onCreate();//必須調用父類方法 Log.i("CREATE","application created...."); } /** * 此方法方便在那些沒有context對象的類中使用 * @return MyApp實例 */ public static MyApp getApplicationInstance() { return instance; } /* setter/getter 方法 */ public String getName() { return name; } public void setName(String name) { this.name = name; } }
B. jsbridge android 匹配無效 被斷開什麼原因
native向js的通信協議也需要制定,一個必不可少的元素就是返回值,這個返回值和js的參數做法一樣,通過json對象進行傳遞,該json對象中有狀態碼code,提示信息msg,以及返回結果result,如果code為非0,則執行過程中發生了錯誤,錯誤信息在msg中,返回結果result為null,如果執行成功,返回的json對象在result中。下面是兩個例子,一個成功調用,一個調用失敗。
{
"code":500,
"msg":"method is not exist",
"result":null
}
Java
{
"code":0,
"msg":"ok",
"result":{
"key1":"returnValue1",
"key2":"returnValue2",
"key3":{
"nestedKey":"nestedValue"
"nestedArray":["value1","value2"]
}
}
}
那麼這個結果如何返回呢,native調用js暴露的方法即可,然後將js層傳給native層的port一並帶上,進行調用即可,調用的方式就是通過WebView.loadUrl方式來完成,如下。
Java
1
mWebView.loadUrl("javascript:JSBridge.onFinish(port,jsonObj);");
關於JsBridge.onFinish方法的實現,後面再敘述。前面所提到了native層的方法必須遵循某種規范,不然就非常不安全了。在native中,我們需要一個JSBridge統一管理這些暴露給js的類和方法,並且能實時添加,這時候就需要這么一個方法
Java
JSBridge.register("jsName",javaClass.class)
這個javaClass就是滿足某種規范的類,該類中有滿足規范的方法,我們規定這個類需要實現一個空介面,為什麼呢?主要作用就混淆的時候不會發生錯誤,還有一個作用就是約束JSBridge.register方法第二個參數必須是該介面的實現類。那麼我們定義這個介面
Java
publicinterfaceIBridge{
}
類規定好了,類中的方法我們還需要規定,為了調用方便,我們規定類中的方法必須是static的,這樣直接根據類而不必新建對象進行調用了(還要是public的),然後該方法不具有返回值,因為返回值我們在回調中返回,既然有回調,參數列表就肯定有一個callback,除了callback,當然還有前文提到的js傳來的方法調用所需的參數,是一個json對象,在java層中我們定義成JSONObject對象;方法的執行結果需要通過callback傳遞回去,而java執行js方法需要一個WebView對象,於是,滿足某種規范的方法原型就出來了。
Java
publicstaticvoidmethodName(WebViewwebview,JSONObjectjsonObj,Callbackcallback){
}
js層除了上文說到的JSBridge.onFinish(port,jsonObj);方法用於回調,應該還有一個方法提供調用native方法的功能,該函數的原型如下
Java
JSBridge.call(className,methodName,params,callback)
在call方法中再將參數組合成形如下面這個格式的uri
Java
jsbridge://className:callbackAddress/methodName?jsonObj
然後調用window.prompt方法將uri傳遞過去,這時候java層就會收到這個uri,再進一步解析即可。
萬事具備了,只欠如何編碼了,別急,下面我們一步一步的來實現,先完成js的兩個方法。新建一個文件,命名為JSBridge.js
Java
(function(win){
varhasOwnProperty=Object.prototype.hasOwnProperty;
varJSBridge=win.JSBridge||(win.JSBridge={});
varJSBRIDGE_PROTOCOL='JSBridge';
varInner={
callbacks:{},
call:function(obj,method,params,callback){
console.log(obj+" "+method+" "+params+" "+callback);
varport=Util.getPort();
console.log(port);
this.callbacks[port]=callback;
varuri=Util.getUri(obj,method,params,port);
console.log(uri);
window.prompt(uri,"");
},
onFinish:function(port,jsonObj){
varcallback=this.callbacks[port];
callback&callback(jsonObj);
deletethis.callbacks[port];
},
};
varUtil={
getPort:function(){
returnMath.floor(Math.random()*(130));
},
getUri:function(obj,method,params,port){
params=this.getParam(params);
varuri=JSBRIDGE_PROTOCOL+'://'+obj+':'+port+'/'+method+'?'+params;
returnuri;
},
getParam:function(obj){
if(obj&typeofobj==='object'){
returnJSON.stringify(obj);
}else{
returnobj||'';
}
}
};
for(varkeyinInner){
if(!hasOwnProperty.call(JSBridge,key)){
JSBridge[key]=Inner[key];
}
}
})(window);
java層有一個空介面來進行約束暴露給js的類和方法,同時也便於混淆
Java
publicinterfaceIBridge{
}
首先我們要將js傳來的uri獲取到,編寫一個WebChromeClient子類。
Java
{
@Override
publicbooleanonJsPrompt(WebViewview,Stringurl,Stringmessage,StringdefaultValue,JsPromptResultresult){
result.confirm(JSBridge.callJava(view,message));
returntrue;
}
}
之後不要忘記了將該對象設置給WebView
Java
WebViewmWebView=(WebView)findViewById(R.id.webview);
WebSettingssettings=mWebView.getSettings();
settings.setJavaScriptEnabled(true);
mWebView.setWebChromeClient(newJSBridgeWebChromeClient());
mWebView.loadUrl("file:///android_asset/index.html");
核心的內容來了,就是JSBridgeWebChromeClient中調用的JSBridge類的實現。前文提到該類中有這么一個方法提供注冊暴露給js的類和方法
Java
JSBridge.register("jsName",javaClass.class)
該方法的實現其實很簡單,從一個Map中查找key是不是存在,不存在則反射拿到對應的Class中的所有方法,將方法是public static void 類型的,並且參數是三個參數,分別是Webview,JSONObject,Callback類型的,如果滿足條件,則將所有滿足條件的方法put進去,整個實現如下
Java
publicclassJSBridge{
privatestaticMap>exposedMethods=newHashMap();
publicstaticvoidregister(StringexposedName,ClassextendsIBridge>clazz){
if(!exposedMethods.containsKey(exposedName)){
try{
exposedMethods.put(exposedName,getAllMethod(clazz));
}catch(Exceptione){
e.printStackTrace();
}
}
}
(ClassinjectedCls)throwsException{
HashMapmMethodsMap=newHashMap();
Method[]methods=injectedCls.getDeclaredMethods();
for(Methodmethod:methods){
Stringname;
if(method.getModifiers()!=(Modifier.PUBLIC|Modifier.STATIC)||(name=method.getName())==null){
continue;
}
Class[]parameters=method.getParameterTypes();
if(null!=parameters¶meters.length==3){
if(parameters[0]==WebView.class&¶meters[1]==JSONObject.class&¶meters[2]==JSCallback.class){
mMethodsMap.put(name,method);
}
}
}
returnmMethodsMap;
}
}
publicstaticStringcallJava(WebViewwebView,StringuriString){
StringmethodName="";
StringclassName="";
Stringparam="{}";
Stringport="";
if(!TextUtils.isEmpty(uriString)&uriString.startsWith("JSBridge")){
Uriuri=Uri.parse(uriString);
className=uri.getHost();
param=uri.getQuery();
port=uri.getPort()+"";
Stringpath=uri.getPath();
if(!TextUtils.isEmpty(path)){
methodName=path.replace("/","");
}
}
if(exposedMethods.containsKey(className)){
HashMapString,Method>methodHashMap=exposedMethods.get(className);
if(methodHashMap!=null&methodHashMap.size()!=0&&methodHashMap.containsKey(methodName)){
Methodmethod=methodHashMap.get(methodName);
if(method!=null){
try{
method.invoke(null,webView,newJSONObject(param),newCallback(webView,port));
}catch(Exceptione){
e.printStackTrace();
}
}
}
}
returnnull;
}
publicclassCallback{
privatestaticHandlermHandler=newHandler(Looper.getMainLooper());
_JS_FORMAT="javascript:JSBridge.onFinish('%s', %s);";
privateStringmPort;
;
publicCallback(WebViewview,Stringport){
mWebViewRef=newWeakReference(view);
mPort=port;
}
publicvoidapply(JSONObjectjsonObject){
finalStringexecJs=String.format(CALLBACK_JS_FORMAT,mPort,String.valueOf(jsonObject));
if(mWebViewRef!=null&mWebViewRef.get()!=null){
mHandler.post(newRunnable(){
@Override
publicvoidrun(){
mWebViewRef.get().loadUrl(execJs);
}
});
}
}
}
{
publicstaticvoidshowToast(WebViewwebView,JSONObjectparam,finalCallbackcallback){
Stringmessage=param.optString("msg");
Toast.makeText(webView.getContext(),message,Toast.LENGTH_SHORT).show();
if(null!=callback){
try{
JSONObjectobject=newJSONObject();
object.put("key","value");
object.put("key1","value1");
callback.apply(getJSONObject(0,"ok",object));
}catch(Exceptione){
e.printStackTrace();
}
}
}
(intcode,Stringmsg,JSONObjectresult){
JSONObjectobject=newJSONObject();
try{
object.put("code",code);
object.put("msg",msg);
object.putOpt("result",result);
returnobject;
}catch(JSONExceptione){
e.printStackTrace();
}
returnnull;
}
}
你可以往該類中扔你需要的方法,但是必須是public static void且參數列表滿足條件,這樣才能找到該方法。
不要忘記將該類注冊進去
Java
JSBridge.register("bridge",BridgeImpl.class);
進行一下簡單的測試,將之前實現好的JSBridge.js文件扔到assets目錄下,然後新建index.html,輸入
html>
head>
metacharset="utf-8">
title>JSBridgetitle>
metaname="viewport"
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1, user-scalable=no"/>
scriptsrc="file:///android_asset/JSBridge.js"type="text/javascript">script>
scripttype="text/javascript">
script>
style>
style>
head>
body>
div>
h3>JSBridge測試h3>
div>
ulclass="list">
li>
div>
buttononclick="JSBridge.call('bridge','showToast',{'msg':'Hello JSBridge'},function(res){alert(JSON.stringify(res))})">
測試showToast
button>
div>
li>
br/>
ul>
body>
html>
C. 如何寫一個JsBridge
Android JsBridge 就是用來在 Android app的原生 java 代碼與 javascript 代碼中架設通信(調用)橋梁的輔助工具。
原文地址點這里
github點這里
有問題請聯系xesam
Javascript 運行在 WebView 中,而 WebView 只是 Javascript 執行引擎與頁面渲染引擎的一個包裝而已。
由於這種天然的隔離效應,我們可以將這種情況與 IPC 進行類比,將 Java 與 Javascript 的每次互調都看做一次 IPC 調用。 如此一來,我們可以模仿各種已有的 IPC 方式來進行設計,比如 RPC。本文模仿 Android 的 Binder 機制來實現一個 JsBridge。
D. Android混合開發該怎麼搞
Cordova是一個廣泛使用的Hybrid開發框架,它提供了一套js和Native交互規范
在Cordova的SystemWebViewEngine類中可以
看到私有靜態void exposeJsInterface(WebView webView,CordovaBridge橋){
if((Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1)){
Log.i(TAG,「自Android版本以來已禁用addJavascriptInterface()橋接。」);
//錯誤是Java Strings不會自動轉換為JS字元串。
//在JS方面解決這個問題並不困難,但是更容易
使用提示橋來代替。
返回;
}
webView.addJavascriptInterface(新SystemExposedJsApi(橋), 「_cordovaNative」);
}
因此當Android系統高於4.2時,Cordova還是使用addJavascriptInterface這種方式,因為這個方法在高版本上安全而且簡單,低於4.2的時候,用什麼方法呢?
答案是WebChromeClient.onJsPrompt方法
WebView可以設置一個WebChromeClient對象,它可以處理js的3個方法
onJsAlert
onJsConfirm
onJsPrompt
這3個方法分別對應js的警告,確認,提示方法,因為只有提示接收返回值,所以js調用一個Native方法後可以等待Native返回一個參數。下面是cordova.js中的一段代碼:
/ **
*實現ExposedJsApi.java的API,但使用prompt()進行通信。
*這是在JellyBean之前使用的,其中addJavascriptInterface()被禁用。
* /
mole.exports = {
exec:function(bridgeSecret,service,action,callbackId,argsJson){
return prompt(argsJson,'gap:'+ JSON.stringify([bridgeSecret,service,action,callbackId]));
},
setNativeToJsBridgeMode:function(bridgeSecret,value){
prompt(value,'gap_bridge_mode:'+ bridgeSecret);
},
retrieveJsMessages:function(bridgeSecret,fromOnlineEvent){
return prompt(+ fromOnlineEvent,'gap_poll:'+ bridgeSecret);
}
};
然後只要在onJsPrompt方法中使用CordovaBridge來處理js的提示調用
/ **
*告訴客戶端向用戶顯示提示對話框。如果客戶端返回true,則WebView將假定客戶端將處理提示對話框並調用相應的JsPromptResult方法。
* <p />
*由於我們出於自己的目的黑客提示,我們不應該為此目的使用它們,也許我們應該破解console.log來代替!
* /
@Override
public boolean onJsPrompt(WebView視圖,String origin,String message,String defaultValue,final JsPromptResult result){
//與@JavascriptInterface橋不同,此方法始終在UI線程上調用。
String processedRet = parentEngine.bridge.promptOnJsPrompt(origin,message,defaultValue);
if(processedRet!= null){
result.confirm(processedRet);
} else {
dialogsHelper.showPrompt(message,defaultValue,new CordovaDialogsHelper.Result(){
@
Override public void gotResult(boolean success,String value){
if(success){
result.confirm(value);
} else {
result.cancel( );
}
}
});
}
return true;
}
E. ios 用jsbridge 怎麼傳參數給h5
純粹的HTML5應用很少,甚至只有一個view是用WebView/UIWebView的方式越來越常見了。 基本上只要對那個view長按,然後看是不是有反應,比如手機震動(Android)、或者出現文字選擇粘貼(Android/iOS),那麼就是WebView!
F. android 混合開發 框架有哪些
Cordova是一個廣泛使用的Hybrid開發框架,它提供了一套js和Native交互規范
在Cordova的 SystemWebViewEngine 類中可以看到
private static void exposeJsInterface(WebView webView, CordovaBridge bridge) {
if ((Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1)) {
Log.i(TAG, "Disabled addJavascriptInterface() bridge since Android version is old.");
// Bug being that Java Strings do not get converted to JS strings automatically.
// This isn't hard to work-around on the JS side, but it's easier to just
// use the prompt bridge instead.
return;
}
webView.addJavascriptInterface(new SystemExposedJsApi(bridge), "_cordovaNative");
}
因此當Android系統高於4.2時,Cordova還是使用 addJavascriptInterface 這種方式,因為這個方法在高版本上安全而且簡單,低於4.2的時候,用什麼方法呢?
答案是 WebChromeClient.onJsPrompt 方法
WebView可以設置一個 WebChromeClient 對象,它可以處理js的3個方法
onJsAlert
onJsConfirm
onJsPrompt
這3個方法分別對應js的 alert 、 confirm 、 prompt 方法,因為只有 prompt 接收返回值,所以js調用一個Native方法後可以等待Native返回一個參數。下面是 cordova.js 中的一段代碼:
/**
* Implements the API of ExposedJsApi.java, but uses prompt() to communicate.
* This is used pre-JellyBean, where addJavascriptInterface() is disabled.
*/
mole.exports = {
exec: function(bridgeSecret, service, action, callbackId, argsJson) {
return prompt(argsJson, 'gap:'+JSON.stringify([bridgeSecret, service, action, callbackId]));
},
setNativeToJsBridgeMode: function(bridgeSecret, value) {
prompt(value, 'gap_bridge_mode:' + bridgeSecret);
},
retrieveJsMessages: function(bridgeSecret, fromOnlineEvent) {
return prompt(+fromOnlineEvent, 'gap_poll:' + bridgeSecret);
}
};
然後只要在 onJsPrompt 方法中使用 CordovaBridge 來處理js的prompt調用
/**
* Tell the client to display a prompt dialog to the user. If the client returns true, WebView will assume that the client will handle the prompt dialog and call the appropriate JsPromptResult method.
* <p/>
* Since we are hacking prompts for our own purposes, we should not be using them for this purpose, perhaps we should hack console.log to do this instead!
*/
@Override
public boolean onJsPrompt(WebView view, String origin, String message, String defaultValue, final JsPromptResult result) {
// Unlike the @JavascriptInterface bridge, this method is always called on the UI thread.
String handledRet = parentEngine.bridge.promptOnJsPrompt(origin, message, defaultValue);
if (handledRet != null) {
result.confirm(handledRet);
} else {
dialogsHelper.showPrompt(message, defaultValue, new CordovaDialogsHelper.Result() {
@Override
public void gotResult(boolean success, String value) {
if (success) {
result.confirm(value);
} else {
result.cancel();
}
}
});
}
return true;
}
G. android token 超時,非同步回調怎麼實現會比較優雅
PhoneGap的js回調有幾種實現方式。其中一種是ajax。
我們先來看一下js端相關代碼:
// file: lib/android/plugin/android/callback.js
define("cordova/plugin/android/callback", function(require, exports, mole) {
var port = null,
token = null,
xmlhttp;
function startXhr() {
// cordova/exec depends on this mole, so we can't require cordova/exec on the mole level.
var exec = require('cordova/exec'),
xmlhttp = new XMLHttpRequest();
// Callback function when XMLHttpRequest is ready
xmlhttp.onreadystatechange=function(){
if (!xmlhttp) {
return;
}
if (xmlhttp.readyState === 4){
// If callback has JavaScript statement to execute
if (xmlhttp.status === 200) {
// Need to url decode the response
var msg = decodeURIComponent(xmlhttp.responseText);
setTimeout(startXhr, 1);
exec.processMessages(msg);
}
// If callback ping (used to keep XHR request from timing out)
else if (xmlhttp.status === 404) {
setTimeout(startXhr, 10);
}
// 0 == Page is unloading.
// 400 == Bad request.
// 403 == invalid token.
// 503 == server stopped.
else {
console.log("JSCallback Error: Request failed with status " + xmlhttp.status);
exec.setNativeToJsBridgeMode(exec.nativeToJsModes.POLLING);
}
}
};
if (port === null) {
port = prompt("getPort", "gap_callbackServer:");
}
if (token === null) {
token = prompt("getToken", "gap_callbackServer:");
}
xmlhttp.open("GET", "http://127.0.0.1:"+port+"/"+token , true);
xmlhttp.send();
}
mole.exports = {
start: function() {
startXhr();
},
stop: function() {
if (xmlhttp) {
var tmp = xmlhttp;
xmlhttp = null;
tmp.abort();
}
},
isAvailable: function() {
return ("true" != prompt("usePolling", "gap_callbackServer:"));
}
};
});
主要的處理是startXhr函數。它向java的server端發起了ajax請求,在onreadystatechange這個回調函數中等待server端返回結果。如果server端返回的結果正確,則再通過setTimeout(startXhr, 1)函數,1豪秒後再重新向server端發起ajax請求。如果從server返回的結果狀態是404,則每隔10豪秒,重新向server端發起ajax請求。
接下來看看server端是如何處理的。server端的處理代碼是CallbackServer.java中的run()方法中。
先看server端的源碼:
它通過serverSocket來模擬http的server端。其中,jsMessageQueue中是從java端發送的js消息,serverSocket在接收到客戶端(js端)的請求後,會將jsMessageQueue中的js代碼發送到客戶端(js端)。
/**
* Start running the server.
* This is called automatically when the server thread is started.
*/
public void run() {
// Start server
try {
this.active = true;
String request;
waitSocket = new ServerSocket(0);
this.port = waitSocket.getLocalPort();
//Log.d(LOG_TAG, "CallbackServer -- using port " +this.port);
this.token = java.util.UUID.randomUUID().toString();
//Log.d(LOG_TAG, "CallbackServer -- using token "+this.token);
while (this.active) {
//Log.d(LOG_TAG, "CallbackServer: Waiting for data on socket");
Socket connection = waitSocket.accept();
BufferedReader xhrReader = new BufferedReader(new InputStreamReader(connection.getInputStream()), 40);
DataOutputStream output = new DataOutputStream(connection.getOutputStream());
request = xhrReader.readLine();
String response = "";
//Log.d(LOG_TAG, "CallbackServerRequest="+request);
if (this.active && (request != null)) {
if (request.contains("GET")) {
// Get requested file
String[] requestParts = request.split(" ");
// Must have security token
if ((requestParts.length == 3) && (requestParts[1].substring(1).equals(this.token))) {
//Log.d(LOG_TAG, "CallbackServer -- Processing GET request");
String payload = null;
// Wait until there is some data to send, or send empty data every 10 sec
// to prevent XHR timeout on the client
while (this.active) {
if (jsMessageQueue != null) {
payload = jsMessageQueue.popAndEncode();
if (payload != null) {
break;
}
}
synchronized (this) {
try {
this.wait(10000); // prevent timeout from happening
//Log.d(LOG_TAG, "CallbackServer>>> break <<<");
break;
} catch (Exception e) {
}
}
}
// If server is still running
if (this.active) {
// If no data, then send 404 back to client before it times out
if (payload == null) {
//Log.d(LOG_TAG, "CallbackServer -- sending data 0");
response = "HTTP/1.1 404 NO DATA\r\n\r\n "; // need to send content otherwise some Android devices fail, so send space
}
else {
//Log.d(LOG_TAG, "CallbackServer -- sending item");
response = "HTTP/1.1 200 OK\r\n\r\n";
response += encode(payload, "UTF-8");
}
}
else {
response = "HTTP/1.1 503 Service Unavailable\r\n\r\n ";
}
}
else {
response = "HTTP/1.1 403 Forbidden\r\n\r\n ";
}
}
else {
response = "HTTP/1.1 400 Bad Request\r\n\r\n ";
}
//Log.d(LOG_TAG, "CallbackServer: response="+response);
//Log.d(LOG_TAG, "CallbackServer: closing output");
output.writeBytes(response);
output.flush();
}
output.close();
xhrReader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
this.active = false;
//Log.d(LOG_TAG, "CallbackServer.startServer() - EXIT");
}
H. 如何寫一個JsBridge-android高心星的私塾
跟web端的人商量好就行。通過webview的url來做交互
I. AlipayJSBridge call參數
AlipayJSBridge call參數如下
content:type,類型:string,描述:文字內容,必選:Y,默認值:『』,版本:8.0;delay:int,延遲多少毫秒後顯示;如果在此時間之前調用了hideLoading, 則不會再顯示,autoHide:bool:默認情況下容器會在pageFinish的後會主動隱藏菊花,默認true, 傳入false,關掉自動隱藏(only android)。
AlipayJSBridge是支付寶客戶端通過bridge機制,允許前端H5頁面通過特定的JS方法AlipayJSBridge不需要任何的引用,是支付寶在window.load後直接存在的。
J. 移動前端行業壓力大不大
壓力挺大的,學的東西很多。
先來說一些基礎的知識1、布局rem,vw,vh,em等2、touch、click事件移動端不在是滑鼠事件,改為touch事件。click事件在移動端有300ms的延遲,可以用fastclick解決。手勢問題可以用hammer.js解決。3、兼容性移動端機器比PC端復雜的多,而且國內基於Android分裂出許多分支。低版本IOS flex布局有問題,不支持webp。低版本Andriod,不支持fetch,不支持ES6特性。解決辦法用babel-ployfill和系統區分,IOS不下發webp。4、jsBridgejsBridge有點像橋接模式,建立起前端和客戶端的通信。jsBridge的原理是什麼,可以查看這篇文章。成楠Peter:hybird App原理20 贊同 · 2 評論文章5、字體移動端不像PC端用微軟雅黑或者使用蘋果自帶字體就行。又因為字體包太大,不能通過網路下載,所以字體的選擇就很總要,並且在英文字體和中文字體間差異很多,經常會出一些詭異的bug。在前端工程化中使用特殊字體7 贊同 · 2 評論文章6、前端框架性能不再像PC端一樣,不用關心react的性能問題了。必須在shouldUpdateComponent攔截某些渲染,否則性能將收到嚴重的影響。所以對開發者編寫的代碼的要求更高。7、webview的機制比如為什麼回退到上一個頁面,頁面不會自動刷新(與PC瀏覽器的機制不一樣),為什麼這樣設計。