移动端H5基础开发指南

641 阅读3分钟

JsBridge

负责Javascript与Native之间相互通信。Js可以调用Native中的方法,Native也可以调用Javascript中的函数。

注意:Js中被Native调用的函数要暴露到window上,不然是调用不到;Native提供给Js调用的对象也挂载到了window上。

jsbridge.png

以Android为例,简单介绍下JsBridge

Activity

Activity 是最容易吸引用户的地方,它是一种可以包含用户界面的组件,主要用于和用户进行交互。

WebView

WebView是Activity中的一种控件,借助它我们就可以在自己的用用程序里嵌入一个浏览器,从而非常轻松地展示各种各样的网页。

Js-Native 通信

Android Studio 新建EmptyActivity项目

  1. 增加创建EmptyActivity项目照片

新建项目.png

  1. 需要加载的主Activity应该已经在AndroidManifest.xml文件中配置好了,我们不需要做过多更改。
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <application
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/Theme.WebViewActivity"
        android:usesCleartextTraffic="true"
        tools:targetApi="31">
        <activity
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
    <uses-permission android:name="android.permission.INTERNET" />

</manifest>
  1. 主Activity的布局xml../res/layout/activity_main.xml中增加WebView控件和Button控件,采用线性布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    android:orientation="vertical">

    <WebView
        android:id="@+id/webView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/button"
        android:layout_margin="8dp"
        android:text="Increase Count"
        ></Button>

</LinearLayout>
  1. 增加MyJsnterface方法
   class MyJsInterface(private  val mContext:Context) {
       // 获取安卓版本
       @JavascriptInterface
       fun getAndroidVersion ():Int {
           return Build.VERSION.SDK_INT
       }
       // 显示 toast弹窗提示 
       @JavascriptInterface
       fun showToast () {
           Toast.makeText(mContext,"Toast from android",Toast.LENGTH_SHORT).show()
       }
   }
  1. 增加html文件,放置在main/assets目录下
<html xmlns="http://www.w3.org/1999/xhtml">
    <body>
        <label>this is a test page</label>
        <label> count: <span id="count"> 0 </span></label>
        <label id="version"></label>
        <button onclick="printAndroidVersion()">
            Click me to print android version
        </button>
        <button onclick="showToast()"> Click me to print a toast</button>
    </body>
    <script>
        const printAndroidVersion = () => {
             const version = Android.getAndroidVersion();
             document.getElementById('version').innerText = `Android version ${version}`;
         }
         const showToast = () => {
             Android.showToast();
         }

         const increaseCount = () => {
             const count = document.getElementById("count").textContent;
             document.getElementById("count").textContent = Number.parseInt(count) + 1;
         }
    </script>
</html>
  1. 主Activitycom.example.webviewactivity/MainActivity.kt中新增WebView相关代码
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        // 获取在布局中增加的WebView控件
        val webView:WebView = findViewById(R.id.webView)
        // webview支持javascript脚本
        webView.settings.javaScriptEnabled = true
        // 当从一个网页跳转到另外一个网页时,希望目标网页仍然在当前WebView中显示,而不是打开系统浏览器
        webView.webViewClient = WebViewClient()
        // 允许加载本地文件
        webView.settings.allowFileAccess = true
        // 支持 content URL
        webView.settings.allowContentAccess = true
        // 加载本地 index.html 文件
        webView.loadUrl("file:///android_asset/index.html")
        // 将Java对象注入到webview中,在页面中可以通过第二个参数提供的名字访问到Java对象
        // Android 会挂到 window对象上
        webView.addJavascriptInterface(MyJsInterface(this),"Android")
        //  找到Button空间添加Click事件
        findViewById<Button>(R.id.button).apply {
            setOnClickListener {
                // 调用 index.html中提供的javascript方法,方法也需要暴露到window上
                webView.loadUrl("javascript:increaseCount()")
            }
        }
    }
}

都配置好之后,手机插到电脑上,然后点击运行按钮,会降app装到手机上,然后就能点击我们新增的按钮进行 js <=> native通信测试了。

适配

flexible 方案

flexible 方案本质是使用rem单位进行布局。

rem

rem 大小取决于根元素的字体大小,因此 1rem 继承了根元素的font-size大小。

核心代码

function r() {
    var width = document.documentElement.clientWidth;
    var e = width / 828 * 100;
    document.documentElement.style.fontSize = e + 'px';
    window.addEventListener('resize', r);
}

使用方式

在828px的设计稿模式下,我们直接将设计稿给的px/100换成rem单位。

例如:828px设计稿下,元素的宽度为100px,我们可以给元素赋值为1rem

随着viewport的兼容性越来越好,flexible这种形式逐渐被抛弃。下面我们看下viewport方案。

viewport 方案

该方案即将视口宽度window.innerWidth和视口高度window.innerHeight平均分成100份,1vw即视口宽度的1%,1vh即视口高度的1%。

转换插件

我们不需要自己转换单位,还是在项目中写px,可以通过插件去转换。

注意:这个插件对JS动态Css、内联Css样式均不生效,所以尽量在这些样式中避免出现width、height、font-size等需要转换值的样式。

常见问题

  • input 调起数字键盘
<input type="number" pattern="[0-9]*" />
  • ios input无法输入
[input] {
    user-select: auto;
}
  • ios font-weight: 500加重不明显
/* 直接升级成 font-weight: 700 */ 提升加粗效果
  • ios 底部安全距离
padding-bottom: constant(safe-area-inset-bottom);
padding-bottom: env(safe-area-inset-bottom);
  • 1px 边框
width: 200%;
height: 200%;
border: 1px solid #000;
transform:scale(0.5);
  • 隐藏滚动条
-webkit-scrollbar {
    display: none;
}
  • 文字溢出效果

单行文字溢出

width: 100px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;

多行文字溢出

display: -webkit-box;
overflow: hidden;
text-overflow: ellipsis;
-webkit-line-clamp: 2; // 控制行数
-webkit-box-orient: vertical;