2017年1月份小程序正式登場,我也和社團小夥伴們一塊兒作了一些小程序,也有一些經驗的積累。小程序自己以便捷輕量、貼近native使用體驗爲核心,成爲了微信新的流量領地。從wepy到mpvue,也有多種小程序開發框架孕育而生,這些框架的誕生也意味着,微信小程序自己的開發體驗並不能知足開發者的實際開發需求。本文也不是去介紹如何高效開發,亦或是去介紹這些框架,只是記錄一下本身肉眼可見的對小程序的探索(要是有不完善的地方求指出)。css
註定這是一個爲前端開發者所設計的開發flow,wxml對於html,wxss對於css。html
也表明了這是一個前端項目,惟一肉眼可見的不一樣之處是標籤名不一樣。前端
小程序整體分爲邏輯層和視圖層,也就是說小程序框架自己就將邏輯層和視圖層分開來了,而不是純web開發,視圖層和邏輯層混合,Vue和React之類的框架實際上也是作的這樣的事情,視圖層只須要去關心UI視圖,邏輯層去處理數據以及用戶的操做狀態等等。vue
微信爲何要這麼幹呢?引用開發指南中的話:webpack
在小程序以前,微信就提供過JS SDK去幫助開發者更高效的開發接近原生體驗的應用,可是光憑SDK沒法完全解決靜態資源離線、UI線程阻塞、頁面切換卡頓等問題。git
產生這些問題的緣由大可能是由於瀏覽器自己的限制,也就是UI線程和JS線程衝突,React 16中的Fiber調度也在一方面是解決此類的問題。孕育而生的就是小程序中的雙線程模型,將邏輯層和視圖層分離。github
咱們經常在開發小程序的過程當中會遇到,模擬器正常可是真機不正常的狀況,主要是由於下面這個表格:web
現代前端開發,已經進入了組件化開發的時代,不管是三大框架仍是新Web標準中的Web Componnents,組件化會大大提升開發效率。小程序也是在後面的更新中才提出了利用Component構造器去實現組件化,在此以前,在小程序中是經過template模板渲染來實現組件化的。json
那麼有了template還爲何要引入Component呢?小程序
小程序開發團隊可能注意到了這一點,因而引入了Component構造器,從小程序層面支持了真正的組件化開發,不管是properties仍是onReady又或者是behaviors,都解決了上述的痛點。
Web開發中,相似Vue之類的框架是經過VDOM或者DocumentFragment之類的去做爲Component構造函數的render模板。而後每個Component類去維護本身的狀態、數據等等。
這都不是咱們這裏的重點,由於相比於這些render模式,小程序自己並不能去經過Javascript直接去控制渲染層的,並且小程序在渲染層的模式是:wxml + wxss。
那麼小程序是怎麼實現組件化呢?
咱們在開發者工具裏來看一下,當我渲染一個組件的時候,會如何渲染呢?
我建立了一個List-Item組件,並在index頁面引入,咱們在開發者工具看下小程序是怎麼渲染的:
顯而易見的,#shadow-root
首先進入個人視線範圍,這是個什麼東東呢?查閱一下相關資料,瞭解到,一個重要的概念——Shadow DOM
,如今它已經進入了新版Shadow DOM v1 規範,從屬於Web Components,順手大膽的預測一下,Web開發的組件化最終多是由Web Component來實現的。由於Web Component已經支持局部做用域、slot插槽等等現有框架所提供的組件化方法,學習Web Component也是我接下來本身學習的目標之一,應該也會寫博客來記錄一下。
微信開發指南中對組件化系統的實現是這麼說的:
Exparser的組件模型與WebComponents標準中的ShadowDOM高度類似。Exparser會維護整個頁面的節點樹相關信息,包括節點的屬性、事件綁定等,至關於一個簡化版的Shadow DOM實現。
也就是說其實小程序的組件就是模仿ShadowDOM,從而實現組件化。
在web開發中,咱們一般能夠從Source panel中看到當前正在執行的腳本文件,小程序開發者工具一樣能夠,指南中是這樣說的:
Sources panel 用於顯示當前項目的腳本文件,同瀏覽器開發不一樣,微信小程序框架會對腳本文件進行編譯的工做,因此在 Sources panel 中開發者看到的文件是通過處理以後的腳本文件,開發者的代碼都會被包裹在 define 函數中,而且對於 Page 代碼,在尾部會有 require 的主動調用。
咱們看下截圖:
當開啓ES6轉ES5的開關以後,每一個js文件會生成一個同名的[name].js[sm],這個文件是轉換前的初始文件,而[name].js就被替換成了ES5版本的代碼。
進一步的,咱們看到這個應用運行在本地51516端口,這個端口實際上是每次重啓開發者工具,隨機分配的一個閒置端口。咱們在瀏覽器中打開127.0.0.1:51516,能夠看到:
簡單分析一下這個html文件。
在這個script中,定義了的全局變量包括路由、當前文件、Component的構造函數、插件等等。咱們順手在控制檯打印一下此時的window對象:
能夠發現,此時window對象上已經被掛載了不少額外的屬性,這也就使得咱們去直接調用wx、Page、Component等方法成爲了可能,與此同時,咱們點開WeixinJSBridge來看:
這個JSBridge主要承擔的責任就是去鏈接JS Core和Native層,是一個典型的事件註冊、監聽、發佈、訂閱的行爲。
從這段代碼能夠看出幾點:
這個__devtoolsConfig顯而易見得是用戶信息以及wx這個對象上所掛載的去調用Native層服務的方法,以及須要受權時的提示信息等,比較讓人意外的是,我在清除全部受權以後,這裏仍然能看到個人openid以及我的敏感信息,可是在實際開發中這些敏感信息其實大多都是經過前端獲取code,而後從後端解密獲取的,因此這一塊是否存在安全問題,還須要進一步的研究。
這段代碼能夠看出,一開始定義的__wxRouteBegain這個變量就是去檢測頁面加載是否成功的。
在開發小程序的過程當中,可能會由於不少限制因素,而致使開發體驗並非很是友好,好比複雜的文件結構,明明能夠官方支持經過loader去作成相似Vue的template的開發模式又或者是jsx之類,更貼近如今前端開發的體驗;更好比說邏輯層和渲染層的分離致使渲染延遲,沒法有效操做dom節點之類的問題。
可是,我的以爲,有機會仍是能夠深刻小程序底層實現,明白它爲何要這麼設計,也能夠幫助咱們成長。相信小程序也會變得愈來愈好,更符合開發直覺~~~