Cordova

news2024/10/2 16:24:10

一、简介

  • Cordova 是用 Web 技术( HTML,CSS 和 JS )构建移动应用的平台。
  • 我们可以认为Cordova 是一个容器,用于将的 Web 应用移植到移动端,同时支持移动端的功能(例如:定位、蓝牙、摄像头等)。

在这里插入图片描述
优势:

  • 对前端友好,学习成本低
    • HTML,CSS 和 JS,只要你写过 SPA,就很熟悉 Cordova
  • 跨平台,一套代码,多端部署(便于移植)
    • IOS,Android,Windows Phone,Amazon-fireos,黑莓,Firefox OS,Ubuntu 和 tizien

不足:

  • Cordova 应用比原生应用慢(不适合做高性能应用)
  • Cordova 跨浏览器的兼容性差
  • Cordova 跨平台的兼容性有待提高(某些平台上的 API 还不支持)

官网: https://cordova.apache.org/
中文镜像:http://cordova.axuer.com/
Github: https://github.com/apache/cordova

默认情况下,Web 应用不能使用移动端功能(例如:定位,蓝牙,摄像头等)。通过 Cordova,我们可以使用 Web 技术,实现应用,同时,支持移动端功能。

架构图

在这里插入图片描述

二、环境搭建

整体来说,Cordova 需要的环境是 Node.js + 平台( 例如:Android 和 iOS 。环境搭建主要包含如下
内容:

  • Node.js 环境搭建
  • Git 安装
  • Android 环境搭建(JDK、Android Studio、Gradle)
    • JAVA_HOME
    • ANDROID_HOME、ANDROID_SDK_ROOT
    • PATH
  • iOS 环境搭建(Xcode)
    • npm i -g ios-sim
    • npm i -g ios-deploy
  • VS Code 编辑器(Cordova Tools插件)

Node.js 环境搭建

Node.js 的版本应大于等于 12 ,推荐安装 LTS 版本(去 Node.js 官网下载安装包)
安装之后,(为了提高下载速度)我们将 npm 镜像源,设置为淘宝的

1 # 修改 npm 的镜像源
2 npm config set registry https://registry.npm.taobao.org
3
4 # 验证是否更改成功(查看镜像源):
5 npm config get registry

Cordova 依赖 Git 命令行工具

Git 安装

如果未安装 Git for Windows,请先安装;
如果已安装 Git for Windows,请确保命令提示符或 PowerShell 中可运行 git 命令

Android 环境搭建

简介
JDK(Java Development Kit)是 Java 开发套件的简称。Android 开发,需要安装 JDK。
下载
下载地址:https://www.oracle.com/java/technologies/javase/javase-jdk8-downloads.html
请选择一个适合本地操作系统的安装包(操作系统+位数,例如:Windows x64)
下载时,提示需要登陆,我们可以先注册 Oracle 账户,登陆后再下载。
安装
下载完成后,双击安装包,开始安装(一直下一步就好,无需特殊配置)
设置 Java 环境变量
JAVA_HOME=C:\Program Files\Java\jdk1.8.0_

在这里插入图片描述

配置好 JAVA_HOME 后,可以再配置两个路径

在这里插入图片描述
检测安装结果
如果以下命令可以正常运行,则说明环境变量配置成功

1 java - version
2
3 javac

Android Studio

Android Studio (简称 AS)是安卓开发的编辑器和运行环境。使用之前,先下载。( 如已经安装,请略
过本节

下载地址:https://developer.android.com/studio/index.html

安装 Android SDK(可选)
正常来说,你可以忽略这一步。
因为 Android Studio 默认会安装最新版本的 Android SDK 。

打开 Android Studio,在菜单 Tools 下找到 “SDK Manager”

下载过程需要翻墙,下载安装内容很多,所以安装过程会很缓慢
Android SDK 是针对安卓开发的套件。
如果最新的 Android SDK 存在兼容性问题。这里你还可以单独安装,指定版本的 Android SDK。

在 SDK Manager 中选择"SDK Platforms"选项卡,然后,在右下⻆勾选"Show Package Details"。展
开指定版本(例如:Android 10 (Q))的选项,确保勾选了下面这些组件( 重申:你必须使用稳定的
翻墙工具,否则可能都看不到这个界面
):
Android SDK Platform 29
Intel x86 Atom_64 System Image(官方模拟器镜像文件,使用非官方模拟器不需要安装此组
件)

然后 点击"SDK Tools"选项卡,同样勾中右下⻆的"Show Package Details" 。展开"Android SDK
Build-Tools"选项,确保选中了29.0.2版本。

点击 OK 执行下载(这个下载时间也比较⻓,同时确保翻墙工具稳定可用)

下载完成后,点击 Finish

设置 Android 环境变量
ANDROID_HOME=C:\Users\你的名字\AppData\Local\Android\Sdk
ANDROID_SDK_ROOT=C:\Users\你的名字\AppData\Local\Android\Sdk

在这里插入图片描述

总共有两个内容,组件大小约:113.0 MB,安装后占用空间约:451.9 MB
如果下载过程中断,请重复选中以上两个组件,再次下载
例如,我本地下载中断,报错:SSL peer shut down incorrectly(网络中断报错)
只需要重复选中所需组件,再次下载即可 。

Gradle 安装

1. 下载
下载地址:https://services.gradle.org/distributions/
下载版本:建议使用 gradle-6.5-all.zip (我之前下载的 6.8 说太高了,而后又切换到 6.5)
2. 解压
下载后解压,将加压包放到任意位置(例如,我本地是 D:\Program Files\gradle-6.5)
3. 绑定环境变量
D:\Program Files\gradle-6.5\bin

在这里插入图片描述

4. 检测安装结果
1 gradle - v

iOS 环境搭建

Mac 上的相同内容的安装这里省略
例如:Node.js、Git、JDK、Android SDK、Gradle 等

安装 Xcode
在 App Store 中安装即可。安装完成后,再安装 iOS 模拟器。

安装部署工具

1 npm install - g ios-sim
2 npm install - g ios-deploy

VS Code 编辑器

下载地址:https://code.visualstudio.com/

在 VS Code 中编辑 Cordova 代码,最好安装 Cordova Tools 插件

在这里插入图片描述

三、初始化项目

当前平台信息( 注意平台版本,例如,Android 是 9.0,将来安装模拟器时,也要安装对应的版本

安装 Cordova CLI

1 npm install - g cordova
2
3 cordova - v

创建项目

1 cordova create HelloCordova io.cordova.hellocordova CordovaApp
2 # HelloCordova 应用程序的目录名称。
3 # io.cordova.hellocordova 项目唯一标识(默认的反向域值)。一般是点连接的语法
4 # CordovaApp 应用的标题。

添加平台

1 cd HelloCordova
2
3 # 浏览器
4 cordova platform add browser
5
6 # 安卓 添加 android 平台,并确保他们保存在了 config.xml 中
7 cordova platform add android --save
8
9 # 查看当前平台
10 cordova platform ls
1 Installed platforms:
2 android 9.0.
3 browser
4 Available platforms:
5 browser ^6.0.
6 electron ^1.0.
7 windows ^7.0.

模拟器安装截图
在这里插入图片描述

如果版本不兼容,后续运行 Cordova 时,模拟器可能无法启动。

运行

1 # 浏览器端运行
2 cordova run browser
3
4 # 安卓端运行
5 cordova run android # 真机调试
6 cordova emulate android # 模拟器启动

项目目录

hooks:钩子目录。每个Cordova 命令都可以定义 before 和 after 的 Hook,比如:before_build、
after_build
platforms:平台目录。例如 android、ios、browser 等
plugins:插件目录。安装的插件会放在这里
www:源代码目录。在执行 cordova prepare 的时候,源码会被 copy 到各个平台工程的 assets\www
目录下
config.xml:主配置文件,比如:项目使用了哪些插件、应用图标和启动⻚面

四、index.html

Meta

在这里插入图片描述

Content-Security-Policy(CSP)

网⻚安全策略(CSP)的实质就是白名单,开发者明确告诉客户端,哪些外部资源可以加载和执行,哪些
不可以。

CSP 的主要目标是减少和报告 XSS 攻击。大大增强了网⻚的安全性。攻击者即使发现了漏洞,也没法
注入脚本
两种方法可以启用 CSP

  • 通过 HTTP 头信息的 Content-Security-Policy 的字段
  • 通过网⻚的 标签
<meta http-equiv="Content-Security-Policy" content="default-src 's
elf' data: gap: https://ssl.gstatic.com 'unsafe-eval'; style-src
'self' 'unsafe-inline'; media-src *; img-src 'self' data: conten
t:;">

选项名

default-src :限制全局
script-src :外部脚本
style-src :样式表
img-src :图像
media-src :媒体文件(音频和视频)
font-src :字体文件
object-src :插件(比如 Flash)
child-src :框架
frame-ancestors :嵌入的外部资源(比如<frame>、<iframe>、<embed>和<applet>)
connect-src :HTTP 连接(通过 XHR、WebSockets、EventSource等)
worker-src :worker脚本
manifest-src :manifest 文件

default-src
用来设置上面各个选项的默认值。

Content-Security-Policy: default-src 'self'

上面代码限制所有的外部资源,都只能从当前域名加载。

如果同时设置某个单项限制(比如 style-src)和 default-src,前者会覆盖后者 ,即字体文件会采用
style-src 的值,其他资源依然采用 default-src 的值。

选项值

在这里插入图片描述
多个值也可以并列,用空格分隔。

1 Content-Security-Policy: script-src 'self' https://apis.google.com

Content-Security-Policy-Report-Only 表示不执行限制选项,只是记录违反限制的行为。

format-detection

<meta name="format-detection" content="telephone=no">
<meta name="format-detection" content="email=no">
<meta name="format-detection" content="adress=no">
 <!-- 也可以连写 -->
<meta name="format-detection" content="telephone=no,email=no,adress=no">
telephone
主要作用是:是否设置自动将你的数字转化为拨号连接
telephone=no 禁止把数字转化为拨号链接
telephone=yes 开启把数字转化为拨号链接,默认开启
email
告诉设备不识别邮箱,点击之后不自动发送
email=no 禁止作为邮箱地址
email=yes 开启把文字默认为邮箱地址,默认情况开启
adress
adress=no 禁止跳转至地图
adress=yes 开启点击地址直接跳转至地图的功能, 默认开启

msapplication-tap-highlight

关闭 Windows 上的触碰高亮

<meta name="msapplication-tap-highlight" content="no">

viewport

视口:是用户网⻚的可视区域。

一些设备上浏览器默认的 viewport 大小

在这里插入图片描述

用法:

参数:

  • **initial-scale:初始缩放比例,即是当⻚面第一次 load 的时候缩放比例。
  • width :控制 viewport 的大小,一般为了自适应设置为 device-width(设备宽度)**
  • maximum-scale:允许的最大缩放程度。是一个浮点值
  • minimum-scale:允许用户缩放到的最小比例。
  • user-scalable:是否允许用户进行缩放,值为 no 或 yes
  • viewport-fit=cover:解决 IphoneX tabbar 底部遮挡问题(是⻚面充满整个屏幕)

color-scheme

使网站支持多种模式(高亮模式、暗黑模式)。 当用户的系统主题更改后,网站样式随之更改。
如何实现:

  1. 声明可用模式
 <meta name="color-scheme" content="light dark">
  1. 针对不同模式,写不同的样式
1 body {
2 /* 默认为 light */
3 background-image:linear-gradient(to bottom, #A7A7A7 0%, #E4E
E4 51%);
4 }
5
6 @media screen and (prefers-color-scheme: dark) { /* 暗黑模式 */
7 body {
8 background-image:linear-gradient(to bottom, #585858 0%, #
1B1B1B 51%);
9 }
10 }

具体效果(以 Windows 为例)

高亮模式:
在这里插入图片描述
暗黑模式:
在这里插入图片描述

注意:并不是所有的浏览器都支持 color-scheme ,详情查看:https://www.caniuse.com/?search=color-scheme

[项目目录]/www/index.html 中引入的 cordova.js 不是当前目录下的。而是构建之后目录下的

cordova.js

 <script src="cordova.js"></script>

这里以 browser 平台为例来解释(如果没有添加 browser 平台,请先添加)
运行 browser

cordova run browser

然后观察 [项目目录]/platform/browser/www/ 目录,如下:

在这里插入图片描述

此时,平台的构建目录下,就有 cordova.js 了

实际上,平台下 cordova.js 来自于 [项目目录]/platform/[平台名称]/platform_www/cordova.js 不同
平台下的 cordova.js 内容不同

五、事件

Cordova 给我们提供了很多的事件。应用程序代码中可以添加这些事件的监听。

设备就绪

它是 Cordova 设备 API 准备好,并可以访问的信号。相当于 Web ⻚面中的 onload 事件。

其他后续事件,一般都写在 onDeviceReady 函数中

1 document.addEventListener('deviceready', onDeviceReady, false);
2
3 function onDeviceReady() {
4 // 设备就绪后的其他逻辑代码
5 }

应用挂起

1 function onDeviceReady() {
2 // 当前应用切换到后台时,触发 pause 事件
3 document.addEventListener('pause', function() {
4 alert('设备挂起');
5 })
6 }

应用回来

1 function onDeviceReady() {
2 // 当前应用由后台切换到前台时,触发 resume 事件
3 document.addEventListener('resume', function() {
4 alert('设备重新回来');
5 })
6 }

回退按钮

1 function onDeviceReady() {
2 // 点击回退按钮时,触发 backbutton 事件
3 document.addEventListener('backbutton', function() {
4 alert('回退按钮');
5 })
6 }

菜单按钮

1 function onDeviceReady() {
2 // 按下菜单按钮时,触发 menubutton 事件
3 document.addEventListener('menubutton', function() {
4 alert('按下菜单按钮');
5 })
6 }

更多详情:https://cordova.apache.org/docs/en/10.x/cordova/events/events.html

六、config.xml

简介

config.xml 是 Cordova 应用程序的全局配置文件。进行项目构建后,该文件会被复制到平台的子目录下。例如:

1 app/platforms/android/res/xml/config.xml
2 app/platforms/ios/AppName/config.xml
3 app/platforms/browser/config.xml

基本结构

1 <?xml?>
2 <widget>
3 <name>引用名称</name>
4 <description>应用描述</description>
5 <author>作者</author>
6
7 <content src="加载内容" />
8 <access origin="访问限制" />
9
10 <platform name="android">
11 <!-- 针对 Android 平台的配置 -->
12 <allow-intent href="market:*" />
13 </platform>
14 <platform name="ios">
15 <!-- 针对 iOS 平台的配置 -->
16 <allow-intent href="itms:*" />
17 <allow-intent href="itms-apps:*" />
18 </platform>
19 </widget>

上述配置是精简后的,不能直接用于项目

Widget

Widget 是 config.xml 文档的根元素。
在这里插入图片描述

1 <?xml version='1.0' encoding='utf-8'?>
2 <widget
3 id="io.cordova.hellocordova"
4 version="1.0.0"
5 xmlns="http://www.w3.org/ns/widgets"
6 xmlns:cdv="http://cordova.apache.org/ns/1.0"
7 >
8 <!- 其他配置 -->
9 </widget>

name

指定应用程序的正式名称,因为它出现在设备的主屏幕上

1 <name>HelloCordova</name>

description
指定可在应用商店上市出现的元数据

1 <description>A sample Apache Cordova application</description>

author
指定可在应用商店上市出现的联系人信息。

在这里插入图片描述

1 <author email="dev@cordova.apache.org" href="http://cordova.io"></
author>

content
声明应用的起始⻚面,默认是 index.html,指代 www 目录下的 index.html

1 <content src="startPage.html"></content>

access
声明与应用程序通信的外部域名集合。
允许访问所有域名

1 <access origin="*"></content>

允许访问指定域名

1 <access origin="http://google.com"></content>

allow-navigation

声明 WebView 可以导航到哪些 URL

1 <!-- 允许链接到 example.com -->
2 <allow-navigation href="http://example.com/*" />
3
4 <!-- 通配符设置协议, 子域名及域名下的路径 -->
5 <allow-navigation href="*://*.example.com/*" />

allow-intent

声明应用请求系统打开的 URL

1 <allow-intent href="http://*/*" />
2 <allow-intent href="https://*/*" />
3 <allow-intent href="tel:*" />
4 <allow-intent href="sms:*" />

engine
指定有关准备过程中要还原的平台的详细信息。

1 <engine name="android" spec="https://github.com/apache/cordova-and
roid.git#5.1.1" />
2 <engine name="ios" spec="^4.0.0" />

plugin

指定准备过程中要还原的插件的详细信息。

1 <plugin name="cordova-plugin-device" spec="^1.1.0" />
2 <plugin name="cordova-plugin-device" spec="https://github.com/apac
he/cordova-plugin-device.git#1.0.0" />

preference

偏好设置。设置各种 名/值 格式的属性。其中 大小写敏感。很多属性在特定平台下名称是唯一的。

1 <!-- 状态条的背景色 -->
2 <preference name="StatusBarBackgroundColor" value="#0000FF" />
3
4 <!-- Splash ⻚面的停留时间 -->
5 <preference name="SplashScreenDelay" value="3000" />

更多详情: http://cordova.axuer.com/docs/zh-cn/latest/config_ref/index.html#preference

platform

1 <platform name="android">
2 <!-- Android 平台下的配置 -->
3 <preference name="Fullscreen" value="true" />
4 </platform>

hook

特定动作发生时,需要执行的自定义脚本

1 <!-- type="钩子名称" src="执行脚本"
-->
2 <hook type="after_plugin_install" src="scripts/afterPluginInstall.
js" />

钩子详情:https://cordova.apache.org/docs/en/10.x/guide/appdev/hooks/index.html

更多详情:https://cordova.apache.org/docs/en/10.x/config_ref/index.html

七、Cordova 命令

基本语法

1 cordova <command> [options] -- [platformOpts]

查看帮助

1 cordova help

项目命令列表

命令 描述
info 生成项目信息
requirements 检查并打印指定平台的所有安装需求
platform 管理项目平台
plugin 管理项目插件
prepare 将文件复制到平台目录下,准备构建
compile 为平台编辑项目
build 为平台构建项目 (prepare + compile)
clean 从构建工件中清除项目
run 运行项目 (包括 prepare 和 compile)
serve 通过本地服务器运行项目 (包括 prepare)

创建项目

1 cordova create HelloCordova io.cordova.hellocordova CordovaApp
2 # HelloCordova 应用程序的目录名称。
3 # io.cordova.hellocordova 项目唯一标识(默认的反向域值)。一般是点连接的语法
4 # CordovaApp 应用的标题。

常用命令

1 cordova install android // 将编译好的应用程序安装到模拟器上
2 cordova emulate android // 在模拟器上运行
3 cordova serve android // 在浏览器运行
4 cordova build android // 打包 Cordova 项目到 android 平台。
5 cordova run android // 通过 USB 直接安装到真机(这里已经包括了 build
命令)

命令语法

这里以 管理平台 为例

cordova {platform | platforms} [
add <platform-spec> [...] {--save | link=<path> } |
{remove | rm} platform [...] |
 {list | ls} |
 check |
save ]

上述命令语法是官网给出的,可以拆分成如下命令

添加平台

1 cordova platform add android

删除平台

1 cordova platform remove android
2 # 或
3 cordova platform rm android

列出平台

1 cordova platform list
2 # 或
3 cordova platform ls

命令参数

通估参数,可以限制命令的执行效果。例如:

1 # 安装插件,并将插件记录在 package.json 中 (默认)
2 cordova plugin add cordova-plugin-geolocation --save
3
4 # 只安装插件,不记录在 package.json 中
5 cordova plugin add cordova-plugin-geolocation --nosave

更多详情:https://cordova.apache.org/docs/en/10.x/reference/cordova-cli/index.html

八、插件

cordova是一个注入代码包,允许Cordova webview在其中呈现的应用程序与运行它的本机平台进行通
信,提供基于web的应用程序与设备和平台功能的访问,所有主要的Cordova API功能都作为插件实
现,通俗点来说, cordova插件是连接web应用程序和设备平台之间的一个桥梁

电池状态

安装

1 cordova plugin add cordova-plugin-battery-status

使用

相机

安装

1 cordova plugin add cordova-plugin-camera

使用

联系人

安装

1 cordova plugin add cordova-plugin-contacts

使用

设备信息

安装

1 cordova plugin add cordova-plugin-device

使用

对话框

安装

1 cordova plugin add cordova-plugin-dialogs

使用

文件系统

安装

1 cordova plugin add cordova-plugin-file

使用

地理位置

安装

1 cordova plugin add cordova-plugin-geolocation

使用

全球化

安装

1 cordova plugin add cordova-plugin-globalization

使用

网络状态

安装

1 cordova plugin add cordova-plugin-network-information

使用

启动屏幕

安装

1 cordova plugin add cordova-plugin-splashscreen

使用

内置浏览器

安装

1 cordova plugin add cordova-plugin-inappbrowser

使用

扫码

安装

1 cordova plugin add cordova-plugin-qrscanner

使用

1 cordova plugin add cordova-plugin-barcodescanner

九、cordova-plugin-device

该插件用来获取设备信息,例如:操作系统,版本号

详情查看:https://www.npmjs.com/package/cordova-plugin-device

安装

1 cordova plugin add cordova-plugin-device

添加按钮

1 <button id="deviceInfo">设备信息</button>

添加事件监听

1 document.getElementById("deviceInfo").addEventListener("click", de
viceInfo);

获取设备信息

1 function deviceInfo() {
2 alert("Cordova version: " + device.cordova + "\n" +
3 "Device model: " + device.model + "\n" +
4 "Device platform: " + device.platform + "\n" +
5 "Device UUID: " + device.uuid + "\n" +
6 "Device version: " + device.version);
7 }

设备属性

device.cordova:获取 Cordova 版本
device.model:获取设备模型(包含制造商等相关信息)
device.platform:获取设备操作系统名称
device.uuid:获取设备唯一 ID
device.version:获取操作系统版本
device.manufacturer:获取设备制造商
device.isVirtual:判断是否运行在模拟器上
device.serial:获取设备的硬件号码

十、cordova-plugin-whitelist

该插件用来指定导航中的白名单策略

详情查看:https://www.npmjs.com/package/cordova-plugin-whitelist

安装

1 cordova plugin add cordova-plugin-whitelist

一般来说,Cordova 项目初始化时,会自动安装该插件

使用

白名单用来配置域名的访问规则。一般来说,有两个地方可以配置

  • config.xml 中
  • index.html 的 CSP 中

十一、cordova-plugin-inappbrowser

该插件允许在 Cordova 应用内部打开 Web 地址(例如:播放视频,查看文章等)。而不用跳出当前
App。

详情参考:https://www.npmjs.com/package/cordova-plugin-inappbrowser

安装

1 cordova plugin add cordova-plugin-inappbrowser

添加触发按钮

1 <button id="goBaidu">百度</button>

添加事件监听

1 document.getElementById("goBaidu").addEventListener("click", openB
aidu);

跳转

1 function openBaidu() {
2 var url = 'https://m.baidu.com'; // 跳转地址
3 var target = '_blank'; // 打开方式 _blank 新⻚面, _self 当前⻚, _s
ystem 系统浏览器中打开
4 var options = "location=yes" // 是否显示地址栏
5 var ref = cordova.InAppBrowser.open(url, target, options);
6
7 ref.addEventListener('loadstart', loadstartCallback);
8 ref.addEventListener('loadstop', loadstopCallback);
9 ref.addEventListener('loaderror', loaderrorCallback);

10 ref.addEventListener('exit', exitCallback);
11
12 function loadstartCallback(event) {
13 alert('Loading started: ' + event.url)
14 }
15
16 function loadstopCallback(event) {
17 alert('Loading finished: ' + event.url)
18 }
19
20 function loaderrorCallback(error) {
21 alert('Loading error: ' + error.message)
22 }
23
24 function exitCallback() {
25 alert('Browser is closed...')
26 }
27 }

跳转语法:cordova.InAppBrowser.open(url, target, options);也可以将其挂到 window 对象上:window.open = cordova.InAppBrowser.open;

选项参数

在这里插入图片描述

十二、cordova-plugin-camera

该插件允许使用摄像头拍照,或在相册中选取图片。

详情查看:https://www.npmjs.com/package/cordova-plugin-camera

安装

1 cordova plugin add cordova-plugin-camera

按钮:负责触发事件
图像:用来展示图片

添加按钮和图像

1 <button id="takePic">拍照</button>
2 <button id="getPic">从相册中选取</button>
3 <img id="myImage"></img>

添加事件监听

1 // 拍照
2 document.getElementById("takePic").addEventListener("click", takeP
ic);
3
4 // 从相册中选取
5 document.getElementById("getPic").addEventListener("click", getPic
);

拍照

1 const takePic = () => {
2 navigator.camera.getPicture(onSuccess, onFail, {

3 quality: 50 ,
4 destinationType: Camera.DestinationType.FILE_URI
5 });
6
7 function onSuccess(imageURI) {
8 var image = document.getElementById('myImage');
9 image.src = imageURI;
10 }
11
12 function onFail(message) {
13 alert('Failed because: ' + message);
14 }
15 }
语法:camera.getPicture(successCallback, errorCallback, options)

从相册中选取

1 const getPic = () => {
2 // alert('相册')
3 navigator.camera.getPicture(onSuccess, onFail, {
4 quality: 50 ,
5 destinationType: Camera.DestinationType.FILE_URI,
6 sourceType: Camera.PictureSourceType.PHOTOLIBRARY
7 });
8
9 function onSuccess(imageURL) {
10 var image = document.getElementById('myImage');
11 image.src = imageURL;
12 }
13
14 function onFail(message) {
15 alert('Failed because: ' + message);
16 }
17 }

拍照选项

在这里插入图片描述

十三、cordova-plugin-qrscanner

该插件可以执行扫码功能

详情查看:https://www.npmjs.com/package/cordova-plugin-qrscanner

安装

1 cordova plugin add cordova-plugin-qrscanner

初始化

1 var done = function(err, status){
2 if(err){
3 console.error(err._message);
4 } else {
5 console.log('QRScanner 初始化. 状态:');
6 console.log(status);
7 }
8 };
9
10 QRScanner.prepare(done);

扫描

1 var callback = function(err, contents) {
2 if(err){
3 console.error(err._message);
4 }
5 alert('扫描内容: ' + contents);
6 };
7 QRScanner.scan(callback);

取消扫描

1 QRScanner.cancelScan(function(status) {
2 console.log(status);
3 });

扫描开关

1 QRScanner.show(function(status) {
2 console.log(status);
3 });
4 QRScanner.hide(function(status) {
5 console.log(status);
6 });

闪光灯开关

1 QRScanner.enableLight(function(err, status) {
2 err && console.error(err);
3 console.log(status);
4 });
5 QRScanner.disableLight(function(err, status) {
6 err && console.error(err);
7 console.log(status);
8 });

切换摄像头

1 QRScanner.useFrontCamera(function(err, status) {
2 err && console.error(err);
3 console.log(status);
4 });
5 QRScanner.useBackCamera(function(err, status) {
6 err && console.error(err);

7 console.log(status);
8 });

销毁

1 QRScanner.destroy(function(status) {
2 console.log(status);
3 });

十四、cordova-plugin-geolocation

该插件可以获取位置信息(经纬度)

详情查看:https://www.npmjs.com/package/cordova-plugin-geolocation

安装

1 cordova plugin add cordova-plugin-geolocation

添加触发按钮

1 <button id="getPosition">获取位置</button>
2 <button id="watchPosition">监测位置</button>
也可以在⻚面加载时(例如:onload 或 deviceready),直接调用位置插件。

添加监听事件

1 document.getElementById("getPosition").addEventListener("click", g
etPosition);
2 document.getElementById("watchPosition").addEventListener("click",
watchPosition);

获取位置

1 function getPosition() {
2 var options = {
3 enableHighAccuracy: true, // 启用高精度
4 maximumAge: 3600000 // 最大请求时间(单位:毫秒)
5 }
6
7 var watchID = navigator.geolocation.getCurrentPosition(onSucce


ss, onError, options);
8
9 function onSuccess(position) {
10 alert('Latitude: ' + position.coords.latitude
+ '\n' + // 纬度
11 'Longitude: ' + position.coords.longitude
+ '\n' + // 经度
12 'Altitude: ' + position.coords.altitude
+ '\n' + // 高度
13 'Accuracy: ' + position.coords.accuracy
+ '\n' + // 精确度
14 'Altitude Accuracy: ' + position.coords.altitudeAccura
cy + '\n' + // 高度精确度
15 'Heading: ' + position.coords.heading
+ '\n' + // 方向
16 'Speed: ' + position.coords.speed
+ '\n' + // 速度
17 'Timestamp: ' + position.timestamp
+ '\n'); // 获取时间戳
18 };
19
20 function onError(error) {
21 // alert('code: ' + error.code + '\n' + 'message: ' +
error.message + '\n');
22 switch(error.code) {
23 case error.PERMISSION_DENIED:
24 alert("定位失败,用户拒绝请求地理定位");
25 break;
26 case error.POSITION_UNAVAILABLE:
27 alert("定位失败,位置信息是不可用");
28 break;
29 case error.TIMEOUT:
30 alert("定位失败,请求获取用户位置超时");
31 break;
32 case error.UNKNOWN_ERROR:
33 alert("定位失败,定位系统失效");
34 break;
35 }
36 }
37 }

监测位置

1 function watchPosition() {
2 var options = {
3 maximumAge: 3600000 ,
4 timeout: 3000 ,
5 enableHighAccuracy: true,
6 }
7
8 var watchID = navigator.geolocation.watchPosition(onSuccess, o
nError, options);
9
10 function onSuccess(position) {
11 alert('Latitude: ' + position.coords.latitude
+ '\n' +
12 'Longitude: ' + position.coords.longitude
+ '\n' +
13 'Altitude: ' + position.coords.altitude
+ '\n' +
14 'Accuracy: ' + position.coords.accuracy
+ '\n' +
15 'Altitude Accuracy: ' + position.coords.altitudeAccura
cy + '\n' +
16 'Heading: ' + position.coords.heading
+ '\n' +
17 'Speed: ' + position.coords.speed
+ '\n' +
18 'Timestamp: ' + position.timestamp
+ '\n');
19 };
20
21 function onError(error) {
22 alert('code: ' + error.code + '\n' +'message: ' + error.mes
sage + '\n');
23 }
24 }

取消监测

1 var watchID = navigator.geolocation.watchPosition(onSuccess, onErr
or, { enableHighAccuracy: true });
2
3 // ...later on...
4
5 navigator.geolocation.clearWatch(watchID);

对象属性

  • postion
    • coords: (Coordinates 类型 )地理坐标信息,包括经纬度、海拔、速度等信息
      • latitude: (Number) 纬度,数值(十进制)
      • longitude: (Number) 经度,数值(十进制)
      • altitude: (Number) 海拔-高度,数值(米)
      • accuracy: (Number) 精确度,数值(米)
      • altitudeAccuracy: (Number) 海拔的精确度,数值(米)
      • heading: (Number) 设备移动的方向,数值(度)
      • speed: (Number) 设备移动的速度
    • coordsType: (String) 坐标系类型,
      • gps:WGS-84 坐标系
      • gcj02:国测局经纬度坐标系
      • bd09:百度墨卡托坐标系
      • bd09ll:百度经纬度坐标系
    • timestamp: (Number) 获取坐标的时间戳
    • address: (Address) 地理位置对应的地址信息, 可以通过设置 PositionOptions 参数的 geocode 属性值为 false 避免获取地址信息
    • addresses: (String) 获取完整地址描述信息
  • PositionOptions
    • enableHighAccuracy: (Boolean) 是否高精确度获取位置信息
    • timeout: (Number 毫秒) 获取位置信息的超时时间
    • maximumAge: (Number 毫秒 ) 获取位置信息的间隔时间,默认 5000 不是很准
    • provider: (String 类型 )优先使用的定位模块
      • system: 系统定位
      • baidu: 百度定位
      • amap: 高德定位
      • 默认 amap>baidu>system
    • coordsType: (String) 指定获取的定位数据坐标系类型, wgs84, gcj02, bd09, bd09ll
    • geocode: (Boolean) 是否解析地址信息, 默认为 true

十五、cordova-plugin-globalization

该插件可以获取全球化信息,包括:语言,日期和时区,货币等。

详情查看:https://www.npmjs.com/package/cordova-plugin-globalization

安装

1 cordova plugin add cordova-plugin-globalization

添加触发按钮

1 <button id="getLanguage">语言</button>
2 <button id="getLocaleName">地域</button>
3 <button id="getDate">日期</button>
4 <button id="getCurrency">货币</button>

添加事件监听

1 document.getElementById("getLanguage").addEventListener("click", g
etLanguage);
2 document.getElementById("getLocaleName").addEventListener("click",
getLocaleName);
3 document.getElementById("getDate").addEventListener("click", getDa
te);
4 document.getElementById("getCurrency").addEventListener("click", g
etCurrency);

获取语言

1 function getLanguage() {
2 navigator.globalization.getPreferredLanguage(onSuccess, onError

);
3
4 function onSuccess(language) {
5 // zh-CN | en-US
6 alert('language: ' + language.value + '\n');
7 }
8
9 function onError(){
10 alert('Error getting language');
11 }
12 }

获取地域

1 function getLocaleName() {
2 navigator.globalization.getLocaleName(onSuccess, onError);
3
4 function onSuccess(locale) {
5 // en-US
6 alert('locale: ' + locale.value);
7 }
8
9 function onError(){
10 alert('Error getting locale');
11 }
12 }

获取日期

1 function getDate() {
2 var date = new Date();
3
4 var options = {
5 formatLength:'short',
6 selector:'date and time'
7 }
8

9 navigator.globalization.dateToString(date, onSuccess, onError,
options);
10
11 function onSuccess(date) {
12 // 12/4/2021 6:46 PM
13 alert('date: ' + date.value);
14 }
15
16 function onError(){
17 alert('Error getting dateString');
18 }
19 }

获取货币

1 function getCurrency() {
2 var currencyCode = 'EUR';
3 navigator.globalization.getCurrencyPattern(currencyCode, onSucc
ess, onError);
4
5 function onSuccess(pattern) {
6 alert('pattern: ' + pattern.pattern + '\n' +
7 'code: ' + pattern.code + '\n' +
8 'fraction: ' + pattern.fraction + '\n' +
9 'rounding: ' + pattern.rounding + '\n' +
10 'decimal: ' + pattern.decimal + '\n' +
11 'grouping: ' + pattern.grouping);
12 }
13
14 function onError(){
15 alert('Error getting pattern');
16 }
17 }

方法详情

在这里插入图片描述

十六、cordova-plugin-splashscreen

该插件可以设置 App 的启动⻚面和图标

打开项目目录下的 config.xml,在 widget 中添加配置项

详情查看:https://www.npmjs.com/package/cordova-plugin-splashscreen

安装

1 cordova plugin add cordova-plugin-splashscreen

添加启动屏幕

打开项目目录下的 config.xml,在 widget 中添加配置项

1 <platform name="android">
2 <splash src="res/screen/android/splash.png" density="hdpi" />
3 <splash src="res/screen/android/splash.png" density="ldpi" />
4 <splash src="res/screen/android/splash.png" density="mdpi" />
5 <splash src="res/screen/android/splash.png" density="xhdpi" /
>
6 <splash src="res/screen/android/splash.png" density="xxhdpi"
/>
7 <splash src="res/screen/android/splash.png" density="xxxhdpi"
/>
8
9 <icon src="res/screen/android/mipmap-ldpi/icon.png" density=
"ldpi" />
10 <icon src="res/screen/android/mipmap-mdpi/icon.png" density=
"mdpi" />
11 <icon src="res/screen/android/mipmap-hdpi/icon.png" density=
"hdpi" />
12 <icon src="res/screen/android/mipmap-xhdpi/icon.png" density=
"xhdpi" />
13 <icon src="res/screen/android/mipmap-xxhdpi/icon.png" density
="xxhdpi" />

14 <icon src="res/screen/android/mipmap-xxxhdpi/icon.png" densit
y="xxxhdpi" />
15 </platform>
16
17 <platform name="ios">
18 <!-- ios 设置省略 -->
19 </platform>
图标可以针对不同尺寸的屏幕生成。生成网站:https://icon.wuruihong.com/
因为 splash 图片的生成收费,因此,我这里用了同一张图片
另外,还可以通过 land 和 port 前缀指定横屏和竖屏的 splash
<splash src="res/screen/android/splash.png" density="land-hdpi" /> <!-- 横屏启动⻚ -->
<splash src="res/screen/android/splash.png" density="port-hdpi" /> <!-- 竖屏启动⻚ -->
详情查看 扩展知识

设置启动屏幕

1 <preference name="SplashScreenDelay" value="3000" /> <!--
启动时⻓,单位:毫秒 -->
2 <preference name="FadeSplashScreen" value="false"/> <!--
启动淡入淡出 -->
3 <preference name="FadeSplashScreenDuration" value="750"/> <!--
淡入淡出时⻓,默认 500 -->
4 <preference name="SplashMaintainAspectRatio" value="true" /> <!--
true:不拉伸图片,默认 false -->
5 <preference name="SplashShowOnlyFirstTime" value="true" /> <!--
只启动一次 -->

扩展知识

两种布局

  • land (landscape - 横屏)
  • port (portrait - 竖屏)

密度为每平方英寸(inch)中的像素(px)数,常用 dpi (Dots Per Inch - 每英寸点数)来表示。
ldpi 低密度
mdpi 中等密度
hdpi 高密度

密度

屏幕大小

在这里插入图片描述

十七、cordova-plugin-network-information

该插件可以获取本地网络信息。

详情查看:https://www.npmjs.com/package/cordova-plugin-globalization

安装

1 cordova plugin add cordova-plugin-network-information

添加按钮

1 <button id="networkInfo">网络详情</button>

添加监听事件

1 document.getElementById("networkInfo").addEventListener("click", n
etworkInfo);
2 document.addEventListener("offline", onOffline, false);
3 document.addEventListener("online", onOnline, false);

声明函数

1 function networkInfo() {
2 var networkState = navigator.connection.type;
3 var states = {};
4
5 states[Connection.UNKNOWN] = 'Unknown connection';
6 states[Connection.ETHERNET] = 'Ethernet connection';
7 states[Connection.WIFI] = 'WiFi connection';
8 states[Connection.CELL_2G] = 'Cell 2G connection';


9 states[Connection.CELL_3G] = 'Cell 3G connection';
10 states[Connection.CELL_4G] = 'Cell 4G connection';
11 states[Connection.CELL] = 'Cell generic connection';
12 states[Connection.NONE] = 'No network connection';
13
14 alert('Connection type: ' + states[networkState]);
15 }
16
17 function onOffline() {
18 alert('网络掉线!');
19 }
20
21 function onOnline() {
22 alert('网络在线!');
23 }

十八、cordova-plugin-battery-status

该插件用于获取终端电池的状态

详情查看:https://www.npmjs.com/package/cordova-plugin-battery-status

安装

1 cordova plugin add cordova-plugin-battery-status

添加监听事件

1 window.addEventListener("batterystatus", onBatteryStatus, false);

创建回调函数

1 function onBatteryStatus(info) {
2 alert("BATTERY STATUS: Level: " + info.level + " isPlugged: "
 + info.isPlugged);
3 }
  • level : 剩余电量的百分比 (0-100)
  • isPlugged : 是否正在充电

插件除了 batterystatus 事件之外,还有两个事件。这些事件的使用方式与 batterystatus 事件相同。

其他事件

在这里插入图片描述

十九、cordova-plugin-statusbar

该插件用来设置终端顶部状态条

详情查看:https://www.npmjs.com/package/cordova-plugin-statusbar

安装

1 cordova plugin add cordova-plugin-statusbar

配置

1 <!-- 状态栏是否覆盖 WebView -->
2 <preference name="StatusBarOverlaysWebView" value="true" />
3
4 <!-- 状态栏背景色 -->
5 <preference name="StatusBarBackgroundColor" value="#000000" />
6
7 <!-- 状态栏样式,可用选项:default, lightcontent, blacktranslucent, b
lackopaque -->
8 <preference name="StatusBarStyle" value="lightcontent" />
9
10 <!-- 在 iOS 上,是否允许 WebView 使用默认的 scroll-to-top 行为 -->
11 <preference name="StatusBarDefaultScrollToTop" value="false" />

使用

1 // 是否覆盖 WebView
2 StatusBar.overlaysWebView(true);
3
4 // 使用默认样式(黑色文字,白色背景)
5 StatusBar.styleDefault();
6
7 // 使用高亮样式(白色文字,黑色背景)


8 StatusBar.styleLightContent();
9
10 // 黑色半透明样式
11 StatusBar.styleBlackTranslucent();
12
13 // 黑色不透明样式
14 StatusBar.styleBlackOpaque();
15
16 // 通过颜色单词设置背景色,
17 // 支持的颜色由:
18 // black, darkGray, lightGray, white, gray, red, green,
19 // blue, cyan, yellow, magenta, orange, purple, brown
20 StatusBar.backgroundColorByName("red");
21
22 // 通过十六进制声明背景颜色
23 StatusBar.backgroundColorByHexString("#C0C0C0");
24
25 // 隐藏状态栏
26 StatusBar.hide();
27
28 // 显示状态栏
29 StatusBar.show();
30
31 // 判断状态栏是否可⻅
32 StatusBar.isVisible
33
34 // 状态栏是否被触碰(该事件只支持 iOS 平台)
35 window.addEventListener('statusTap', function() {
36 // scroll-up with document.body.scrollTop = 0; or do whatever
you want
37 });

二十、自定义插件

本节实现自定义 Cordova 插件

安装 Plugman

1 npm install -g plugman

Cordova 通过 Plugman 来创建插件

创建插件

注意:存放插件的目录,不能有中文和空格等特殊符号。例如:我先创建一个目录 cordovaplugin,然后
cd 进入

1 plugman create --name [插件名] --plugin_id [插件id] --plugin_
version [插件版本]
2 plugman create --name MyToast --plugin_id me.cliu.mytoast --plugin
_version 1 .0.0
3
4 cd MyToast
插件名:建议使用大驼峰
插件 id:建议使用 Java 包的命名方式,例如:me.cliu.mytoast
插件版本:三级写法 1.0.0

生成插件的目录结构:

1 MyToast
2 ├── src 平台源码
3 ├── www 原生 JS
4 │ └── MyToast.js
5 └── plugin.xml 插件配置文件

初始的 MyToast.js 代码

1 var exec = require('cordova/exec');
2
3 exports.coolMethod = function (arg0, success, error) {
4 exec(success, error, 'MyToast', 'coolMethod', [arg0]);
5 };

初始的 plugin.xml 代码

1 <?xml version='1.0' encoding='utf-8'?>
2 <plugin
3 id="me.cliu.mytoast"
4 version="1.0.0"
5 xmlns="http://apache.org/cordova/ns/plugins/1.0"
6 xmlns:android="http://schemas.android.com/apk/res/android"
7 >
8 <name>MyToast</name>
9 <js-module name="MyToast" src="www/MyToast.js">
10 <clobbers target="cordova.plugins.MyToast" />
11 </js-module>
12 </plugin>

在这里插入图片描述

添加支持平台

进入插件目录之后(cd MyToast),我们添加插件支持的平台

1 plugman platform add --platform_name android # 安卓平台支持
2 plugman platform add --platform_name ios # iOS 平台支持(不支持
可以不添加)

添加完平台后,插件src下会多出两个目录

1 MyToast
2 ├── src
3 ├──── android # 安卓平台支持
4 │ └── MyToast.java
5 ├──── ios # iOS 平台支持
6 │ └── MyToast.m
7 ├── www
8 │ └── MyToast.js
9 └── plugin.xml

src/android/MyToast.java

如果没有调整的内容,则不需要编辑

1 package me.cliu.mytoast;
2
3 import org.apache.cordova.CordovaPlugin;
4 import org.apache.cordova.CallbackContext;
5
6 import org.json.JSONArray;
7 import org.json.JSONException;
8 import org.json.JSONObject;
9
10 /**
11 * This class echoes a string called from JavaScript.

12 */
13 public class MyToast extends CordovaPlugin {
14
15 @Override
16 public boolean execute(String action, JSONArray args, Callbac
kContext callbackContext) throws JSONException {
17 if (action.equals("coolMethod")) {
18 String message = args.getString( 0 );
19 this.coolMethod(message, callbackContext);
20 return true;
21 }
22 return false;
23 }
24
25 private void coolMethod(String message, CallbackContext callb
ackContext) {
26 if (message != null && message.length() > 0 ) {
27 callbackContext.success(message);
28 } else {
29 callbackContext.error("Expected one non-empty string
argument.");
30 }
31 }
32 }

此时,我们再来看一下 www/MyToast.js

1 var exec = require('cordova/exec');
2
3 exports.coolMethod = function (arg0, success, error) {
4 exec(success, error, 'MyToast', 'coolMethod', [arg0]);
5 // 执行(成功, 失败, 类名, 方法名, 参数);
6 };

此时,我们可以调整代码内容。例如:方法名可以自定义
但是 www/MyToast.js 中的类名和方法名,需要与 src/android/MyToast.java 中保持一致

plugin.xml

目的:熟悉 plugin.xml 中各个配置项的含义

1 <?xml version='1.0' encoding='utf-8'?>
2 <plugin
3 id="me.cliu.mytoast"
4 version="1.0.0"
5 xmlns="http://apache.org/cordova/ns/plugins/1.0"
6 xmlns:android="http://schemas.android.com/apk/res/android"
7 >
8 <name>MyToast</name>
9 <!--JS 代码的位置 -->
10 <js-module name="MyToast" src="www/MyToast.js">
11 <clobbers target="cordova.plugins.MyToast" />
12 </js-module>
13
14 <!--添加 Android 平台 -->
15 <platform name="android">
16 <config-file parent="/*" target="res/xml/config.xml">
17 <!-- JS调用时的名字 -->
18 <feature name="MyToast">
19 <!-- value:的值是对应的插件中 MyToast.java 存放的路径 -->
20 <param name="android-package" value="me.cliu.mytoast.MyTo
ast" />
21 </feature>
22 </config-file>
23 <config-file parent="/*" target="AndroidManifest.xml"></confi
g-file>
24
25 <!--
26 src:是插件里存放对应 .java 的路径,
27 target-dir:安装插件时把 .java 文件存放的位置,要和上面的 val
ue 路径对应
28 -->
29 <source-file
30 src="src/android/MyToast.java"
31 target-dir="src/me/cliu/mytoast/MyToast"
32 />
33 </platform>
34 </plugin>

进入到插件目录,然后运行

[项目目录]/www/index.html 中添加如下一行

www/MyToast.js

1 var exec = require('cordova/exec');
2
3 // MyToast: 是 plugin.xml 文件中的 feature 标签 name 属性
4 // coolMethod:是 js 中调用的方法名
5 // [arg0]: 表示一个参数,[arg0, arg1]:表示两个参数
6 exports.coolMethod = function (arg0, success, error) {
7 exec(success, error, 'MyToast', 'coolMethod', [arg0]);
8 };

初始化插件

1 cd MyToast
2 npm init
3
4 # 或
5 plugman createpackagejson [插件路径]
根据提示一路向下,最终会在插件目录下生成 package.json

在项目中安装自定义插件

1 cd [Cordova项目目录]
2 cordova plugin add [插件路径]
3
4 // 我本地
5 cordova plugin add D:\cliu\HelloCordova\MyToast

声明触发按钮

1 <button id="toast">点我提示</button>

[项目目录]/www/js/index.js 中添加如下内容

调用自定义插件

1 function onDeviceReady() {
2 // ....
3
4 // 添加这一行
5 document.getElementById("toast").addEventListener("click", ca
llMyToast);
6 }
7
8 // 调用自定插件
9 function callMyToast() {
10 cordova.plugins.MyToast.coolMethod('Hello', toastSuccess, toa
stFail);
11
12 function toastSuccess(msg) {
13 alert('toast success'+msg)
14 }
15 function toastFail() {
16 alert('toast fail')
17 }
18 }

十三、项目

现在,我们已经掌握 Cordova 的基本内容了。接下来,我们就通过 Cordova 来开发一款 App。

App = 移动功能 + Web 界面

移动功能可以通过 Cordova 的插件实现
Web 界面可以自己写 HTML、CSS 和 JS。也可以借助成熟的前端框架(例如 Vue)。这样可以提高开
发效率。

Cordova 和 Vue 我们已学过。怎么将二者结合起来呢?

其实逻辑很简单: 将 Vue 项目的打包目录,设置为 Cordova 项目的 www 项目。

这样,我们先打包 Vue,然后运行 Cordova 就可以了。

Vue 项目初始化

安装 Vue CLI

1 npm install -g @vue/cli

创建 Vue 项目

1 vue create vc

手动选择特征
在这里插入图片描述

去掉 Linter,选中 Router 和 Vuex
在这里插入图片描述

选择 Vue 3.x
在这里插入图片描述

不使用 history 模式的路由(App 中,只支持 hash 模式)
Vue 项目将来会通过 Cordova 打包成 App,这里的路由模式不能选 history

在这里插入图片描述

默认,继续

在这里插入图片描述

默认,继续

在这里插入图片描述

如果一切顺利,则项目创建完成

运行项目

1 cd [Vue 项目目录]
2 npm run serve

十四、Vue 集成 Cordova

本节的目标是将 Vue 项目和 Cordova 合并在一起。通过 Vue 实现非移动端的功能,通过 Cordova 实现移动端的功能。

进入 Vue 项目

1 cd [你的 Vue 项目目录]

修改 Vue 打包位置

在 Vue 项目目录下声明 vue.config.js

1 module.exports = {
2 publicPath: './', // 必填
3 outputDir: 'www', // 打包后的目录名称(为了适配 Cordova,这里必须写成 ww
w)
4 assetsDir: '', // 静态资源目录名称
5 productionSourceMap: false, // 去掉打包的时候生成的 map 文件
6 lintOnSave: false,
7 }

修改 Vue 中的 index.html

在 public/index.html 的 head 中添加 Cordova 需要的 meta 标签

1 <!DOCTYPE html>
2 <html lang="">
3 <head>
4 <!-- 其他内容 -->
5 <meta http-equiv="Content-Security-Policy" content="default-s
rc 'self' data: gap: https://ssl.gstatic.com 'unsafe-eval'; style
-src 'self' 'unsafe-inline'; media-src *; img-src 'self' data: co
ntent:;">
6 <meta name="format-detection" content="telephone=no">

7 <meta name="msapplication-tap-highlight" content="no">
8 <meta name="viewport" content="initial-scale=1, width=device-
width, viewport-fit=cover">
9 <meta name="color-scheme" content="light dark">
10 <!-- 其他内容 -->
11 </head>
12
13 <!-- 其他内容 -->
14 </html>

在 public/index.html 的 body 中添加 cordova.js
通过判断环境来区分 Vue 还是 Cordova。只有 Cordova 运行时,才能加载到 cordova.js

1 <% if (process.env.NODE_ENV === 'production') { %>
2 <script src="cordova.js"></script>
3 <% } %>

修改 Vue 中的 main.js

在 src/main.js 中添加 Cordova 的 deviceready 事件

1 if (process.env.NODE_ENV === 'production') {
2 document.addEventListener('deviceready', function() {
3 app.mount('#app')
4 }, false);
5 } else {
6 app.mount('#app')
7 }

执行构建

这一步的目的是打包出 www 目录,www 目录是 Cordova 必须的源码目录

1 npm run build

将 Cordova 中的 config.xml 复制到 Vue 项目中

先创建一个 Cordova 项目

1 cordova create vc io.cordova.vc CordovaApp

然后将 Cordova 中的 config.xml 复制到 Vue 项目中

如果 Vue 项目中没有 config.xml,会有如下报错
报错:Current working directory is not a Cordova-based project
原因:当前项目中不包含 Cordova 项目的 config.xml
解决:创建 Cordova 项目
cordova create cdva io.cordova.cdva CordovaApp
将 Cordova 项目中的 config.xml 复制到 Vue 项目中

添加平台

由于 Cordova 初始化项目的配置文件(config.xml)中不包含平台信息,因此,在运行之前先添加平台支
持。
此时,可以在 Vue 项目中直接运行下面的命令

1 cordova platform add android --save

添加白名单插件

1 cordova plugin add cordova-plugin-whitelist
2 cordova prepare

运行

1 cordova run android

将 Cordova 命令集成到 Vue 命令中

安装 Cordova 相关插件
1 npm install corodva-lib # 包含 Cordova 和 Plugman 的常用命令
自定义 Cordova 命令

在 Vue 项目目录下创建 cdva.js。目的是将 Cordova 命令,集成到 Vue 命令中。

1 const { cordova } = require('cordova-lib')
2
3 // 清除
4 const clean = api => {
5 api.registerCommand('clean', args => {
6 return cordova.clean()
7 .catch(console.error)
8 })
9 }
10
11 // 构建
12 const build = api => {
13 const { build } = api.service.commands
14
15 const originalBuild = build.fn
16
17 build.fn = (...args) => {
18 return originalBuild(...args)
19 .then(() => cordova.prepare())
20 .then(() => cordova.compile({ options: args[ 0 ] }))
21 .catch(console.error)
22 }
23 }
24
25 // 运行
26 const develop = api => {
27 api.registerCommand('develop', args => {
28 return cordova.run()
29 .catch(console.error)
30 })
31 }
32
33 // 将命令导出

34 module.exports = (api, options) => [clean, build, develop].map(fn
=> fn(api, options))
修改 package.json

添加上述命令的支持代码

1 {
2 // ....
3 "scripts": {
4 "clean": "vue-cli-service clean",
5 "serve": "vue-cli-service serve",
6 "build": "vue-cli-service build",
7 "develop": "vue-cli-service develop"
8 },
9 "vuePlugins": {
10 "service": [
11 "cdva.js"
12 ]
13 },
14 // ....
15 }
vue-cli-service: https://cli.vuejs.org/guide/cli-service.html#vue-cli-service-inspect
vuePlugins: https://cli.vuejs.org/guide/plugins-and-presets.html#installing-plugins-in-an-
existing-project
通过 develop 运行 Cordova
1 npm run develop

十五、实时调试

Cordova 没有热更新,所以每次代码修改后,都需要重新启动才能看到效果。这里,我们可以通过 Vue的热更新,来近似地实现 Cordova 的实时调试。

启动 Vue 项目

1 cd [Vue 项目目录]
2 npm run serve

注意查看启动后的 公网 IP 地址 ,稍后会用来 Cordova 的 config.xml 中

在这里插入图片描述

修改 config.xml

将 Cordova 默认加载的地址,由本地的 index.html 改成上面 Vue 的 公网 IP 地址

在这里插入图片描述

启动 Cordova

1 cordova run android

查看实时更新

此时可以修改 Vue ⻚面中的内容,查看 App 端是否实时更新

注意:这里只是利用 Vue 的热更新来 近似地 实现 Cordova 的实时调试。但是,App 端的功能毕竟在浏
览器上不能调试。使用时,请注意区分。

十六、新闻列表

使用 Vant

安装 Vant 3
Vant 真的会 Vue 3 也针对性地推出了 Vant 3(对应的包叫 vant@next)

1 npm i vant@next -S

Vant 详情:https://github.com/youzan/vant
Vant 效果:https://vant-contrib.gitee.io/vant/v3/
引入 Vant

1 // ...
2 import Vant from 'vant'
3 import 'vant/lib/index.css'
4
5 const app = createApp(App)
6 app.use(Vant) // 使用 Vant
7 // ...

Tab 导航

声明⻚面
声明三个⻚面
首⻚:src/views/home/index.vue
新闻:src/views/news/index.vue
我: src/views/user/index.vue
声明路由
在 src/router/index.js 中,为上述三个⻚面声明路由

1 const routes = [
2 {
3 path: '/',
4 name: 'home',
5 component: () => import('@/views/home/index')
6 },
7 {
8 path: '/news',
9 name: 'news',
10 component: () => import('@/views/news/index')
11 },
12 {
13 path: '/user',
14 name: 'user',
15 component: () => import('@/views/user/index')
16 },

声明导航
声明 src/components/ LayoutFooter.vue

1 <template>
2 <div class="layout-footer">
3 <van-tabbar route>
4 <van-tabbar-item replace to="/" icon="orders-o">首⻚</van-ta
bbar-item>
5 <van-tabbar-item replace to="/news" icon="desktop-o">新闻</v
an-tabbar-item>
6 <van-tabbar-item replace to="/user" icon="user-o">我</van-t
abbar-item>
7 </van-tabbar>
8 </div>
9 </template>
10
11 <script>
12 export default {
13 name: 'LayoutFooter',
14 data () {
15 return {}
16 }
17 }
18 </script>

这里,使用 Vant 中的 Tabbar 来实现导航。
Tabbar 详情:https://vant-contrib.gitee.io/vant/v3/#/zh-CN/tabbar

引入导航
在 App.vue 中,引入 LayoutFooter.vue

1 <template>
2 <router-view />
3 <LayoutFooter />
4 </template>
5
6 <script>
7 import LayoutFooter from '@/components/LayoutFooter.vue'
8
9 export default {
10 name: 'App',
11 components: {
12 LayoutFooter
13 }
14 }
15 </script>

新闻⻚

新闻⻚ = Axios 请求接口 + 列表布局
安装 Axios
1 npm install axios
Axios 详情:https://github.com/axios/axios
封装 Axios
创建 src/api/http.js

1 import axios from 'axios'
2
3 // 创建 axios 实例

4 const service = axios.create({
5 timeout: 5000 // 请求超时时间
6 })
7
8 // 请求拦截器
9 service.interceptors.request.use(config => {
10 config.headers['Accept'] = 'application/json'
11 // config.data = Object.assign({}, config.data, {
12 // authToken: 'tokenplaceholder_xxxxxxxx'
13 // });
14
15 return config
16 }, error => {
17 Promise.reject(error)
18 })
19
20 // 响应拦截器
21 service.interceptors.response.use(
22 response => {
23 // console.log(response)
24 if (response.status === 200 ) {
25 return response.data
26 } else {
27 console.log('响应数据报错')
28 return Promise.reject(response)
29 }
30 },
31 error => {
32 if (error.response) {
33 const res = error.response.data
34 // todo
35 return res
36 } else {
37 return Promise.reject(error)
38 }
39 }
40 )
41
42 export default service

申请接口
新闻头条地址:https://www.juhe.cn/docs/api/id/235

申请方式参考官网介绍。
注意: 免费的新闻接口,每天只能访问 100 次。建议自己申请一个秘钥 (如果都用老师的,访问可能受限)

请求接口
声明 src/api/index.js

1 import http from './http'
2
3 var newsAPI = ""
4 if (process.env.NODE_ENV === 'production') {
5 newsAPI = "http://v.juhe.cn" // cordova 中没有跨域。可以直接调用域名
6 } else {
7 newsAPI = "/news" // vue 中的跨域代理
8 }
9
10 // 新闻列表
11 export function newsList(type = 'top', page = 1 , pageSize = 10 ) {
12 return http.get(newsAPI + '/toutiao/index', {
13 params: {
14 key: '你的请求秘钥',
15 type,
16 page,
17 pageSize
18 }
19 })
20 }

解决跨域
在 vue.config.js 中,声明 proxy

1 module.exports = {
2 devServer: {
3 proxy:{
4 '/api': {
5 target: "http://v.juhe.cn",
6 changeOrigin:true, // 是否改变请求源

7 pathRewrite:{ // 路径重写
8 "^/api":''
9 }
10 }
11 }
12 }

调用接口

1 import { newsList } from '@/api'
2
3 newsList(this.type, this.page, this.pageSize).then((res) => {
4 this.loading = false;
5
6 if (res.error_code === 0 ) {
7 console.log(res.result.data)
8 this.news = this.news.concat(res.result.data)
9 } else {
10 this.finished = true
11 }
12 }).catch((err) => {
13 console.log(err)
14 })

展示列表

1 <template>
2 <div>
3 <van-list
4 v-for="item in news"
5 :key="item.uniquekey"
6 >
7 <van-cell>
8 <template #icon>
9 <img :src="item.thumbnail_pic_s" alt="" style="width:3r
em;height:2rem; margin-right:.2rem">
10 </template>
11


12 <template #title>
13 <span class="custom-title">{{item.title.substring(0,26)
+ '...'}}</span>
14 </template>
15
16 <template #label>
17 <span style="font-size: 12px;">{{item.date}}</span>
18 &nbsp;&nbsp;
19 <span style="font-size: 12px;">{{item.author_name.subst
ring(0,5)}}</span>
20 </template>
21 </van-cell>
22 </van-list>
23 </div>
24 </template>

十七、天气预报

之前,我们通过 cordova-plugin-geolocation 获取了地理位置,接下来,我们可以通过地理位置来查询天气。

获取地理位置

首先要安装 cordova-plugin-geolocation

1 const getPosition = () => {
2 var options = {
3 enableHighAccuracy: true,
4 maximumAge: 1000 , // 毫秒为单位
5 }
6 navigator.geolocation.getCurrentPosition(onSuccess, onError, op
tions)
7 function onSuccess(position) {
8 alert('经度:' + position.coords.longitude + "\n" +
9 '纬度:' + position.coords.latitude + "\n"
10 );
11 }
12
13 function onError(error) {
14 alert("Code: " + error.code + "\n Message: " + error.messag
e)
15 }
16 }

申请天气接口

https://dev.qweather.com/docs/api/weather/

声明接口

1 import http from './http'
2
3 var weatherProxy = ""

4 if (process.env.NODE_ENV === 'production') {
5 weatherProxy = "https://devapi.qweather.com/v7/weather"
6 } else {
7 weatherProxy = "/weather"
8 }
9
10
11 // 3天的天气预报
12 export function get3d(location) {
13 return http.get(
14 weatherProxy + '/3d',
15 {
16 params: {
17 key: "687e517f06684448a9f4695721414a07",
18 location
19 }
20 }
21 )
22 }

设置代理

编辑 vue.config.js

1 module.exports = {
2 outputDir: 'www',
3 publicPath: './',
4 devServer: {
5 proxy: {
6 "/weather" : {
7 target: 'https://devapi.qweather.com/v7/weather',
8 changeOrigin: true,
9 pathRewrite: {
10 "^/weather": ""
11 }
12 }
13 }
14 }
15 }

调用接口

1 const getPosition = () => {
2 var options = {
3 enableHighAccuracy: true,
4 maximumAge: 1000 , // 毫秒为单位
5 }
6 navigator.geolocation.getCurrentPosition(onSuccess, onError, op
tions)
7 function onSuccess(position) {
8 alert('经度:' + position.coords.longitude + "\n" +
9 '纬度:' + position.coords.latitude + "\n"
10 );
11 // 调用天气预报接口
12 const location = position.coords.longitude+","+position.coord
s.latitude
13 get3d(location).then(res => {
14 if (res.code == '200') {
15 state.weather = res.daily
16 } else {
17 console.log('获取天气失败')
18 }
19 }).catch(err => {
20 console.log(err)
21 })
22 }
23
24 function onError(error) {
25 alert("Code: " + error.code + "\n Message: " + error.messag
e)
26 }
27 }

展示天气信息

1 <van-list finished-text="没有更多了" >

2
3 <template #icon>
4
5
6 <template #title>
7 {{item.textDay}}
8
9 <template #label>
10 ⻛向:{{item.windDirDay}}  
11 温度:{{item.tempMin}} - {{item.tempMax}}
12
13
14

需要将天气相关的图标下载到 src/assets/color-64/ 下,然后才能根据接口数据,展示天气图标。
图标详情:https://dev.qweather.com/docs/start/icons/
下载地址:https://github.com/qwd/WeatherIcon

十八、更新头像

这里我们通过 cordova-plugin-camera 来实现在手机端更新用户头像功能

准备编辑⻚面

1 <template>
2 <div>
3 <van-nav-bar title="个人资料" left-text="返回" right-text="按钮"
left-arrow />
4
5 <van-cell-group>
6 <van-cell title="头像" @click="show = true" >
7 <template #default>
8 <div>
9 <img :src="require('@/assets/logo.png')" id="myImage"
>
10 </div>
11 </template>
12 </van-cell>
13 <van-cell title="昵称" value="张三" />
14 </van-cell-group>
15
16 <van-action-sheet
17 v-model:show="show"
18 :actions="actions"
19 cancel-text="取消"
20 close-on-click-action
21 @select="onCancel"
22 />
23 </div>
24 </template>
25
26 <script>
27 import { reactive, toRefs, onMounted } from 'vue'
28 import { useRouter } from 'vue-router'


29
30 export default {
31 name: "Profile",
32 setup () {
33 const state = reactive({
34 show: false
35 })
36
37 const router = useRouter()
38
39 // 拍照
40 const takePic = () => {
41 alert('拍照')
42 }
43
44 // 从相册中选取
45 const getPic = () => {
46 alert('从相册中选取')
47 }
48
49 // 先声明回调函数,然后再将回调函数,放到 actions 当中(否则,回调函数无
效)
50 const actions = [
51 { name: "拍照", callback: takePic },
52 { name: "从相册中选取", callback: getPic }
53 ]
54
55 const onCancel = () => {
56 state.show = false
57 }
58
59 // 挂载完成
60 onMounted (() => {
61 })
62
63 return {
64 ...toRefs(state),
65 onCancel,
66 actions
67 }


68 },
69 }
70
71 </script>
72 <style lang="less" scoped>
73 #myImage {
74 width: 2rem;
75 height: 2rem;
76 }
77 </style>

注意 actions 中的回调函数,如果写成箭头函数,则必须先声明,然后才能使用
因为箭头函数不能提升(普通函数不用考虑声明位置,会自动提升)

拍照更新头像

1 const takePic = () => {
2 alert('拍照')
3 // 拍照
4 navigator.camera.getPicture(onSuccess, onError, {
5 quality: 50 ,
6 destinationType: Camera.DestinationType.FILE_URI
7 })
8
9 function onSuccess(imageURI) {
10 var image = document.getElementById('myImage')
11 image.src = imageURI
12 }
13
14 function onError(message) {
15 alert("拍照失败:" + message)
16 }
17 }

浏览相册更新头像

1 const getPic = () => {


2 alert('从相册中选取')
3 navigator.camera.getPicture(onSuccess, onError, {
4 quality: 50 ,
5 destinationType: Camera.DestinationType.FILE_URI,
6 sourceType: Camera.PictureSourceType.PHOTOLIBRARY // 只需添
加这一行
7 })
8
9 function onSuccess(imageURI) {
10 var image = document.getElementById('myImage')
11 image.src = imageURI
12 }
13
14 function onError(message) {
15 alert("拍照失败:" + message)
16 }
17 }

十九、扫一扫

这里我们通过 cordova-plugin-qrscanner 来实现扫码功能。

插件详情:https://www.npmjs.com/package/cordova-plugin-qrscanner

安装

1 cordova plugin add cordova-plugin-qrscanner

声明扫码⻚面

1 <template>
2 <div>
3 <van-nav-bar title="扫一扫" left-text="返回" right-text="按钮"
left-arrow />
4
5 <div class="scan-container">
6 <div class="scan-none-1"></div>
7 <div class="scan-box-container">
8 <div class="scan-none-2"></div>
9 <div class="scan-box">
10 <div class="scan-box-area">
11 <div class="top-half top-left"></div>
12 <div class="top-half top-right"></div>
13 <div class="bottom-half bottom-left"></div>
14 <div class="bottom-half bottom-right"></div>
15 </div>
16 </div>
17 <div class="scan-none-2"></div>
18 </div>
19 <div class="scan-none-1">
20 <van-tag type="primary" plain size="large">放入框内,自动扫
描</van-tag>


21 <div id="scanMenu">
22 <van-button round color="#00ddaa" @click="toggleLight
()">
23 {{lightOn? '关闭' : '打开'}}
24 </van-button>
25 <van-button round color="#00ddaa" @click="toggleCamera
()">
26 {{frontCamera? '后摄' : '前摄'}}
27 </van-button>
28 </div>
29 </div>
30 </div>
31 </div>
32 </template>
33
34 <script>
35 import { reactive, toRefs, onMounted, onUnmounted } from 'vue'
36 import { useRouter } from 'vue-router'
37
38 export default {
39 name: "Scan",
40 setup () {
41 const state = reactive({
42 lightOn: false,
43 frontCamera: false
44 })
45
46 // 切换闪光灯
47 const toggleLight = () => {
48 alert('切换闪光灯')
49 }
50
51 // 切换摄像头
52 const toggleCamera = () => {
53 alert('切换摄像头')
54 }
55
56 return {
57 ...toRefs(state),
58 toggleLight,


59 toggleCamera
60 }
61 },
62 }
63 </script>
64
65 <style lang="less" scoped>
66 #scanMenu {
67 position: absolute;
68 bottom: 60px;
69 width: 100vw;
70 }
71
72 @primary: rgb( 74 , 243 , 220 );
73 @bg: rgba( 0 , 0 , 56 , 0.4);
74
75 .scan-container {
76 background: rgba( 0 , 0 , 0 , 0 );
77 display: flex;
78 flex-direction: column;
79 width: 100%;
80 height: calc(100vh - 50px);
81
82 .scan-none-1 {
83 flex: 1 ;
84 width: 100%;
85 background: @bg;
86 text-align: center;
87 padding-top: 0.32rem;
88 color: rgba( 255 , 255 , 255 , 0.8);
89
90 &:first-child {
91 flex: 0.6;
92 }
93 }
94
95 .scan-box-container {
96 display: flex;
97
98 .scan-none-2 {


99 flex: 1 ;
100 height: calc(8rem + 2px);
101 background: @bg;
102 }
103
104 .scan-box {
105 width: 8rem;
106 height: 8rem;
107 border: 1px solid @primary;
108 background: rgba( 0 , 0 , 0 , 0 );
109
110 .scan-box-area {
111 width: 8rem;
112 height: 8rem;
113 position: relative;
114
115 .top-half {
116 position: absolute;
117 top: -3px;
118 width: 1rem;
119 height: 1rem;
120 border-top: 6px solid @primary;
121 }.top-left {
122 left: -3px;
123 border-left: 6px solid @primary;
124 }.top-right {
125 right: -3px;
126 border-right: 6px solid @primary;
127 }
128
129 .bottom-half {
130 position: absolute;
131 bottom: -3px;
132 width: 1rem;
133 height: 1rem;
134 border-bottom: 6px solid @primary;
135 }.bottom-left {
136 left: -3px;
137 border-left: 6px solid @primary;
138 }




139 .bottom-right {
140 right: -3px;
141 border-right: 6px solid @primary;
142 }
143 }
144 }
145 }
146 }
147 </style>

声明路由

在 router/index.js 中添加路由

1 import { createRouter, createWebHashHistory } from 'vue-router'
2
3 const routes = [
4 // ...
5 {
6 path: '/scan',
7 name: 'Scan',
8 component: () => import('@/views/scan/index')
9 },
10 // ...
11 ]

扫码

1 const doScan = () => {
2 if (typeof QRScanner !== 'object') {
3 alert('QRScanner 不存在')
4 return;
5 }
6
7 QRScanner.prepare(onDone)
8 function onDone(err, status) {
9 if (err) {
10 console.log(err._message)

11 }
12
13 if (status.authorized) {
14 QRScanner.scan(displayContents)
15 function displayContents(err, text) {
16 if (err) {
17 console.error(err)
18 } else {
19 alert(text)
20 // 后续操作
21 }
22 }
23
24 // 让 webview 透明,执行扫码操作
25 QRScanner.show()
26 } else if (status.denied) {
27 alert('用户拒绝扫码')
28 } else {
29 alert('未获取数据')
30 }
31 }
32 }
33
34 // 挂载完成
35 onMounted (() => {
36 doScan()
37 })

切换闪光灯

1 // 切换闪光灯
2 const toggleLight = () => {
3 alert('切换闪光灯')
4 if (state.lightOn === false) {
5 QRScanner.enableLight((err, status) => {
6 err && console.log(err)
7 state.lightOn = true;
8 })

9 } else {
10 QRScanner.disableLight((err, status) => {
11 err && console.log(err)
12 state.lightOn = false;
13 })
14 }
15 }

切换摄像头

1 // 切换摄像头
2 const toggleCamera = () => {
3 alert('切换摄像头')
4 if (state.frontCamera === false) {
5 QRScanner.useFrontCamera((err, status) => {
6 err && console.log(err)
7 state.frontCamera = true
8 })
9 } else {
10 QRScanner.useBackCamera((err, status) => {
11 err && console.log(err)
12 state.frontCamera = false
13 })
14 }
15 }

重置⻚面背景

1 onUnmounted(() => {
2 document.getElementById('app').style.backgroundColor = "#FFFFF
F"
3 document.querySelector('body').style.backgroundColor = "#FFFFF
F"
4
5 try {
6 QRScanner.hide(status => {
7 console.log('关闭扫描' + JSON.stringify(status))

8 })
9 QRScanner.destroy(status => {
10 console.log('销毁扫描' + JSON.stringify(status))
11 })
12 } catch (error) {
13 console.log(error)
14 }
15 })

查看效果

1 npm run build
2
3 npm run develop

二十、Splash ⻚

详情查看:cordova-plugin-splashscreen
在这里插入图片描述

二十一、国际化

通过 cordova-plugin-globalization 获取当前语言信息。然后通过 Vue 的 i18n 来实现多语言的效果。

下载 i18n

1 npm install vue-i18n@next

创建语言包

创建 src/assets/i18n 目录,并声明语言包

1 src
2 ├── assets
3 | └──i18n 国际化目录
4 │ └── en.js 英文
5 | └── zh.js 中文
6 | └── index.js

en.js

1 export default {
2 // 公共的key
3 common: {
4 all: 'All',
5 back: 'Back',
6 search: 'Search',
7 scan: 'Scan'
8 },
9 nav: {
10 home: 'Home',
11 news: 'News',
12 profile: 'Profile'
13 }
14 }

zh.js

1 export default {
2 // 公共的key
3 common: {
4 all: '全部',
5 back: '返回',
6 search: '搜索',
7 scan: '扫一扫'
8 },
9 nav: {
10 home: '首⻚',
11 news: '新闻',
12 profile: '我的'
13 }
14 }

index.js

1 import { createI18n } from 'vue-i18n'
2 import enLocale from "./en";
3 import zhLocale from "./zh";
4
5 const messages = {
6 en: { ...enLocale }, // 英文语言包
7 zh: { ...zhLocale } // 中文语言包
8 };
9
10 const i18n = createI18n({
11 locale: localStorage.lang || en,
12 messages
13 })
14
15 export default i18n

引入 i18n

在 src/main.js 中引入 i18n

1 import i18n from './assets/i18n/index'
2
3 const app = createApp(App)
4
5 app.use(i18n)

使用语言包

1 <template>
2 <div>
3 <van-tabbar v-model="active">
4 <van-tabbar-item to="/" icon="home-o">{{$t('nav.home')}}</va
n-tabbar-item>
5 <van-tabbar-item to="/news" icon="desktop-o">{{$t('nav.new
s')}}</van-tabbar-item>
6 <van-tabbar-item to="/user" icon="user-o">{{$t('nav.profil
e')}}</van-tabbar-item>
7 </van-tabbar>
8 </div>
9 </template>

这里的 nav 就对应语言包中的 nav

二十二、电话短信

1 <van-grid :gutter="6" border>
2 <van-grid-item icon="peer-pay" text="短信" to="" url="sms:1876421
9356" />
3 <van-grid-item icon="phone-o" text="呼叫" to="" url="tel:40062828
35" />
4 </van-grid>

二十三、FAQ

  1. There was a network error.(某个域名)

报错原因:没有添加白名单,或者白名单规则不允许访问上述域名
解决:

  • 添加白名单
  • 为上述域名添加允许访问的规则
  1. net::err_cleartext_not_permitted

报错原因:APP 默认不支持 http 协议(默认只允许 https)
解决:
在 android 目录中的 AndroidManifest.xml 文件添加一行
(一般路径为:android/app/src/main/AndroidManifest.xml)

1 <application
2 android:hardwareAccelerated="true"
3 android:icon="@mipmap/ic_launcher"
4 android:label="@string/app_name"
5 android:supportsRtl="true"
6 android:usesCleartextTraffic="true" <!-- 添加这一行 -->
7 >

二十四、inappbrowser

  • cordova-plugin-inappbrowser
  • 作用
    • 允许在cordova应用内部打开web地址,而无需跳出app
    • 比如:支付页面
<template>
  <div>
    <van-nav-bar title="应用内跳转" left-text="返回" right-text="按钮" left-arrow @click-left="goHome" @click-right=""/>

    <van-search 
      v-model="url" 
      placeholder="请输入跳转地址" 
      label="地址"
      show-action
      @search="onSearch"
    >
      <template #action>
        <div @click="onSearch">
          跳转
        </div>
      </template>
    </van-search>

    <van-dropdown-menu>
       <van-dropdown-item v-model="target" :options="targetList"/>
       <van-dropdown-item v-model="options" :options="optionsList"/>
    </van-dropdown-menu>

    <van-button type="primary" @click="goBaidu">跳转到百度</van-button>
  </div>
</template>
<script>
import { reactive, toRefs, onMounted } from 'vue'
import { useRouter } from 'vue-router'

export default {
  name: "Inappbrowser",
  setup () {
    const state = reactive({
      url: "https://m.lagou.com",
      target: '_blank', // _blank 新页面打开 | _self 当前页打开 | _system 在系统浏览器中打开
      options: 'location=yes', // 显示地址栏
    })

    const router = useRouter()

    const goHome = () => {
      router.push('/')
    }

    const targetList = [
      { text: '当前页打开', value: '_self' },
      { text: '新页面打开', value: '_blank' },
      { text: '系统浏览器打开', value: '_system' },
    ]

    const optionsList = [
      { text: '显示地址栏', value: 'location=yes' },
      { text: '隐藏地址栏', value: 'location=no' },
    ]

    const goBaidu = () => {
      location.href = "https://m.baidu.com"
    }

    // 自定义函数
    const onSearch = () => {
      var ref = cordova.InAppBrowser.open(state.url, state.target, state.options)

      ref.addEventListener('loadstart', loadstartCallback)
      ref.addEventListener('loadstop', loadstopCallback)
      ref.addEventListener('loaderror', loaderrorCallback)
      ref.addEventListener('exit', exitCallback)

      function loadstartCallback(event) {
        alert('Loading started: ' + event.url)
      }

      function loadstopCallback(event) {
        alert('Loading finished: ' + event.url)
      }

      function loaderrorCallback(event) {
        alert('Loading error: ' + event.message)
      }

      function exitCallback() {
        alert('浏览器已关闭')
      }
    }

    // 挂载完成
    onMounted (() => {

    })

    return {
      ...toRefs(state),
      onSearch,
      goBaidu,
      targetList,
      optionsList,
      goHome
    }
  },
}

</script>
<style lang="less" scoped>

</style>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/337845.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux内核并发与竞争-原子操作

一.原子操作的概念首先看一下原子操作&#xff0c;原子操作就是指不能再进一步分割的操作&#xff0c;一般原子操作用于变量或者位操作。假如现在要对无符号整形变量 a 赋值&#xff0c;值为 3&#xff0c;对于 C 语言来讲很简单&#xff0c;直接就是&#xff1a; a3但是 C 语言…

机器学习基本原理总结

本文大部分内容参考《深度学习》书籍&#xff0c;从中抽取重要的知识点&#xff0c;并对部分概念和原理加以自己的总结&#xff0c;适合当作原书的补充资料阅读&#xff0c;也可当作快速阅览机器学习原理基础知识的参考资料。 前言 深度学习是机器学习的一个特定分支。我们要想…

Elasticsearch bucket_script、bucket_selector、bucket_sort 区别和应用场景?

1、实战问题POST test-002/_bulk {"index":{"_id":1}} {"name": "张三","city": "beijing"} {"index":{"_id":2}} {"name": "李四","city": "beijing&qu…

简信CRM:医疗健康行业数字化解决方案

随着社会群体健康意识提升、用户消费习惯变化、新冠疫情冲击等因素&#xff0c;人们对于个人和公共安全健康问题就越发重视&#xff0c;而且已经逐渐从对“病”的被动治疗转变为对“健康”的主动管理&#xff0c;医疗健康行业呈现出一片火热的趋势。但医疗健康行业的情况比较复…

idekCTF 2022 比赛复现

Readme 首先 []byte 是 go 语言里面的一个索引&#xff0c;比如&#xff1a; package mainimport "fmt"func main() {var str string "hello"var randomData []byte []byte(str)fmt.Println(randomData[0:]) //[104 101 108 108 111] }上面这串代码会从…

Java程序运行机制

Java语言既具有编译型语言的特征&#xff0c;又具有解释型语言的特征&#xff0c;Java程序要经过先编译后解释两个阶段。高级语言的运行机制&#x1f4cd;编译型语言使用专门的编译器&#xff0c;针对特定的平台&#xff08;移植性差&#xff09;&#xff0c;将高级语言的源代码…

情人节有哪些数码好物值得送礼?情人节实用性强的数码好物推荐

转瞬间&#xff0c;情人节快到了&#xff0c;大家还在为送什么礼物而烦恼&#xff1f;在这个以科技为主的时代&#xff0c;人们正在享受着科技带来的便利&#xff0c;其中&#xff0c;数码产品也成为了日常生活中必不可少的存在。接下来&#xff0c;我来给大家推荐几款比较实用…

大数据框架之Hadoop:入门(四)Hadoop运行模式

Hadoop运行模式包括&#xff1a;本地模式、伪分布式模式以及完全分布式模式。 Hadoop官方网站&#xff1a;http://hadoop.apache.org/ 4.1本地运行模式 4.1.1官方Grep案例 1.创建在hadoop文件夹下面创建一个input文件夹 [roothdp101 hadoop]# mkdir input2.将Hadoop的xml配…

SpringBoot整合Druid数据源(实行监控功能)

在上篇文章中分析了数据连接池&#xff08;Durid&#xff09;在应用中可以做到资源重用&#xff0c;提升系统响应速度&#xff0c;避免数据库连接遗漏。它除了是一个高性能数据库连接池之外&#xff0c;更是一个自带监控的数据库连接池 JDDC与Druid 1Druid是什么 Apache Drui…

tui-swipe-action组件上的按钮点击后有阴影的解决方法

大家好,我是雄雄,欢迎关注微信公众号:雄雄的小课堂。 目录 前言问题描述问题解决前言 一直未敢涉足电商领域,总觉得这里面的道道很多,又是支付、又是物流的,还涉及到金钱,所以我们所做的项目,一直都是XXXX管理系统,XXX考核系统,移动端的也是,XX健康管理平台…… 但…

SLAM中坐标轴旋转及ros的接口解释

读完几个loam算法&#xff0c;满篇的坐标轴旋转&#xff0c;还是手写的(作者&#xff0c;用eigen写不好嘛。。。)&#xff0c;我滴天适应了好久…&#xff0c;今天就总结一下坐标轴旋转问题。 一、首先&#xff0c;我们看一下ros中关于欧拉角旋转的函数&#xff1a;setRPY、set…

C++展开模板参数包、函数参数包-(lambda+折叠表达式)

开门见山 以下代码可展开模板参数包和展开函数参数包。 // lambda折叠表达式(需C17) #include <iostream> using namespace std;// 1.展开模板参数包 template<typename ...T> void Func1() {([]() {cout << typeid(T).name() << endl;}(), ...);// …

姿态估计端到端新方案 | DirectMHP:用于全范围角度2D多人头部姿势估计

前言 现有的头部姿势估计主要集中在具有预先检测到的正面头部的单个人&#xff0c;这依赖于单独训练的面部检测器&#xff0c;不能很好地泛化到完整的视点。在本文中&#xff0c;作者关注全范围 MPHPE 问题&#xff0c;并提出了一个名为 DirectMHP 的直接端到端简单基线&#x…

怎么给笔记本电脑外接两台显示器?

我们在办公室会看见不少同事的电脑不止一台显示器&#xff0c;多屏确实可以提高工作效率。有的游戏党也会选择给电脑外接显示器&#xff0c;带来绝佳的体验。 不过要怎么把将外部显示器连接到笔记本电脑上&#xff1f;驱动人生在这里教给大家给笔记本外接显示器的做法。 一、…

TensorFlow CNN 卷积神经网络实现人脸性别检测 完整教程 附完整代码

本文主要是实现了根据人脸识别性别的卷积神经网络,并对卷积过程中的提取特征进行了可视化.

HydroD 实用教程(二)有限元模型

目 录一、前言二、模型种类三、单元类型四、FEM文件五、参考文献一、前言 SESAM &#xff08;Super Element Structure Analysis Module&#xff09;是由挪威船级社&#xff08;DNV-GL&#xff09;开发的一款有限元分析&#xff08;FEA&#xff09;系统&#xff0c;它以 GeniE、…

【Linux command 09】tcpdump 命令

tcp一款sniffer工具&#xff0c;是Linux上的抓包工具&#xff0c;嗅探器语法tcpdump (选项)选项-c&#xff1a; 指定要抓取的包数量。注意&#xff0c;是最终要获取这么多个包。例如&#xff0c;指定"-c 10"将获取10个包&#xff0c;但可能已经处理了100个包&#xf…

激光slam学习笔记2--激光点云数据结构特点可视化查看

背景&#xff1a;不同厂商的激光点云结果存在一定差异&#xff0c;比如有些只有xyz&#xff0c;有些包含其他&#xff0c;如反光率、时间戳、ring等。如何快速判断是个值得学习的点 概要&#xff1a;对于rosbag类型的激光点云&#xff0c;介绍使用rviz快速查看点云结构特点 如…

JavaWeb--MySQL高级

MySQL高级1 约束1.1 概念1.2 分类1.3 非空约束1.4 唯一约束1.5 主键约束1.6 默认约束1.7 检查约束1.8 外键约束1.8.1 概述1.8.2 语法2 数据库设计2.1 数据库设计简介2.2 表关系(一对多)2.3 表关系(多对多)2.4 表关系(一对一)3 多表查询3.1 内连接查询3.2 外连接查询3.3 子查询3…

技能树基础——17四平方和(拉格朗日定理,嵌套循环)

题目&#xff1a;四平方和定理&#xff0c;又称为拉格朗日定理&#xff1a;每个正整数都可以表示为至多4个正整数的平方和。如果把0包括进去&#xff0c;就正好可以表示为4个数的平方和。比如&#xff1a;5 0^ 2 0^ 2 1^ 2 2^27 1^ 2 1^ 2 1^ 2 2^2 &#xff08;^符号表…