1. 程式人生 > >[翻譯]Nativescript 中 Web 視圖與 Android/IOS 的雙向通信

[翻譯]Nativescript 中 Web 視圖與 Android/IOS 的雙向通信

facede gson pri ren change 內容 pan 應用 ans

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

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

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

Javascript
(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);
}

讓我們來處理loadLanguagesweb 視圖中的事件。

www/index.js

Javascript
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

Javascript
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

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]);
}

在這裏, 我們打電話給addNewLanguageweb 視圖的功能, 直接從本機應用程序. 請註意, 我們要傳遞給的參數addNewLanguage功能必須是數組格式。
由於我們不期望在 web 視圖中的語言添加操作有任何返回值, 所以我們不需要將任何回調函數賦給callJSFunctionApi。

讓我們創建addNewLanguage在 web 視圖中的函數來處理此操作。

www/index.js

Javascript
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

Javascript
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

Javascript
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 的雙向通信