微信小程序開發02-小程序基本介紹

前言

前面咱們研究了下微信小程序的執行流程,由於拿不到源碼,只能算咱們的猜測,咱們須要更加了解小程序還須要作具體的項目,因而咱們將原來那套還算複雜的業務拿出來:html

【組件化開發】前端進階篇之如何編寫可維護可升級的代碼(有些晦澀有些亂,可是對於總體瞭解小程序結構有幫助)前端

咱們用小程序實現這裏的代碼,看看是個什麼樣的體驗,另外我這裏想保證代碼最大程度重用,爲後續一端代碼四端運行作前驅探索。node

頁面複雜度仍是比較高的,包括了:web

① 彈出層小程序

② 頁面跳轉微信小程序

③ 緩存數組

④ 數據請求緩存

⑤ 列表頁、滾動分頁前端框架

⑥ ......微信

我相信完成了這個例子,咱們對小程序業務代碼怎麼寫會有比較好的瞭解,因而讓咱們開始今天的代碼吧。

小程序的佈局

爲何不使用HTML&CSS

微信小程序這種平臺型的超越Hybrid系統誕生仍是有一些客觀條件的,其中一個就是移動端的應用相對來講簡單的多,想一想PC負責的佈局,若是要使用小程序實現,那麼複雜度會提升不少。

小程序代碼編寫邏輯層依舊使用JS完成,可是結構層以及樣式層推出了:

① WXML,Weixin Markup Language,是微信設計的一套標籤語言,與HTML相似,作過React&Vue的同窗會很是熟悉

② WXSS,WeiXin Style Sheets,是一套樣式語言,用於定義樣式,與CSS相似,通常認爲是CSS的子集

由於小程序中UI組件都是Native實現,因此小程序直接手起刀落壓根放棄讓咱們使用HTML容器,這樣作我以爲有個好處是:

爲了更好的限制,我以前也在作Hybrid乃至前端框架,通常來講我會限制到View級別的實習,要求必須按照個人規則作,可是由於入口爲index.html文件,我甚至將全局控制器App的實例化放到了main.js裏面,只提供了建議的作法,事實上HTML仍是太過靈活,有些同事逐漸根本不按照咱們的規則玩,他以爲他的作法更好,可是這樣一來便會破壞了項目的整體性,後續的工程性的優化或者監控可能就不能幫助他了,從某個角度來講,我是承認小程序的作法的。

咱們以前在這裏研究過自定義標籤的作法:從DOM操做看Vue&React的前端組件化,順帶補齊React的demo

1 <article class="cm-page page-list" id="main">
2     <div class="js_sort_wrapper sort-bar-wrapper">
3         <mySortBar :entity="sortEntity"></mySortBar>
4     </div>
5     <myList :entity="listEntity" :sort="sort"></myList>
6 </article>

從這個文章以及小程序的實現能夠看出基本的概念:

① 標籤的出現根本不是作標籤用,而是爲了讓JS捕捉執行相關邏輯,最後生成真正的標籤

② 爲了作更好的限制,小程序根本不提供入口index.html文件了,因此這裏的標籤是用做JS作模板解析後生成Native能識別的代碼,更具體點說是,Native實現了一個組件,組件有不少規則,可使用JS去調用,正如咱們這裏的header組件調用邏輯(JS會設置Native的Header組件展現),這裏若是不太清晰能夠參考下這個文章:淺談Hybrid技術的設計與實現第二彈

固然,小程序底層具體是否是這麼作,咱們不得而知,若是有小程序的同事,能夠指導下:),至此,我以爲能夠從技術層面說明爲何不直接使用HTML&CSS了:更好的業務限制 + 方便JS解析模板被Native執行。

小程序組件

咱們以前作Hybrid應用的時候,事實上只提供了一個真正具備結構的組件Header,其餘loading類的提示組件都比較簡單,而咱們看看小程序提供了哪些組件呢:

容器類組件

view&scroll-view&swiper等做爲容器組件存在,這裏官方有基本介紹,咱們這裏看看其中一個便可:

這裏官方給了一個demo進行說明:

 1 <view class="section">
 2   <view class="section__title">flex-direction: row</view>
 3   <view class="flex-wrp" style="flex-direction:row;">
 4     <view class="flex-item bc_green">1</view>
 5     <view class="flex-item bc_red">2</view>
 6     <view class="flex-item bc_blue">3</view>
 7   </view>
 8 </view>
 9 <view class="section">
10   <view class="section__title">flex-direction: column</view>
11   <view class="flex-wrp" style="height: 300px;flex-direction:column;">
12     <view class="flex-item bc_green">1</view>
13     <view class="flex-item bc_red">2</view>
14     <view class="flex-item bc_blue">3</view>
15   </view>
16 </view>
1 @import "../lib/weui.wxss";
2 
3 .page-section{
4   margin-bottom: 20rpx;
5 }
6 .flex-wrp {display: flex;}
7 .bc_green {background: green;width:100px; height: 100px;}
8 .bc_red {background: red;width:100px; height: 100px;}
9 .bc_blue {background: blue;width:100px; height: 100px;}

能夠將這個標籤理解爲div類組件。

swipe

通常來講,Native提供的輪播圖體驗要好得多,因此這裏也提供了一個Native的組件:

 1 <view class="container">
 2   <view class="page-body">
 3     <view class="page-section page-section-spacing swiper">
 4       <swiper
 5         indicator-dots="{{indicatorDots}}" autoplay="{{autoplay}}" circular="{{circular}}" vertical="{{vertical}}"
 6         interval="{{interval}}" duration="{{duration}}" previous-margin="{{previousMargin}}px" next-margin="{{nextMargin}}px">
 7         <block wx:for="{{background}}" wx:key="*this">
 8           <swiper-item>
 9             <view class="swiper-item {{item}}"></view>
10           </swiper-item>
11         </block>
12       </swiper>
13     </view>
14     <view class="page-section" style="margin-top: 40rpx;margin-bottom: 0;">
15       <view class="weui-cells weui-cells_after-title">
16         <view class="weui-cell weui-cell_switch">
17           <view class="weui-cell__bd">指示點</view>
18           <view class="weui-cell__ft">
19             <switch checked="{{indicatorDots}}" bindchange="changeProperty" data-property-name="indicatorDots" />
20           </view>
21         </view>
22         <view class="weui-cell weui-cell_switch">
23           <view class="weui-cell__bd">自動播放</view>
24           <view class="weui-cell__ft">
25             <switch checked="{{autoplay}}" bindchange="changeProperty" data-property-name="autoplay" />
26           </view>
27         </view>
28         <view class="weui-cell weui-cell_switch">
29           <view class="weui-cell__bd">銜接滑動</view>
30           <view class="weui-cell__ft">
31             <switch checked="{{circular}}" bindchange="changeProperty" data-property-name="circular" />
32           </view>
33         </view>
34         <view class="weui-cell weui-cell_switch">
35           <view class="weui-cell__bd">豎向</view>
36           <view class="weui-cell__ft">
37             <switch checked="{{vertical}}" bindchange="changeProperty" data-property-name="vertical" />
38           </view>
39         </view>
40       </view>
41     </view>
42 
43     <view class="page-section page-section-spacing">
44       <view class="page-section-title">
45         <text>幻燈片切換時長(ms)</text>
46         <text class="info">{{duration}}</text>
47       </view>
48       <slider value="{{duration}}" min="500" max="2000" bindchange="changeProperty" data-property-name="duration" />
49       <view class="page-section-title">
50         <text>自動播放間隔時長(ms)</text>
51         <text class="info">{{interval}}</text>
52       </view>
53       <slider value="{{interval}}" min="2000" max="10000" bindchange="changeProperty" data-property-name="interval" />
54       <view class="page-section-title">
55         <text>前邊距(px)</text>
56         <text class="info">{{previousMargin}}</text>
57       </view>
58       <slider value="{{previousMargin}}" min="0" max="50" bindchange="changeProperty" data-property-name="previousMargin" />
59       <view class="page-section-title">
60         <text>後邊距(px)</text>
61         <text class="info">{{nextMargin}}</text>
62       </view>
63       <slider value="{{nextMargin}}" min="0" max="50" bindchange="changeProperty" data-property-name="nextMargin" />
64     </view>
65   </view>
66 </view>
View Code
 1 Page({
 2   data: {
 3     background: ['demo-text-1', 'demo-text-2', 'demo-text-3'],
 4     indicatorDots: true,
 5     vertical: false,
 6     autoplay: false,
 7     circular: false,
 8     interval: 2000,
 9     duration: 500,
10     previousMargin: 0,
11     nextMargin: 0
12   },
13   changeProperty: function (e) {
14     var propertyName = e.currentTarget.dataset.propertyName
15     var newData = {}
16     newData[propertyName] = e.detail.value
17     this.setData(newData)
18   },
19   changeIndicatorDots: function (e) {
20     this.setData({
21       indicatorDots: !this.data.indicatorDots
22     })
23   },
24   changeAutoplay: function (e) {
25     this.setData({
26       autoplay: !this.data.autoplay
27     })
28   },
29   intervalChange: function (e) {
30     this.setData({
31       interval: e.detail.value
32     })
33   },
34   durationChange: function (e) {
35     this.setData({
36       duration: e.detail.value
37     })
38   }
39 })
View Code

有demo有代碼,仍是比較清晰。

movable-area

提供一個能夠移動的區域,暫時沒想到應用場景......

icon

圖標,小程序這邊還擴展了一下,給了不少默認的圖標樣式,能知足基本需求

text

文本

rich-text

富文本,用於展現文章,支持HTML,這裏的nodes屬性建議使用數組,類型,還不如系統本身解析js算了,由於不會有人像這樣寫代碼(nodes看上去很蠢):

 1 Page({
 2   data: {
 3     html: '<div class="div_class" style="line-height: 60px; color: red;">Hello&nbsp;World!</div><script>console.log(1)</script>',
 4     nodes: [{
 5       name: 'div',
 6       attrs: {
 7         class: 'div_class',
 8         style: 'line-height: 60px; color: red;'
 9       },
10       children: [{
11         type: 'text',
12         text: 'Hello&nbsp;World!'
13       }]
14     }]
15   },
16   tap() {
17     console.log('tap')
18   }
19 })

progress

進度條

button

按鈕

checkbox

選擇框

form

表單相關

input

輸入框,小程序的數據流動是單向的,每次數據更新,動態調用setData改變數據便會觸發view更新,底層實現便不知道了;文本框值改變js須要本身去獲取

label

與html一致,用以點擊文字操做控件,主要用於文本框

picker&picker-view

用於級聯操做

navigator&function-page-navigator

頁面連接,這個組件感受不利於跳轉收口,建議少用

其餘組件請你們直接到這裏來看demo,很是清晰:

https://developers.weixin.qq.com/miniprogram/dev/component/map.html#map

總結

能夠看出,小程序Native層是將經常使用的HTML標籤分別都實現了一次,使用這些組件能夠拼接處任何複雜的組件。至於樣式方面,WXSS與CSS大同小異,其中主要區別是小程序沒有使用px而是使用的rpx,這個相似於rem的實現,爲了解決移動端的適配問題而存在,總而言之,你在iPhone6設計搞上是多少px就寫成多少rpx就行,其他系統會幫你完成適配工做,這塊透明作的很好,後續樣式咱們直接上實例便可。

小程序的生命週期

咱們這裏上一張圖:

這張圖不但真實反映了Page的生命週期,也將咱們以前的猜測作了一個證實,解讀這張圖大概是這個意思(未必正確,若有錯誤請指出):

Native層在載入小程序時候,起了兩個線程一個的view Thread一個是AppService Thread,我這邊理解下來應該就是程序邏輯執行與頁面渲染分離,也許是想優化性能,這裏更具體一點的解釋是(帶有猜想了):微信會開一個webview來執行咱們的JS邏輯,而後會開一個Native View UI執行頁面渲染;兩個部分是彼此獨立的,頁面點擊時候觸發事件,View線程會獲取APPService服務線程(其實就是獲取webview),執行其中的js邏輯;APPService執行js邏輯改變數據經過setData調用,觸發一個JSCore通訊,通知view線程執行UI更新,這裏結合這張圖作下理解:

① 微信打開一個小程序時,主UI線程繼續運行,開啓一個webview(我認爲這裏的主線程就是view Thread,webview就是APPService線程,這裏可能有誤

② 主View等待構建頁面命令,邏輯層開始載入js邏輯(編譯過),微信底層應該會將WXML以及WXSS翻譯爲JS代碼,邏輯層執行JS代碼作一些初始化工做APP結束後,開始Page邏輯,而他這個圖只有Page的邏輯,沒有將app囊括進去,這裏也引發了我一個疑惑:我在onLoad的時候打了個斷點,而頁面這個時候事實上已經進行告終構層的渲染,也就是說頁面的WXML邏輯已經執行了:

若是要按照我現有的邏輯下作解釋的話,我認爲實例化Page的時候,執行了一個create事件,可是小程序並無釋放onCreate事件讓咱們作註冊,因此我這裏知識體系的基礎依舊是:

JS邏輯先於Native UI 執行,頁面渲染是由實例化Page時候發出

因此我以爲,這裏的圖好像少了一部分(或者說我理解是有問題的):

③ 業務線程執行實例化Page邏輯,引起onLoad、onShow事件,onShow的時候頁面初步渲染已經結束,若是系統有異步數據或者其餘再次數據渲染會執行setData,引起Native UI更新,邏輯結束

可是微信給出的圖不多是錯的,而從圖上看,首次異步通知是由View Thread發起的,我這裏就非常困惑了😪,由於我認爲邏輯發起者必定是邏輯層的js發出通知

總結

今天咱們對小程序進行了基本的瞭解學習,明天咱們持續完成咱們的demo吧

相關文章
相關標籤/搜索