document.write 能夠用來同步引入外部js。javascript
若是不用模塊加載的庫,咱們引入外部js的方法是createElement script標籤,而後再監聽onload事件。html
咱們也能夠直接在代碼裏使用以下代碼前端
docuemnt.write('http://xxx.com/xxx.js');
// xxxxxx 後續代碼
複製代碼
瀏覽器會等到document.write的js文件加載並執行完以後,纔會執行後續代碼。不過要注意一點,外部js裏若是又引用裏其餘的js,瀏覽器是不會等待其餘的js文件加載完的。vue
在app內部嵌入h5頁面,迫於webview的安全限制,有時會須要調用原生端提供的方法,來完成交互。(例如安卓webview不支持input file控件
)java
通訊方式有三種:android
① url攔截方式 - 不推薦ios
② JsBridge 方式 - 安全性較高,推薦git
Android JsBridgegithub
iOS JsBridgeweb
內容較多,用法可參考文檔。
③ 安卓使用註解,ios使用JSContext方式
原理:
安卓端暴露一個對象,並給這個對象添加方法。前端能夠在window上下文獲取到這個對象。
iOS 能夠獲取到 UIWebview 的當前 window 上下文, 也就是讓OC 和 JS 共享同一個 JSContext。
android :
// 只展現重要代碼
// 獲取 webview
WebView mwebView = (WebView) findViewById(R.id.webview);
// 開啓js支持
mWebView.getSettings().setJavaScriptEnabled(true);
// 設置本地調用對象, JSInterface 爲 js與原生通訊的橋樑接口對象
mWebView.addJavascriptInterface(new JavaScriptInterface(this), "JSInterface");
/*------------------------------------------------------------------------------*/
// 定義可以讓javascript調用的方法
public Class JavaScriptInterface {
Context mContext;
public JavaScriptInterface(Context c) {
mContext = c;
}
@JavascriptInterface // 加註解
public void showToast(String str) {
Toast.makeText(mContext, str, Toast.LENGTH_LONG).show();
}
}
複製代碼
ios:
// 只展現重要代碼
-(void)webViewDidFinishLoad:(UIWebView *)webView
{
//獲取當前 JS 環境
JSContext *context=[webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
//其中 testLog 是 js 的方法名稱,賦給是一個 block 裏面是 iOS 代碼
//此方法最終將打印出全部接收到的參數
context[@"testLog"] = ^() {
NSArray *args = [JSContext currentArguments];
for (id obj in args) {
NSLog(@"%@",obj);
}
};
}
複製代碼
javascript:
// Android
window.JSInterface.showToast('js調用安卓');
// ios
window.testLog('js調用ios');
複製代碼
ios:
// 1. WKWebView注入ScriptMessageHandler
[wkWebView.configuration.userContentController
addScriptMessageHandler:(id <WKScriptMessageHandler>)scriptMessageHandler name:@"xxxx"];
// 2. 提供setWebViewAppearance方法,這樣就能反射出H5即將傳來的字符串@"setWebViewAppearance"
- (void)setWebViewAppearance {
}
複製代碼
javascript:
// window.webkit.messageHandlers.<name>.postMessage(<messageBody>)
window.webkit.messageHandlers.xxxx.postMessage(data);
複製代碼
文件路徑vue項目下: src/compiler/parser/html-parser
代碼以下:
// Regular Expressions for parsing tags and attributes
const attribute = /^\s*([^\s"'<>\/=]+)(?:\s*(=)\s*(?:"([^"]*)"+|'([^']*)'+|([^\s"'=<>`]+)))?/
// could use https://www.w3.org/TR/1999/REC-xml-names-19990114/#NT-QName
// but for Vue templates we can enforce a simple charset
const ncname = '[a-zA-Z_][\\w\\-\\.]*'
const qnameCapture = `((?:${ncname}\\:)?${ncname})`
const startTagOpen = new RegExp(`^<${qnameCapture}`)
const startTagClose = /^\s*(\/?)>/
const endTag = new RegExp(`^<\\/${qnameCapture}[^>]*>`)
const doctype = /^<!DOCTYPE [^>]+>/i
// #7298: escape - to avoid being pased as HTML comment when inlined in page
const comment = /^<!\--/
const conditionalComment = /^<!\[/
複製代碼
一個個來
const attribute = /^\s*([^\s"'<>\/=]+)(?:\s*(=)\s*(?:"([^"]*)"+|'([^']*)'+|([^\s"'=<>`]+)))?/
複製代碼
這個正則表示式式用來匹配html屬性的,如'class="adc def"'。
首先咱們要清楚幾個知識點:
// 正則中表達式的含義
^ ---- 匹配輸入字符串的開始位置,若是在方括號中,則表示排除
?: ---- 表示匹配但不捕獲結果
複製代碼
這個正則咋一看又臭又長,讓人丈二和尚摸不着頭腦。咱們能夠試着把它拆分開再看,如圖:
// ^\s*([^\s"'<>\/=]+) 從字符串的開頭開始匹配,捕獲非空白字符,非單雙引號,非大於號小於號,非斜槓,非等號的任何字符, 這段是匹配屬性名稱用的。
// \s*(=)\s* 捕獲等號,等號先後能夠有多個空白字符
// "([^"]*)"+ 捕獲雙引號之間非雙引號的全部內容,也就是屬性的值
// '([^']*)'+ 捕獲單引號之間非單雙引號的全部內容,也是匹配屬性值。由於html中容許屬性值寫單引號
// ([^\s"'=<>`]+) 捕獲非空白字符,非單雙引號,非等號,非大於號小於號,非反撇號的任何字符,用於匹配相似 readonly, disabled 之類能夠不用寫屬性值的屬性
// 測試一下
const attribute = /^\s*([^\s"'<>\/=]+)(?:\s*(=)\s*(?:"([^"]*)"+|'([^']*)'+|([^\s"'=<>`]+)))?/
console.log('class="some-class"'.match(attribute)) // 測試雙引號
// 輸出
[
"class="some-class""
"class"
"="
"some-class"
undefined
undefined
]
複製代碼
ncname 的概念是不包含冒號(:)的 XML 名稱,關於XML名稱的規範在這裏能查到 XML 詞彙表, 也就是這個正則表達式是用來匹配規範的XML標籤名稱
const ncname = '[a-zA-Z_][\\w\\-\\.]*'
複製代碼
// [a-zA-Z_] 匹配 a-z, A-z, 以及下劃線內的全部字符
// [\\w\\-\\.]* 匹配全部字母、數字、下劃線,中劃線,以及除換行符(\n、\r)以外的任何單個字符,
// 爲何要雙斜槓,由於這個是字符串,做爲下一步 new RegExp 的參數。
複製代碼
qname 就是:<前綴:標籤名稱>
,也就是合法的XML標籤
const qnameCapture = `((?:${ncname}\\:)?${ncname})`
// 這個是 qnameCapture 字符串的值
// ((?:[a-zA-Z_][\w\-\.]*\:)?[a-zA-Z_][\w\-\.]*)
複製代碼
匹配開始標籤的標籤名稱
const startTagOpen = new RegExp(`^<${qnameCapture}`)
// 這個是 startTagOpen 正則表達式的值
// /^<((?:[a-zA-Z_][\w\-\.]*\:)?[a-zA-Z_][\w\-\.]*)/
複製代碼
匹配結束標籤的標籤名稱
const endTag = new RegExp(`^<\\/${qnameCapture}[^>]*>`)
// 這個是 endTag 正則表達式的值
// /^<\/((?:[a-zA-Z_][\w\-\.]*\:)?[a-zA-Z_][\w\-\.]*)[^>]*>/
複製代碼
匹配文檔的DocType 類型
匹配註釋
匹配條件註釋
我印象中條件註釋語句是長下面這樣的
<!--[if IE 8 ]> xxx <![endif]-->
複製代碼
但是這個表達式是這樣的
const conditionalComment = /^<!\[/
複製代碼
因此這裏還沒搞清楚。
Vue技術內幕 強力推薦,做者業界良心。