[翻譯]Nativescript 中 Web 視圖與 Android/IOS 的雙向通信
English document From http://shripalsoni.com/blog/nativescript-webview-native-bi-directional-communication/
Nativescript 中 Web 視圖與 Android/IOS 的雙向通信
由shripal編寫 在Nativescript中Nativescript 提供跨平臺的 web 視圖 ui 元素。它為在我們的頁面中顯示 web 視圖內容提供了服務。
但是, 如果您希望將一些數據發送到 web 視圖或從 web 視圖獲取一些數據, 則需要為此編寫特定於平臺的代碼。因此, 與其在每個應用程序中編寫所有這樣的代碼, 不如有一個插件。
我已經創建了nativescript web 視圖接口插件以實現此目的。您可以克隆演示應用程序, 以便快速入門使用此插件。
演示應用的輸出如下所示:
Android
Ios
在這個演示應用程序中, 我們在 web 視圖中有語言下拉列表, 我們可以在下拉菜單中添加新的語言和查詢語言, 從本機側面。每當選定內容發生更改時, 下拉列表也會向本機發出事件。
讓我們理解一下, 這是如何工作的。
步驟 1: 插件的初始化
首先, 我們需要按照https://www.npmjs.com/package/nativescript-webview-interface#installation)中的指令安裝插件
一旦安裝了插件, 讓我們添加
web-view
元素到我們的頁面。
main-page.xml
<Page xmlns="http://schemas.nativescript.org/tns.xsd" loaded="pageLoaded">
....
<web-view id="webView" src="~/www/index.html"></web-view>
....
</Page>
現在, 初始化插件, 在我們的main-page.ts
文件。(在這裏, 我使用的是文稿, 但您可以在https://github.com/shripalsoni04/nativescript-webview-interface-demo中查看 javascript 中的相關代碼。
main-page.ts
import {webViewInterfaceDemoVM} from ‘./main-view-model‘;
var webViewInterfaceModule = require(‘nativescript-webview-interface‘);
var oLangWebViewInterface;
export function pageLoaded(args){
page = args.object;
page.bindingContext = webViewInterfaceDemoVM;
setupWebViewInterface(page)
}
/**
* Initializes webViewInterface for communication between webview and android/ios
*/
function setupWebViewInterface(page: Page){
var webView = page.getViewById(‘webView‘);
oLangWebViewInterface = new webViewInterfaceModule.WebViewInterface(webView);
}
檢查代碼main-view-model
供參考。
假設我們按照上面提到的安裝說明復制了 web 視圖的插件文件, 讓我們將插件文件導入到我們的index.html
www/index.html
<!doctype html>
<html>
<body>
<select id="knownLanguage">
<option value="-1">----Select Language----</option>
</select>
<script src="./lib/nativescript-webview-interface.js"></script>
<script src="./index.js"></script>
</body>
</html>
一旦插件文件在 html 文件中導入, 我們就可以訪問所有必要的 API, 從 web 視圖與本機應用程序進行通信, 在window.nsWebViewInterface
全局對象。
www/index.js
(function(){
// oWebViewInterface provides necessary APIs for communication to native app.
var oWebViewInterface = window.nsWebViewInterface;
var languageDD = document.getElementById(‘knownLanguage‘);
function init(){
}
init();
})()
步驟 2: 從本機應用程序的下拉列表中加載語言
現在, 我們要加載在其中加載的一些默認語言的下拉列表。在加載 web 視圖後, 我們可以通過使用默認語言向 web 視圖發出事件來執行此項設置。
main-page.ts
function setupWebViewInterface(page: Page){
...
// loading languages in dropdown, on load of webView.
webView.on(WebView.loadFinishedEvent, (args: LoadEventData) => {
if (!args.error) {
loadLanguagesInWebView();
}
});
...
}
/**
* Sends intial list of languages to webView, once it is loaded
*/
function loadLanguagesInWebView(){
oLangWebViewInterface.emit(‘loadLanguages‘, webViewInterfaceDemoVM.lstLanguages);
}
讓我們來處理loadLanguages
web 視圖中的事件。
www/index.js
function init(){
...
addNativeMsgListener();
...
}
/**
* Registers handlers for native events.
*/
function addNativeMsgListener() {
oWebViewInterface.on(‘loadLanguages‘, function (arrLanguages) {
for (var i = 0; i < arrLanguages.length; i++) {
addLanguageOption(arrLanguages[i]);
}
});
}
/**
* Adds language to dropdown options
*/
function addLanguageOption(language){
var option = document.createElement(‘Option‘);
option.text = language;
option.value = language;
languageDD.appendChild(option);
}
步驟 3: 在下拉菜單中更改語言時通知本機應用程序
要讓本機應用程序知道, 每當在下拉列表中更改語言時, 我們需要從 web 視圖中從選擇更改中發出事件。
www/index.js
function init(){
...
languageDD.onchange = function(){
sendSelectedValue(languageDD.value);
}
...
/**
* Sends selected value to native app by emitting an event
*/
function sendSelectedValue(selectedLanguage){
oWebViewInterface.emit(‘languageSelection‘, selectedLanguage);
}
}
我們需要在本機方面處理此事件, 以便對語言更改進行任何操作。
main-page.ts
function setupWebViewInterface(page: Page){
...
listenLangWebViewEvents();
...
}
/**
* Handles any event/command emitted by language webview.
*/
function listenLangWebViewEvents(){
// handles language selectionChange event.
oLangWebViewInterface.on(‘languageSelection‘, (selectedLanguage) => {
webViewInterfaceDemoVM.selectedLanguage = selectedLanguage;
});
}
步驟 4: 從本機的下拉列表中添加新語言
要在本機應用程序的下拉選項中添加新語言, 我們可以直接調用在 web 視圖中處理此操作的 JS 函數。
main-page.xml
<GridLayout rows="50" columns="*, 70">
<TextField id="txtLanguage" col="0" hint="Language" />
<Button col="1" text="Add" tap="addLanguage" />
</GridLayout>
main-page.ts
/**
* Adds language to webView dropdown
*/
export function addLanguage(){
var txtField = <TextField>page.getViewById(‘txtLanguage‘);
oLangWebViewInterface.callJSFunction(‘addNewLanguage‘, [txtField.text]);
}
在這裏, 我們打電話給addNewLanguage
web 視圖的功能, 直接從本機應用程序. 請註意, 我們要傳遞給的參數addNewLanguage
功能必須是數組格式。
由於我們不期望在 web 視圖中的語言添加操作有任何返回值, 所以我們不需要將任何回調函數賦給callJSFunction
Api。
讓我們創建addNewLanguage
在 web 視圖中的函數來處理此操作。
www/index.js
function init(){
...
defineNativeInterfaceFunctions();
...
}
/**
* Defines global functions which will be called from andorid/ios
*/
function defineNativeInterfaceFunctions(){
/**
* Handles new language addition initiated by native app
*/
window.addNewLanguage = function(language){
addLanguageOption(language);
languageDD.value = language;
languageDD.onchange();
};
}
步驟 5: 從 web 視圖查詢數據
現在, 我們希望從 web 視圖中獲取當前選定語言的值。我們可以通過將 JS 函數調用到 web 視圖來做到這一點。
main-page.ts
/**
* Fetches currently selected language of dropdown in webView.
*/
export function getSelectedLanguage(){
oLangWebViewInterface.callJSFunction(‘getSelectedLanguage‘, null, (oSelectedLang) => {
alert(`Selected Language is ${oSelectedLang.text}`);
});
}
www/index.js
function defineNativeInterfaceFunctions(){
...
window.getSelectedLanguage = function(){
var selectedLangOpt = languageDD.options[languageDD.selectedIndex];
return {id: selectedLangOpt.value, text: selectedLangOpt.text};
};
...
}
步驟 6: 從 JS 功能調用的 web 視圖返回延遲結果
根據 javscript 的異步性質, 有時我們不能在 web 視圖中立即返回 js 函數的調用, 因此在這種情況下, 我們可以在 js 函數調用上返回一個承諾。
因此, 每當承諾得到解決, 在本機應用程序端註冊的回調函數將用承諾的解析值來調用。
main-page.ts
/**
* Fetches currently selected language of dropdown in webview.
* The result will come after 2s. This function is written to show the support of deferred result.
*/
export function getSelectedLanguageDeferred(){
oLangWebViewInterface.callJSFunction(‘getSelectedLanguageDeferred‘, null, (oSelectedLang) => {
alert(`Deferred Selected Language is ${oSelectedLang.text}`);
});
}
www/index.js
function defineNativeInterfaceFunctions(){
...
window.getSelectedLanguageDeferred = function(){
var selectedLangOpt = languageDD.options[languageDD.selectedIndex];
return new Promise(function(resolve) {
setTimeout(function(){
resolve({id: selectedLangOpt.value, text: selectedLangOpt.text});
}, 2000);
});
};
...
}
我知道這是非常瑣碎的應用程序, 但我發現這個應用程序是正確的解釋所有的方案, 可以處理 nativescript-webivew 接口插件。
我還創建了一個服務於有效用例的應用程序。我將在將來發布它。
[翻譯]Nativescript 中 Web 視圖與 Android/IOS 的雙向通信