├── imgs └── index.js ├── style └── index.js ├── package.json ├── LICENSE ├── README.md └── index.js /imgs/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | export default { 4 | // icon: require('./icon.png'), 5 | } 6 | -------------------------------------------------------------------------------- /style/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import { 4 | StyleSheet, 5 | Dimensions 6 | } from 'react-native'; 7 | 8 | export default StyleSheet.create({ 9 | webview: { 10 | flexGrow: 1, 11 | paddingLeft: 5, 12 | paddingRight: 5, 13 | } 14 | }); 15 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-native-webview2", 3 | "version": "1.1.1", 4 | "description": "This is the `WebView` component in React Native both for Android and iOS, support `auto height` & call js between component and html page, very useful & easily!", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/greatbsky/react-native-webview2.git" 12 | }, 13 | "keywords": [ 14 | "react-native-webview2", 15 | "WebView", 16 | "Web", 17 | "auto height", 18 | "call js", 19 | "react-native" 20 | ], 21 | "author": "architect.bian", 22 | "license": "MIT", 23 | "bugs": { 24 | "url": "https://github.com/greatbsky/react-native-webview2/issues" 25 | }, 26 | "homepage": "https://github.com/greatbsky/react-native-webview2#readme" 27 | } 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 greatbsky 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # react-native-webview2 2 | 3 | [![reactnative Version](https://img.shields.io/badge/reactnative-V0.40.0%2B-brightgreen.svg)](http://facebook.github.io/react-native/versions.html) 4 | [![NPM Version](https://img.shields.io/npm/v/react-native-webview2.svg?style=flat-square)](https://www.npmjs.com/package/react-native-webview2) 5 | [![NPM Downloads](https://img.shields.io/npm/dm/react-native-webview2.svg?style=flat-square)](https://www.npmjs.com/package/react-native-webview2) 6 | [![GitHub issues](https://img.shields.io/github/issues/greatbsky/react-native-webview2.svg)](https://github.com/greatbsky/react-native-webview2/issues) 7 | [![GitHub stars](https://img.shields.io/github/stars/greatbsky/react-native-webview2.svg)](https://github.com/greatbsky/react-native-webview2/stargazers) 8 | [![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/greatbsky/react-native-webview2/master/LICENSE) 9 | [![Twitter](https://img.shields.io/twitter/url/https/github.com/greatbsky/react-native-webview2.svg?style=social)](https://twitter.com/intent/tweet?text=Wow:&url=%5Bobject%20Object%5D) 10 | 11 | 12 | This is the `WebView` or `Web` component in React Native both for Android and iOS, support `auto height` & `call js` (not support on ios) between component and html document, very useful & easily! 13 | 14 | This is a JavaScript-only implementation of `WebView` in React Native, named `react-native-webview2` or `WebView` or `Web`. 15 | 1. `react-native-webview2` can change the height of `WebView` dynamically when you set the prop `source={uri:xxx}`(until now not yet support html) if you not set the prop `style={height:xxx}`, otherwise the height of `WebView` is fixed. 16 | 2. `react-native-webview2` also can make you call js in html document or reactnative, if you want to call js in html page from react-native, you just invoke `this.web.evalJs("js code...here")` from react-native. If you want to call react-native code, you just invoke `returnEval("rn code...here")` from html page, meanwhile set the prop `evalReturn={((r) => {eval(r)}).bind(this)}`. 17 | 3. `react-native-webview2` support all props of `WebView` in React Native. 18 | 19 | `WebView` demo project: https://github.com/greatbsky/react-native-webview2-demo 20 | 21 | ## `WebView` Demo 22 | 23 | ![](https://raw.githubusercontent.com/greatbsky/react-native-webview2-demo/master/WebView2App/image/demo.gif) 24 | 25 | ## `WebView` Usage 26 | 1. Run `npm install react-native-webview2@latest --save` 27 | 2. Code like this: 28 | ``` 29 | import Web from 'react-native-webview2'; 30 | 31 | {this.web = c}} 33 | evalReturn={((r) => {eval(r)}).bind(this)} 34 | source={{uri: 'xxx'}} 35 | style={[styles.web, {minHeight: 300}]} 36 | ...other props 37 | /> 38 | ``` 39 | 3. Full demo code: https://github.com/greatbsky/react-native-webview2-demo/blob/master/WebView2App/app.js 40 | 41 | 42 | ## `WebView` configuration 43 | 44 | **special props for `WebView`** 45 | * **`evalJs`**: (not support on ios) handle function if you want to call js in html page from react-native. eg: ``` this.web.evalJs('var t = document.title; alert(t)'); ``` 46 | * **`evalReturn`**: require if you need call js fun in react-native from html page. `evalReturn={((r) => {eval(r)}).bind(this)}`. 47 | * **`go`**: handle function if you need open a new uri. eg: ``` this.web.go('http://xxxxxx'); ``` 48 | 49 | **other** 50 | * **`returnEval`**: js function in html page if you want to call js in react-native from html page, eg:```returnEval('this.setText("from html page...")')```, usually you also need set the prop of component `evalReturn={((r) => {eval(r)}).bind(this)}` 51 | 52 | ## Licensed 53 | MIT License 54 | 55 | # 中文说明请参见 56 | 57 | https://github.com/greatbsky/react-native-webview2/wiki 58 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import React, { Component } from 'react'; 4 | import { 5 | View, 6 | WebView 7 | } from 'react-native'; 8 | 9 | import styles from './style/index.js'; 10 | 11 | /** 12 | 通过webview里网页的url的hash进行js相互调用,并实现autoheight功能,只支持source={uri},不支持source={html} 13 | Demo: 14 | import Web from 'react-native-webview2'; 15 | 16 | {eval(r)} 18 | ref={(c) => {this.web = c}} 19 | source={{uri: 'xxx'}} 20 | style={[styles.web, {minHeight: 300}]} 21 | ...other props 22 | /> 23 | */ 24 | export default class extends Component { 25 | 26 | constructor(props) { 27 | super(props); 28 | this.isEnable = (this.props.source && this.props.source.uri) ? true : false; 29 | this.state = Object.assign({}, props, { 30 | source: this.props.source, 31 | pageId: Math.random(), 32 | nativeJsId: Math.random(), 33 | style: this.props.styles ? this.props.styles : styles.webview, 34 | }); 35 | this.initJavaScript = this.initJavaScript.bind(this); 36 | this.onMessage = this.onMessage.bind(this); 37 | this.setHeight = this.setHeight.bind(this); 38 | this.evalJs = this.evalJs.bind(this); 39 | this.evalReturn = this.evalReturn.bind(this); 40 | this.go = this.go.bind(this); 41 | this.reload = this.reload.bind(this); 42 | this.newPageId = this.newPageId.bind(this); 43 | this.initJavaScript(); 44 | } 45 | 46 | initJavaScript() { 47 | let autoHeightJsFun = `window.autoHeight = function() {window.returnEval('${this.state.nativeJsId};this.setHeight(' + document.documentElement.offsetHeight + ')');};`; 48 | this.initJsCode = ` 49 | window.returnEval = function (v) { 50 | setTimeout(function() { 51 | window.postMessage(String(v)); 52 | }, 0); 53 | }; 54 | ${autoHeightJsFun} 55 | window.ready = function(){ 56 | window.autoHeight(); 57 | }; 58 | function isComplete() { 59 | if (document.readyState == "complete" && document.documentElement.offsetWidth > 0) { 60 | window.ready(); 61 | } else { 62 | setTimeout(isComplete, 100); 63 | } 64 | }; 65 | isComplete(); 66 | `; 67 | this.state.injectedJavaScript = this.initJsCode + this.props.injectedJavaScript; 68 | } 69 | 70 | onMessage(e) { 71 | // console.log('-----------------------onMessage'); 72 | // console.log(e.nativeEvent.data); 73 | this.props.onMessage && this.props.onMessage(e); 74 | this.evalReturn(e.nativeEvent.data); 75 | } 76 | 77 | setHeight(h) { 78 | this.setState({ 79 | height: h 80 | }); 81 | } 82 | 83 | // only support on android 84 | evalJs(js) { 85 | // console.log('-----------------------evalJs'); 86 | // console.log(js); 87 | this.go(`javascript: ${js};` + Math.random()); 88 | } 89 | 90 | evalReturn(r) { 91 | // console.log('--------------------evalReturn'); 92 | // console.log(r); 93 | if (this.props.evalReturn && r.indexOf(this.state.nativeJsId) == -1) { //外部有传递evalReturn 并且要执行的hash非内嵌的方法 94 | this.props.evalReturn(r); //在外部执行hash 95 | } else { 96 | eval(r); 97 | } 98 | } 99 | 100 | go(uri) { 101 | this.setState({source: { 102 | uri: uri 103 | }}); 104 | } 105 | 106 | goForward() { 107 | this.newPageId(); 108 | this.webview.goForward(); 109 | } 110 | 111 | goBack() { 112 | this.newPageId(); 113 | this.webview.goBack(); 114 | } 115 | 116 | stopLoading() { 117 | this.webview.stopLoading(); 118 | } 119 | 120 | reload() { 121 | this.newPageId(); 122 | this.webview.reload(); 123 | } 124 | 125 | newPageId() { 126 | this.setState({ 127 | pageId: Math.random() 128 | }); 129 | } 130 | 131 | render() { 132 | let height = this.getHeight(this.props.style); //style设置了height就不会autoheight 133 | return ( 134 | 135 | {this.webview = c}} {...this.props} style={[this.state.style, {'height': height}]} source={this.state.source} pageId={this.state.pageId} evalReturn={this.evalReturn} 136 | injectedJavaScript={this.state.injectedJavaScript} 137 | onMessage={this.onMessage} /> 138 | 139 | ); 140 | } 141 | 142 | getHeight(s) { 143 | if (s) { 144 | if (s.length > 1) { 145 | let lastH = -1; 146 | for (var item of s) { 147 | if (item.height) { 148 | lastH = item.height; 149 | } 150 | } 151 | if (lastH > 0) { 152 | return lastH; 153 | } 154 | } else if(s.height) { 155 | return s.height; 156 | } 157 | } 158 | return this.state.height; 159 | } 160 | 161 | } 162 | --------------------------------------------------------------------------------