Отправить сообщение из мини-программы WeChat в веб-просмотр

Я создаю мини-программу WeChat, которая на одной из ее страниц имеет web-view контроль. Например:

page.wxml

<web-view src="https://..." bindmessage="onWebViewMessage"></web-view>

страница.js

const app = getApp();
Page({
    onWebViewMessage:function(e) {
         console.log(e);
    },
    onLoad:function() {
    }
});

В web-view загружается HTML-страница (index.html), включающая jweixin-1.3.2.js библиотеку из WeChat, для подключения к WeChat API, а также для подключения к родительской мини-программе. Страница пуста, нет элементов DOM, просто javascript, который будет выполняться при загрузке документа.

У него есть javascript примерно так:

index.js

document.addEventListener('DOMContentLoaded',function(){
    wx.miniProgram.postMessage({data:'test'});
});

Я могу без проблем отправлять сообщения из этого документа в мини-программу. Также можно отправить некоторые навигационные команды мини-программы, такие как wx.miniProgram.navigateTo({url:'path/to/page'});, так что все выглядит нормально. Я также могу получить обратный вызов в мини-программе, когда web-view завершит загрузку.

Вопрос:

Как отправить сообщение из мини-программы в веб-просмотр? Например, чтобы передать строку или объект в веб-представление.

Я часами гуглю и не могу найти никого, кто бы это делал, но я не могу поверить, что возможна только односторонняя связь.

Любая помощь или идея приветствуется!


person Sinisa    schedule 16.06.2019    source источник
comment
Было бы очень полезно понять, почему за этот вопрос проголосовали против, учитывая, что онлайн-информация по этой теме очень ограничена. Знание того, в чем была проблема с этим, помогло бы мне улучшить свои будущие вопросы.   -  person Sinisa    schedule 23.06.2019
comment
не получать сообщения с веб-страницы.   -  person Kamlesh Delat    schedule 29.08.2019
comment
@KamleshDelat правильно, проблема заключалась в том, как отправлять данные из мини-программы на веб-страницу внутри веб-представления, поскольку для этого нет API.   -  person Sinisa    schedule 30.08.2019
comment
@Sunisa, настоящая проблема заключается в том, что сообщение в мини-программе не отправляется с помощью HTML с использованием wx.miniProgram.postMessage.   -  person Kamlesh Delat    schedule 30.08.2019
comment
@KamleshDelat Я думаю, ты неправильно понял. Проблема в том, как я могу отправить сообщение из мини-программы в веб-просмотр в любой момент. Несколько сообщений, если это необходимо, когда это необходимо. Веб-представление может отправить обратно сообщение в мини-программу с помощью wx.miniProgram.postMessage, но нет API для обратного. Отсюда мой вопрос.   -  person Sinisa    schedule 31.08.2019
comment
wx.miniProgram.postMessage отправить сообщение после выгрузки или уничтожения webView, это не для связи в реальном времени   -  person Kamlesh Delat    schedule 13.09.2019
comment
@KamleshDelat то, что я ищу, - это общение в реальном времени от мини-программы до веб-просмотра, а не наоборот.   -  person Sinisa    schedule 13.09.2019
comment
тоже самое ищу.   -  person Kamlesh Delat    schedule 14.09.2019


Ответы (1)


Я нашел эффективный способ передачи данных из мини-программы в содержимое веб-просмотра, и кажется, что на данный момент это единственно возможный способ сделать это.

Мини-программа

1. Модуль Base64

Вам нужно будет иметь возможность конвертировать обычную строку в строку Base64. API мини-программы имеет метод преобразования массива байтов в строку base64, но он не будет использоваться для этой цели. Итак, создайте свой собственный модуль, который делает это:

Файл: lib/b64.js

var string2base64 = function(str) {
    .... here put your js code for making b64 string ....
    return result;
};

module.exports = {
    string2base64
};

2. Страница с веб-представлением

На странице с элементом управления web-view подготовьте элемент DOM в файле wxml следующим образом:

Файл: pages/xxx/index.wxml

<web-view src="{{webURL}}" bindload="onWebLoad" binderror="onWebError"></web-view>

Обратите внимание, что параметр src теперь привязан к свойству webURL страницы. Всякий раз, когда страница устанавливает значение для этого свойства, оно автоматически применяется к элементу DOM.

В файле pages/xxx/index.js вам нужно будет добавить модуль base64:

const b64 = require('../../lib/b64.js')

обратите внимание, что требуемый путь может различаться в зависимости от того, как вы настроили свой проект

и в объекте страницы data добавьте свойства webURL и webBaseURL, например:

Page({
    data: {
        webURL:'',
        webBaseURL:'https://your/web/app/url',
        messageQueue:[],
        messageQueueSize:0,
        .... other page properties go here ....
    },
    ..... rest of your page code goes here .....
})

Обратите внимание, что webURL установлено пустым. Это означает, что при загрузке страницы в качестве объекта DOM по умолчанию будет установлена ​​пустая строка.

webBaseURL немного объяснит.

messageQueue — это массив, в котором будут храниться ожидающие сообщения для отправки в веб-представление. messageQueueSize - это просто длина массива. Используется для повышения производительности, чтобы избежать чтения Array.length.

3. Запустить очередь сообщений

В onShow обратном вызове страницы установите webURL и запустите интервал, который будет читать messageQueue массив каждые 250 мс. Вы можете изменить способ, которым это делается, если вам не нравятся интервалы, это был просто самый простой способ проверить теорию.

onShow: function(){
    // This will start loading of the content in web-view
    this.setData({webURL: this.data.webBaseURL } );

    // Sends message from message queue to web-view
    let _this = this;
    setInterval(function(e) {
        if( _this.data.messageQueueSize < 1 ) return;
        _this.data.messageQueueSize --;
        let msg = _this.data.messageQueue.splice(0,1);
        _this.setData({webURL: _this.data.webBaseURL+"#"+msg});
    },250);
}

Вы можете видеть, что сообщение добавляется к источнику веб-просмотра (url) в виде хэша.

webBaseURL используется для генерации конечного URL с хешем, который затем отправляется в веб-просмотр.

4. Добавьте сообщение в очередь

Чтобы создать сообщение в очереди сообщений, просто определите следующий метод на своей странице:

addMessageToQueue: function(obj) {
    obj.unique = Math.round(Math.random()*100000);
    let msg = b64.string2base64(JSON.stringify(obj));
    this.data.messageQueue.push(msg);
    this.data.messageQueueSize++;
}

Всякий раз, когда вы вызываете этот метод, просто передайте объект с любыми свойствами, которые вам нужны, и он будет преобразован в строку JSON, затем в строку base64 и, наконец, добавлен в очередь сообщений.

Свойство unique добавлено, чтобы сгенерированный результат base64 всегда отличался, даже если остальные свойства объекта одинаковы - мне это просто нужно для целей моего проекта. Вы можете игнорировать его/удалить, если он вам не нужен.

Поскольку существует интервал выполнения и проверки очереди сообщений, все сообщения, добавленные таким образом, будут отправлены в веб-представление в том же порядке, в котором они были добавлены в очередь.

Теперь осталось только одно — добавить прослушивание изменения хэша в HTML-странице, которую мы загрузили в веб-представление:

HTML-веб-приложение

1. Слушайте изменение хэша

window.addEventListener("hashchange",function(e){
    let messageBase64 = window.location.hash.substr(1);
    let json = window.atob( messageBase64 );
    let data = JSON.parse(json);
    console.log("Received data from mini-program:",data);
});

Проверено на Xiaomi Mi8 Pro. Мне еще предстоит проверить на других устройствах, продаваемых в Китае.

Ваше здоровье!

person Sinisa    schedule 23.06.2019