react native之WebView中流入js接口(jsBridge)

by admin on 2018年12月17日

 

前言

在react
native在此以前,大都采取hybird方案,最近WebView已经是app中必不可少的同样片段,拔取react
native之后仍亟待匡助。react
native要旨库中虽富含WebView的包,但光是无限基础支撑,要壮大WebView的效率,手段有就是是流入js,俗称jsBridge。

react native需要iOS7上述系辅助,由此注入js有一定量种植方案:

  1. 经过Request Url截获解析。这是在iOS7事先运用的点子。
  2. 由此系统提供的javascriptCore通信格局。

这边我们谈论第两种方案,倘诺你针对jsBridge不极端熟稔,能够看即首H5与native之间的通信。假设对javascriptCore不熟练,可以拘留这么些javascriptCore详解

既是已有成熟的方案,为啥还要写那篇著作?

抑或那么句话,最好不要修改react
native原有代码,对之后的版本控制以及保障还坏,下边就是来看看哪些不修改react
native实现需求,先放种地址

  简介:为此SharePoint代码加实施之方法,完成接近人人网站内信效率,当然,实现之相比简单,样式也较难看,只为给大家一个执行之简易思路,如发不当,还求见谅。当然,还有就是是截图相比较长,当然为吃我们清楚了解各一样步,并无是博主啰嗦,事先声明。

JS注入实现

若果被WebView注入js,需要WebView资源加载了时,获取WebView的JSContext。也即是当- (void)webViewDidFinishLoad:(UIWebView *)webView回调方法吃经过[webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"]收获上下文,然后便好为所欲为了。

那要点仍然在:如何不侵入react native内部源码

这会儿候category和swizzling隆重登场。首先使用swizzling替换原有webViewDidFinishLoad方法:

+(void)load {

  RCTSwapInstanceMethods([RCTWebView class], @selector(initWithFrame:), @selector(newInitWithFrame:));
  RCTSwapInstanceMethods([RCTWebView class], @selector(webViewDidFinishLoad:), @selector(newWebViewDidFinishLoad:));
}

接下来于新点子中,除了举行原逻辑之外,再实践js注入:

- (void)newWebViewDidFinishLoad:(UIWebView *)webView {

  [self injectWebView: webView];
  [self newWebViewDidFinishLoad: webView];
}

-(void) injectWebView: (UIWebView *) webView {

  JSContext *context = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
  if (context == nil) {
    return;
  }

  //自定义注入对象
  __weak typeof(self) weakSelf = self;
  context[@"alert"] = ^(NSString *message) {

    dispatch_async(dispatch_get_main_queue(), ^{

      UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"" message: message delegate:weakSelf cancelButtonTitle:@"cancel" otherButtonTitles:nil, nil];
      [alert show];
    });

  };
}

此处定义了个大概的函数alert,用于调用native方法。下边验证下流入是否可行,在js侧定义WebView,并机关调用alert方法,为简易从见WebView加载本地html:

const HTML = `<html>

  <body>
    <h1>Hello web view</h1>
    <input type="button" value="call native" onclick='buttonAction()'/>
    <script>
      function buttonAction() {
        alert('native button alert');
      };
      alert('native alert');
    </script>
  </body>
</html>`;

  <WebView
    ref={'webView'}
    automaticallyAdjustContentInsets={false}
    // style={styles.webView}
    source={{html: HTML}}
    // source={{url:'https://www.baidu.com'}}
    javaScriptEnabled={true}
    domStorageEnabled={true}
    decelerationRate="normal"
    onNavigationStateChange={this.onNavigationStateChange}
    onShouldStartLoadWithRequest={this.onShouldStartLoadWithRequest}
    // startInLoadingState={true}
    scalesPageToFit={true}/>

关押下力量:

图片 1

单身提一下,iOS中的WebView每一次finishLoad时JSContext都会面暴发变化,所以只要于历次load截至时再次注入js。还有一样种植意况是,在资源加载过程中得调用native接口,那么尽管要是在WebView创制时又取得JSContext注入js:

- (instancetype)newInitWithFrame:(CGRect)frame {
  RCTWebView *slf = [self newInitWithFrame: frame];

  UIWebView *webView = [slf valueForKey:@"_webView"];
  [self injectWebView: webView];
  return slf;
}

RCTWebView自身提供了一个性能injectedJavaScript,用于资源加载了时自动执行之等同截js脚本。比如你用将jsBridge的js侧代码库注入及目的页,可以行使此特性。

同一、显示力量等同,李四发送站外信为张三:

react native的JSContext获取、注入

react
native项目自身行使的JSContext与WebView的JSContext不是一样拨事情,也就是说你以react
native的JSContext中流入接口,WebView是不可以访问到的,反之亦然。假设您需要用js接口在react中及WebView中能同时利用,必须两边都使注入。

react
native关于JSContext的包裹在RCTJSCExecutor未遭,它实现了一个通报RCTJavaScriptContextCreatedNotification,当JSContext创立了,还未加载main.jsbundle时会发送通知,JSContext作为通知之参数传递过来。

于是,一切就简单了,我们报了名之文告获JSContext:

+(void)load {

  [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(recieveNotification:) name:RCTJavaScriptContextCreatedNotification object:nil];
}

+(void) recieveNotification: (NSNotification *) notification {

  JSContext *context = notification.object;
  __weak typeof(self) weakSelf = self;

  //这里由js线程调用,所以UI操作需要指定主线程
  context[@"alert"] = ^(NSString *message) {

    dispatch_async(dispatch_get_main_queue(), ^{

      UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"" message:@"native alert" delegate:weakSelf cancelButtonTitle:@"cancel" otherButtonTitles:nil, nil];

      [alert show];
    });

  };
}

意义实现了,不过那里要提拔一句,react
native实现了扳平仿js与native模块化通信的体制,尽管咱依旧得以给react通过JSContext注入的措施,但非提出如此使用,通过react
native提供的模块导出方法才是正道。

关于react native模块的知,可以参照react
native之模块

要是欲驾驭react native通信机制原理,可以参见react
native之OC以及js之间相互

这么些还偏源码,可能有些读者不爱雅观,前边会独自生一致首react native模块开发的章节。

1、李四发站内信,给张三,如下图所示:

图片 2

2、发送了后,查看李四的收件箱,为空,如下图:

图片 3

3、发送完后,查看李四的发件箱,有李四给张三发送的立内信,如下图:

图片 4

4、切换账号,张三登陆,查看右上比赛登录信息,张三;右上较量有平等上不念消息指示,是独WebPart,把鼠标在下边,看到状态栏有链接,是查看站内信的链接,点击进入;

图片 5

5、进入收件箱,发现张三的收件箱里,有李四发被张三的立外信,如下图:

图片 6

6、进入发件箱,发现并未其余站内信,如下图:

图片 7

7、切换回来收件箱,然后点击那长长的吸收的站外信,如下图:

图片 8

8、点击查看站内信,站内信的题、内容、接受者、发送者、是否读,样式有点难看,其实能够稍微美化下,时间仓促,也远非做,凑合见人吧,如下图:

图片 9

9、查看后,重返http://mytravels/SitePages/MyMessage.aspx页面,发现阅读了的那么长音信,下边的加粗没有了,如下图(相比7,可能拘留不深精晓,可以点击大图):

图片 10

次、显示效果二,张三发送站外信为联络人组

1、发送站内信,Receiver接受者输入联系人组“联系人”,如下图;

图片 11

2、特别表明,联系人组,有张三及李四六只人口,如下图:

图片 12

3、站外信发送了后,张三的立内信收件箱有平等长条新立外信,因为他啊在联系人组,如下图:

图片 13

4、张三查看自己的发件箱,唯有刚发送给联络人组的立内信,如下图:

图片 14

5、切换李四账号,进入首页,发现指示有平等长条站外信,如下图:

图片 15

6、进入收件箱,看到张三发给联络人组的站外信,如下图;至此,张三发被关系人组的站外信,张三、李四还接了;

图片 16

其三、结构简单介绍

暴发三三两两摆列表,一张凡发件箱,一张是收件箱如下图介绍:

1、 发件箱列表,如下图所著,包括字段标题、内容、收件人(用户/用户组)

图片 17

2、收件箱列表,通过Sender字段(类型:用户/用户组),确定就漫漫站内信是孰之

图片 18

规律简介:

  发件箱里各级投入一长达信息,通过一个风波触发器来发送站内信,假诺是用户,就朝收件箱里add一长条Item,sender字段就是收件人;如果是用户组,就拿用户组里的人手宣读出来,往收件箱里为每个用户add一漫漫Item。

  发件箱创立一个视图,就是创制者=本人,也就是兼具登陆用户发送的立内信,都亮出了;收件箱通过一个WebPart举办亮,把所有Sender字段是登陆用户的,全体著出来,要是IsRead是否读字段为耶,也就是没有看的,加多少展现,IsRead是否读字段为是,也即是既读的,正常呈现。

  然后,在翻阅页面及,添加一个WebPart,效能是在登陆用户点进去查看这站外信,就用Item.SystemDate()把是否读字段,更新为凡,也便是曾看,这样,重返站内信列表的时候,加多少展现就相会不复存在。

  首先的立内信提醒,是朗诵取Sender==本人,且是否读也乎,也固然是登陆账号没有看之站外信数量,通过Div浮动呈现在右上比赛,加关闭js脚本实现。

季、示例代码:

1、 解决方案结构,如下图所示:

图片 19

2、发件箱的波触发器代码

1、 public static string url = "http://mytravels";

2、 /// <summary>

3、 /// 已°?添¬¨ª加¨®项?.

4、 /// </summary>

5、 public override void ItemAdded(SPItemEventProperties properties)

6、 {

7、 string strTitle = string.Empty;

8、 string strMessage = string.Empty;

9、 string strCreator = string.Empty;

10、 string strReceiver = string.Empty;

11、

12、 strTitle = properties.ListItem["Title"].ToString();

13、 strMessage = properties.ListItem["Message"].ToString();

14、 strCreator = properties.ListItem["Author"].ToString();

15、 strReceiver = properties.ListItem["Receiver"].ToString();

16、

17、 using (SPSite site = new SPSite(url))

18、 {

19、 using (SPWeb web = site.OpenWeb())

20、 {

21、 string str = GetUserString(strReceiver);

22、 if (str.IndexOf("$") > 0)

23、 {

24、 string[] strUser = str.Split(‘$’);

25、 for (int i = 0; i < strUser.Length; i++)

26、 {

27、 SPListItem item = web.Lists["ReceiveList"].Items.Add();

28、 item["Title"] = strTitle;

29、 item["Message"] = strMessage;

30、 item["Sender"] = strUser[i];

31、 item["Onwer"] = strCreator;

32、 item.Update();

33、 }

34、 }

35、 else

36、 {

37、 SPListItem item = web.Lists["ReceiveList"].Items.Add();

38、 item["Title"] = strTitle;

39、 item["Message"] = strMessage;

40、 item["Sender"] = strReceiver;

41、 item["Onwer"] = strCreator;

42、 item.Update();

43、 }

44、 }

45、 }

46、 //base.ItemAdded(properties);

47、 }

48、

49、 public static string GetUserString(string str)

50、 {

51、 string Rs = string.Empty;

52、 string strID = string.Empty;

53、 if (str.IndexOf(";") > 0)

54、 {

55、 strID = str.Split(‘;’)[0];

56、 }

57、 int myID = Convert.ToInt32(strID);

58、 using (SPSite site = new SPSite(url))

59、 {

60、 using (SPWeb web = site.OpenWeb())

61、 {

62、 try

63、 {

64、 SPUser user = web.AllUsers.GetByID(myID);

65、 Rs = str;

66、 }

67、 catch

68、 {

69、 }

70、 try

71、 {

72、 SPGroup group = web.Groups.GetByID(myID);

73、 SPUserCollection usercol = group.Users;

74、

75、 foreach (SPUser user in usercol)

76、 {

77、 if (user.Name == "系¦Ì统ª3帐¨º户¡ì")

78、 continue;

79、 Rs += user.ID + ";#" + user.Name + "$";

80、 }

81、 Rs = Rs.Substring(0, Rs.Length – 1);

82、 }

83、 catch

84、 {

85、 }

}

}

 

return Rs;

}

3、收件箱呈现代码:

protected override void Render(HtmlTextWriter writer)

{

SPSite site = SPContext.Current.Site;

SPWeb web = site.OpenWeb();

SPList list = web.Lists["ReceiveList"];

SPQuery query = new SPQuery();

query.Query = @"<Where>

<Eq>

<FieldRef Name=’Sender’ LookupId=’TRUE’/>

<Value Type=’User’>" + web.CurrentUser.ID.ToString() + @"</Value>

</Eq>

</Where>";

writer.Write("<script>function del(){alert(‘123’);}</script>");

writer.Write("<table>");

writer.Write("<tr><td><a onclick=’del()’>删¦?除y</a></td><td>站?内¨²信?标À¨º题¬a</td><td>创ä¡ä建¡§时º¡À间?</td></tr>");

foreach (SPListItem item in list.GetItems(query))

{

string BoldFont = "style=’text-decoration:none;color:#000000;’";

if (item["IsRead"].ToString() != "True")

{

BoldFont = "style=’text-decoration:none;color:#000000;font-weight:bold;’";

}

writer.Write("<tr><td><input type=’checkbox’ id=’ID" + item["ID"].ToString() + "’/></td><td>");

writer.Write("<a " + BoldFont + " href=’/Lists/ReceiveList/DispForm.aspx?ID=" + item["ID"].ToString() + "’>" + item["Title"].ToString() + "</a>");

writer.Write("</td><td>" + item["Created"].ToString() + "");

writer.Write("</td></tr>");

}

writer.Write("</table>");

//base.Render(writer);

}

4、修改站内信呢曾读代码

protected override void Render(HtmlTextWriter writer)

{

try

{

SPSecurity.RunWithElevatedPrivileges(delegate()

{

using (SPSite site = new SPSite("http://mytravels"))

{

using (SPWeb web = site.OpenWeb())

{

int ItemID = Convert.ToInt32(HttpContext.Current.Request.QueryString["ID"]);

web.AllowUnsafeUpdates = true;

SPListItem item = web.Lists["ReceiveList"].GetItemById(ItemID);

item["IsRead"] = "True";

item.SystemUpdate();

web.AllowUnsafeUpdates = false;

}

}

});

}

catch

{

}

//base.Render(writer);

}

5、首页未念站外信指示代码

protected override void Render(HtmlTextWriter writer)

{

SPSite site = SPContext.Current.Site;

SPWeb web = site.OpenWeb();

SPList list = web.Lists["ReceiveList"];

SPQuery query = new SPQuery();

query.Query = @"<Where>

<And>

<Eq>

<FieldRef Name=’Sender’ LookupId=’TRUE’/>

<Value Type=’User’>" + web.CurrentUser.ID.ToString() + @"</Value>

</Eq>

<Eq>

<FieldRef Name=’IsRead’ />

<Value Type=’Boolean’>False</Value>

</Eq>

</And>

</Where>";

SPListItemCollection itemcoll = list.GetItems(query);

if (itemcoll.Count == 0)

return;

string content = "未¡ä读¨¢站?内¨²信?:êo" + itemcoll.Count.ToString();

writer.Write(@"<div id=’divMessage’ style=’height:25px;position:absolute;z-index:1;float:right;top:15px;right:0px;background-color:#00CCFF’>

<table width=’200′ border=’0′ cellspacing=’0′ cellpadding=’0′>

<tr>

<td><a href=’/SitePages/MyMessage.aspx’>" + content + @"</a></td>

<td><a onclick=’closediv()’>X</a></td>

</tr>

</table>

<script type=’text/javascript’>

function closediv()

{

document.getElementById(‘divMessage’).style.display=’none’;

}

</script>");

}

五、博主感言

  用半龙的日子,实现如此一个效应,感觉就吗是SharePoint相比有利的地点,简单的代码开发,页面定制,完成一个稍微效用,功能也不到底很没有。当然,我未是降级net或者其他支付,笔者对各级一样项技艺,都好器重。

  于SharePoint的开支中,最可怜之感触就是无代码开发和代码开发相结合,那就是待大家对SharePoint现有功用的领悟了解,和对于SharePoint平台的理解,当然,笔者从SharePoint时间啊非是好充足,每个人犹起投机之局限性,在利用业余时间,做点多少物共享为我们,一起学探讨SharePoint,是千篇一律码乐事。

  特别地说,实施进程由于岁月匆忙,代码写的相比较简单,更多为执行功用,很多内需留意的地方,都并未设想太多;再爆发就是对此列表性能方面,也从不涉及太多着想,只是与我们一个简约思路,如有参照,慎行。还有,就是每个人之艺不一致,要是当本文过于简单请绕行,老鸟勿喷,谢谢。

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图