New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WEEX-233][iOS] More enhanced about <web> component #1047

Closed
wants to merge 8 commits into
base: master
from

Conversation

Projects
None yet
3 participants
@tw93
Contributor

tw93 commented Mar 5, 2018

Hi, I'm Tw93(侑夕) from Fliggy, I'd like to discuss the enhancements about component, let it take over where we can't implement through weex.

Target

<web> is used to display web content that specified by src attribute in weex page,We also can use webview module to control WebView behavior such as goBack, goForward and reload.

But it's not enough in most businesses,I think a more enhanced web component should have the following:

  • Support to send messages from Weex to a html in component.
  • Support to send messages from a html in component to Weex.
  • Support to render html source.

Previously, component was an island that only rendered a remote url, but enabled it to communicate through the context native to the webView. Then I'm going to describe the solution that I came up with.

My solution

Code

Demo && Theory

Details

Support to send messages from Weex to a html in component.

  • Native:(W3c MessageEvent)

     // Weex postMessage to web
    - (void)postMessage:(NSDictionary *)data {
        WXSDKInstance *instance = [WXSDKEngine topInstance];
    
        NSMutableString *bundleUrlOrigin = @"";
    
        if (instance.pageName) {
            NSString *bundleUrl = [instance.scriptURL absoluteString];
            NSURL *url = [NSURL URLWithString:bundleUrl];
            bundleUrlOrigin = [NSString stringWithFormat:@"%@://%@%@", url.scheme, url.host, url.port ? [NSString stringWithFormat:@":%@", url.port] : @""];
        }
    
        NSDictionary *initDic = @{
            @"type" : @"message",
            @"data" : data,
            @"origin" : bundleUrlOrigin
        };
    
        NSString *json = [WXUtility JSONString:initDic];
    
        NSString *code = [NSString stringWithFormat:@"(function (){window.dispatchEvent(new MessageEvent('message', %@));}())", json];
        [_jsContext evaluateScript:code];
    }
    
  • How to use:

      // Weex
      const webview = weex.requireModule('webview');
      // recommend
      this.$refs['wxc-web'].postMessage({ detail: "a message" });
      //not recommend
      //webview.postMessage(this.$refs.webview, {detail:"a message"});
    
      // Web 
      window.addEventListener('message',function(e){
      console.log(e.data,e.type,e.origin); // { detail: "a message" },"message","*"
    },false)
    

Support to send messages from a html in component to Weex.

  • Native:(W3c MessageEvent)

    //Weex catch postMessage event from web
        _jsContext[@"postMessage"] = ^() {
    
            NSArray *args = [JSContext currentArguments];
    
            if (args && args.count < 2) {
                return;
            }
    
            NSDictionary *data = [args[0] toDictionary];
            NSString *origin = [args[1] toString];
    
            if (data == nil) {
                return;
            }
    
            NSDictionary *initDic = @{ @"type" : @"message",
                                       @"data" : data,
                                       @"origin" : origin
            };
    
            [weakSelf fireEvent:@"message" params:initDic];
        };
    
  • How to use:

      // Weex
      <web @message="onMessage"></web>
      
       onMessage (e) {
              console.log(e.data,e.type,e.origin); // { detail: "a message" },"message","*"
        },
      
      // Web iframe
        window.parent.postMessage({ detail: "a message" }, '*');
    

Support to render html source.

  • Native:

    [_webview loadHTMLString:_source baseURL:nil];
    
  • How to use:

    <web source='<p style="text-align: center;"><img align="absmiddle" src="http://img03.taobaocdn.com/imgextra/i3/1124701655/TB2zmmIcpXXXXbIXpXXXXXXXXXX_!!1124701655.jpg"/></p>'></web>

Welcome to put forward any suggestion about the solution or other requirements for the component, Thanks!

@weex-bot

This comment has been minimized.

weex-bot commented Mar 5, 2018

Messages
📖 has no android file changed.
📖 android test finished.

Generated by 🚫 dangerJS

@tw93 tw93 closed this Mar 7, 2018

@tw93 tw93 reopened this Mar 7, 2018

tw93 added some commits Mar 7, 2018

@@ -27,6 +27,7 @@ @implementation WXWebViewModule
@synthesize weexInstance;

This comment has been minimized.

@acton393

acton393 Mar 7, 2018

Member

webViewModule method is deprecated gradually as we support component method, the same expose way as module method
see more details: http://weex.apache.org/guide/extend-ios.html#component-method

Maybe it will be better if use component method

This comment has been minimized.

@tw93

tw93 Mar 7, 2018

Contributor

Thinks @acton393 , I have modified it

@@ -69,6 +71,11 @@ - (instancetype)initWithRef:(NSString *)ref type:(NSString *)type styles:(NSDict
{
if (self = [super initWithRef:ref type:type styles:styles attributes:attributes events:events weexInstance:weexInstance]) {
self.url = attributes[@"src"];
if(attributes[@"source"]){
self.source = attributes[@"source"];

This comment has been minimized.

@acton393

acton393 Mar 7, 2018

Member

the init method is executed in background thread named component method and self.source will call [self setSource:""],
the method for setSource called view operation which is only for main thread.

A better way is that define another member for source to save the variable during this initialization, and call self.source in component hook lifeCycle like viewDidLoad.

@@ -104,6 +142,10 @@ - (void)updateAttributes:(NSDictionary *)attributes
if (attributes[@"src"]) {
self.url = attributes[@"src"];
}
if (attributes[@"source"]) {

This comment has been minimized.

@acton393

acton393 Mar 7, 2018

Member

maybe we should update the initSource when update attributes,
as the view can be unloaded during the screen scroll, so the viewDidLoad method can called again with initSource

This comment has been minimized.

@tw93

tw93 Mar 7, 2018

Contributor

done!

tw93 added some commits Mar 7, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment