週記-工做小總結

document.write

document.write 能夠用來同步引入外部js。javascript

若是不用模塊加載的庫,咱們引入外部js的方法是createElement script標籤,而後再監聽onload事件。html

咱們也能夠直接在代碼裏使用以下代碼前端

docuemnt.write('http://xxx.com/xxx.js');

// xxxxxx 後續代碼
複製代碼

瀏覽器會等到document.write的js文件加載並執行完以後,纔會執行後續代碼。不過要注意一點,外部js裏若是又引用裏其餘的js,瀏覽器是不會等待其餘的js文件加載完的。vue

原生端和移動web端通訊方式

在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');
複製代碼
注意:WKweview支持用MessageHandler的方式進行通訊

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 源碼 parseHTML 函數的正則表達式

文件路徑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"'=<>`]+)))?/
複製代碼

attribute

這個正則表示式式用來匹配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

ncname 的概念是不包含冒號(:)的 XML 名稱,關於XML名稱的規範在這裏能查到 XML 詞彙表, 也就是這個正則表達式是用來匹配規範的XML標籤名稱

const ncname = '[a-zA-Z_][\\w\\-\\.]*'
複製代碼
// [a-zA-Z_]  匹配 a-z, A-z, 以及下劃線內的全部字符
// [\\w\\-\\.]* 匹配全部字母、數字、下劃線,中劃線,以及除換行符(\n、\r)以外的任何單個字符,
// 爲何要雙斜槓,由於這個是字符串,做爲下一步 new RegExp 的參數。
複製代碼

qname

qname 就是:<前綴:標籤名稱>,也就是合法的XML標籤

const qnameCapture = `((?:${ncname}\\:)?${ncname})`

// 這個是 qnameCapture 字符串的值 
// ((?:[a-zA-Z_][\w\-\.]*\:)?[a-zA-Z_][\w\-\.]*)
複製代碼

startTagOpen

匹配開始標籤的標籤名稱

const startTagOpen = new RegExp(`^<${qnameCapture}`)

// 這個是 startTagOpen 正則表達式的值 
// /^<((?:[a-zA-Z_][\w\-\.]*\:)?[a-zA-Z_][\w\-\.]*)/
複製代碼

endTag

匹配結束標籤的標籤名稱

const endTag = new RegExp(`^<\\/${qnameCapture}[^>]*>`)

// 這個是 endTag 正則表達式的值 
// /^<\/((?:[a-zA-Z_][\w\-\.]*\:)?[a-zA-Z_][\w\-\.]*)[^>]*>/
複製代碼

doctype

匹配文檔的DocType 類型

comment

匹配註釋

conditionalComment

匹配條件註釋

我印象中條件註釋語句是長下面這樣的

<!--[if IE 8 ]> xxx <![endif]-->
複製代碼

但是這個表達式是這樣的

const conditionalComment = /^<!\[/
複製代碼

因此這裏還沒搞清楚。

參考

Vue技術內幕 強力推薦,做者業界良心。

相關文章
相關標籤/搜索