Demand background

The h5 page in the WebView needs to modify the current share page after some operations, but the link of the H5 page does not change. There needs to be a mechanism for notifying applet pages that share parameters need to be changed.

Technology to solve

According to applets documentation, support webView pages to communicate with applets in the form of postMessage (only triggered during special operations such as sharing, returning, etc.)

Key points:

  • Using wx. MiniProgram. PostMessage to small program communication, when a user forward can listen to the news page
  • The page listens to historical messages and does not clear them. You need to handle them by yourself
  • Applets page set onShareAppMessage can support sharing, the default share is the current page
  • After the user clicks forward, onMessage of webView will be triggered first, and then onShareAppMessage will be called to set the sharing configuration

PostMessage message format as agreed by H5 and applets:

{
    type:'Message type', / /setShareOption ... RestData // Other parameters}Copy the code

H5 Page sharing parameters:

/** * Set "postMessage" * @param option * @examplesetWeappShareOption({title:"Share title",path:"Share links",imageUrl:'Share picture may be empty'}) * /export function setWeappShareOption(option:{title:string,path:string,imageUrl:string}){
    if(window['wx'] && window['wx'].miniProgram && window['wx'].miniProgram.postMessage){
        window['wx'].miniProgram.postMessage({
           data:{
                type:'setShareOption', title:option.title, path:option.path, imageUrl:option.imageUrl } }); }}Copy the code

Applet pages support sharing:

The source address

import Taro from '@tarojs/taro'
import { WebView } from '@tarojs/components'
import {
  getCurrentChannelEventHash,
  resetChannelHash,
} from './WebViewHashChannelData'
import { unpackUrl,packUrl } from '.. /.. /src/core/UrlHelper'

const DEFAULT_WEB_PATH = 'https://xxx.x.com/xxx'// To default domain name prefix /** * applet Page * @param to ADDRESS of THE H5 Page to be moved to :/ XXX/XXX or full address https://xxx.... * @param title Title of h5 page to jump to */export default class H5WebView extends Taro.Component {
  config = {
    navigationBarTitleText: ' ',
  }

  state = {
    url: ' '// THE URL does not support Hashhash: ' ',
  }

  isBack = false

  shareOption = {
    title: null,
    path: null,
  }

  componentWillMount() {
    this.isBack = false
    const to = decodeURIComponent(this.$router.params.to || ' ')
    const urlObj = unpackUrl(to)
    let url = urlObj.pathWithSearch
    let hash = urlObj.hash
    let title = this.$router.params.title
    if (title) {
      title = decodeURIComponent(title)
      Taro.setNavigationBarTitle({ title: title })
    }
    this.setState({
      url,
      hash,
    })
    console.log('[H5WebView] mount', url, hash)}componentDidShow() {
    // onShow
    if(this.isback) {// Applet page falls back, notifying H5let channelEventHash = getCurrentChannelEventHash()
      // if(! ChannelEventHash) {// TODO only whitelist pages to add backPush via postMessage?? // channelEventHash = getBackEventHash(); } this.setState({this.setState({this.setState);}hash: channelEventHash,}) // Reset resetChannelHash() console.log('[H5WebView] show set hash', channelEventHash, this.state.url)
    } else {
      console.log('[H5WebView] show first')
    }
    this.isBack = true
  }
 
  _getLastData(itemList, type) {
    if(! itemList || itemList.length === 0) {return null
    }
    let lastIdx = itemList.length - 1
    while (lastIdx >= 0) {
      let item = itemList[lastIdx]
      if (item && item.type === type) {
        return item
      }
    }
  }
  handleMessage(e) {
    let{data} = e.datail // Set the last sharelet shareOption = this._getLastData(data, 'setShareOption')
    if (shareOption) {
      this.shareOption = {
        title: shareOption.title,
        imageUrl: shareOption.imageUrl,
        path: shareOption.path,
      }
    }
    console.log('withWV handleMessage', data)} /** * supports message sharing */onShareAppMessage() {
    if (this.shareOption) {
      let path = null
      if (this.shareOption.path) {
        path = packUrl(this.$router.path, {
          to: this.shareOption.path,
          title: this.shareOption.title,
        })
      }
      return {
        title: this.shareOption.title,
        path,
        imageUrl: this.shareOption.imageUrl,
      }
    }
  }

  onWebViewLoad(e) {
    console.log('withWV onWebViewLoad'SRC, this.state.hash) this.shareoption. path = e.daail. SRC // Default share page is the current page}_normalizeTo() {
    let to = this.state.url
    if(! to) {return null
    }
    if(to.substr(0, 4) ! = ='http') {
      to = DEFAULT_WEB_PATH + to
    }
    if (this.state.hash) {
      to += The '#' + this.state.hash
    }
    return to
  }

  render() {
    let to = this._normalizeTo()
    if(! to) {return null
    }
    return (
      <WebView
        src={to}
        onMessage={this.handleMessage}
        onLoad={this.onWebViewLoad}
      />
    )
  }
}

Copy the code

TODO

You can add a field ID to postMessage, and after each processing, record the ID of the last message that was processed last time. The next processing will be processed after that message