<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                # 小程序 視圖 [TOC] # WXML WXML(WeiXin Markup Language)是框架設計的一套標簽語言,結合[基礎組件](https://developers.weixin.qq.com/miniprogram/dev/component/index.html)、[事件系統](https://developers.weixin.qq.com/miniprogram/dev/framework/view/wxml/event.html),可以構建出頁面的結構。 用以下一些簡單的例子來看看 WXML 具有什么能力: ### [數據綁定](https://developers.weixin.qq.com/miniprogram/dev/framework/view/wxml/data.html) ``` <!--wxml--> <view> {{message}} </view> ``` ``` // page.js Page({ data: { message: 'Hello MINA!' } }) ``` ### [列表渲染](https://developers.weixin.qq.com/miniprogram/dev/framework/view/wxml/list.html) ``` <!--wxml--> <view wx:for="{{array}}"> {{item}} </view> ``` ``` // page.js Page({ data: { array: [1, 2, 3, 4, 5] } }) ``` ### [條件渲染](https://developers.weixin.qq.com/miniprogram/dev/framework/view/wxml/conditional.html) ``` <!--wxml--> <view wx:if="{{view == 'WEBVIEW'}}"> WEBVIEW </view> <view wx:elif="{{view == 'APP'}}"> APP </view> <view wx:else="{{view == 'MINA'}}"> MINA </view> ``` ``` // page.js Page({ data: { view: 'MINA' } }) ``` ### [模板](https://developers.weixin.qq.com/miniprogram/dev/framework/view/wxml/template.html) ``` <!--wxml--> <template name="staffName"> <view> FirstName: {{firstName}}, LastName: {{lastName}} </view> </template> <template is="staffName" data="{{...staffA}}"></template> <template is="staffName" data="{{...staffB}}"></template> <template is="staffName" data="{{...staffC}}"></template> ``` ``` // page.js Page({ data: { staffA: {firstName: 'Hulk', lastName: 'Hu'}, staffB: {firstName: 'Shang', lastName: 'You'}, staffC: {firstName: 'Gideon', lastName: 'Lin'} } }) ``` ### [事件](https://developers.weixin.qq.com/miniprogram/dev/framework/view/wxml/event.html) ``` <view bindtap="add"> {{count}} </view> ``` ``` Page({ data: { count: 1 }, add: function(e) { this.setData({ count: this.data.count + 1 }) } }) ``` 具體的能力以及使用方式在以下章節查看: [數據綁定](https://developers.weixin.qq.com/miniprogram/dev/framework/view/wxml/data.html)、[列表渲染](https://developers.weixin.qq.com/miniprogram/dev/framework/view/wxml/list.html)、[條件渲染](https://developers.weixin.qq.com/miniprogram/dev/framework/view/wxml/conditional.html)、[模板](https://developers.weixin.qq.com/miniprogram/dev/framework/view/wxml/template.html)、[事件](https://developers.weixin.qq.com/miniprogram/dev/framework/view/wxml/event.html)、[引用](https://developers.weixin.qq.com/miniprogram/dev/framework/view/wxml/import.html) # 數據綁定 WXML 中的動態數據均來自對應 Page 的 data。 ## 簡單綁定 數據綁定使用 Mustache 語法(雙大括號)將變量包起來,可以作用于: ### 內容 ``` <view> {{ message }} </view> ``` ``` Page({ data: { message: 'Hello MINA!' } }) ``` ### 組件屬性(需要在雙引號之內) ``` <view id="item-{{id}}"> </view> ``` ``` Page({ data: { id: 0 } }) ``` ### 控制屬性(需要在雙引號之內) ``` <view wx:if="{{condition}}"> </view> ``` ``` Page({ data: { condition: true } }) ``` ### 關鍵字(需要在雙引號之內) `true`:boolean 類型的 true,代表真值。 `false`: boolean 類型的 false,代表假值。 ``` <checkbox checked="{{false}}"> </checkbox> ``` *特別注意:不要直接寫 `checked="false"`,其計算結果是一個字符串,轉成 boolean 類型后代表真值。* ## 運算 可以在 `{{}}` 內進行簡單的運算,支持的有如下幾種方式: ### 三元運算 ``` <view hidden="{{flag ? true : false}}"> Hidden </view> ``` ### 算數運算 ``` <view> {{a + b}} + {{c}} + d </view> ``` ``` Page({ data: { a: 1, b: 2, c: 3 } }) ``` view中的內容為 `3 + 3 + d`。 ### 邏輯判斷 ``` <view wx:if="{{length > 5}}"> </view> ``` ### 字符串運算 ``` <view>{{"hello" + name}}</view> ``` ``` Page({ data:{ name: 'MINA' } }) ``` ### 數據路徑運算 ``` <view>{{object.key}} {{array[0]}}</view> ``` ``` Page({ data: { object: { key: 'Hello ' }, array: ['MINA'] } }) ``` ## 組合 也可以在 Mustache 內直接進行組合,構成新的對象或者數組。 ### 數組 ``` <view wx:for="{{[zero, 1, 2, 3, 4]}}"> {{item}} </view> ``` ``` Page({ data: { zero: 0 } }) ``` 最終組合成數組`[0, 1, 2, 3, 4]`。 ### 對象 ``` <template is="objectCombine" data="{{for: a, bar: b}}"></template> ``` ``` Page({ data: { a: 1, b: 2 } }) ``` 最終組合成的對象是 `{for: 1, bar: 2}` 也可以用擴展運算符 `...` 來將一個對象展開 ``` <template is="objectCombine" data="{{...obj1, ...obj2, e: 5}}"></template> ``` ``` Page({ data: { obj1: { a: 1, b: 2 }, obj2: { c: 3, d: 4 } } }) ``` 最終組合成的對象是 `{a: 1, b: 2, c: 3, d: 4, e: 5}`。 如果對象的 key 和 value 相同,也可以間接地表達。 ``` <template is="objectCombine" data="{{foo, bar}}"></template> ``` ``` Page({ data: { foo: 'my-foo', bar: 'my-bar' } }) ``` 最終組合成的對象是 `{foo: 'my-foo', bar:'my-bar'}`。 注意:上述方式可以隨意組合,但是如有存在變量名相同的情況,后邊的會覆蓋前面,如: ``` <template is="objectCombine" data="{{...obj1, ...obj2, a, c: 6}}"></template> ``` ``` Page({ data: { obj1: { a: 1, b: 2 }, obj2: { b: 3, c: 4 }, a: 5 } }) ``` 最終組合成的對象是 `{a: 5, b: 3, c: 6}`。 注意: 花括號和引號之間如果有空格,將最終被解析成為字符串 ``` <view wx:for="{{[1,2,3]}} "> {{item}} </view> ``` 等同于 ``` <view wx:for="{{[1,2,3] + ' '}}"> {{item}} </view> ``` # 列表渲染 ### wx:for 在組件上使用?`wx:for`?控制屬性綁定一個數組,即可使用數組中各項的數據重復渲染該組件。 默認數組的當前項的下標變量名默認為?`index`,數組當前項的變量名默認為?`item` ``` <view wx:for="{{array}}"> {{index}}: {{item.message}} </view> ``` ``` Page({ data: { array: [{ message: 'foo', }, { message: 'bar' }] } }) ``` 使用?`wx:for-item`?可以指定數組當前元素的變量名, 使用?`wx:for-index`?可以指定數組當前下標的變量名: ``` <view wx:for="{{array}}" wx:for-index="idx" wx:for-item="itemName"> {{idx}}: {{itemName.message}} </view> ``` `wx:for`?也可以嵌套,下邊是一個九九乘法表 ``` <view wx:for="{{[1, 2, 3, 4, 5, 6, 7, 8, 9]}}" wx:for-item="i"> <view wx:for="{{[1, 2, 3, 4, 5, 6, 7, 8, 9]}}" wx:for-item="j"> <view wx:if="{{i <= j}}"> {{i}} * {{j}} = {{i * j}} </view> </view> </view> ``` ### block wx:for 類似?`block wx:if`,也可以將?`wx:for`?用在`<block/>`標簽上,以渲染一個包含多節點的結構塊。例如: ``` <block wx:for="{{[1, 2, 3]}}"> <view> {{index}}: </view> <view> {{item}} </view> </block> ``` ### wx:key 如果列表中項目的位置會動態改變或者有新的項目添加到列表中,并且希望列表中的項目保持自己的特征和狀態(如?`<input/>`?中的輸入內容,`<switch/>`?的選中狀態),需要使用?`wx:key`?來指定列表中項目的唯一的標識符。 `wx:key`?的值以兩種形式提供 1. 字符串,代表在 for 循環的 array 中 item 的某個 property,該 property 的值需要是列表中唯一的字符串或數字,且不能動態改變。 2. 保留關鍵字?`*this`?代表在 for 循環中的 item 本身,這種表示需要 item 本身是一個唯一的字符串或者數字,如: 當數據改變觸發渲染層重新渲染的時候,會校正帶有 key 的組件,框架會確保他們被重新排序,而不是重新創建,以確保使組件保持自身的狀態,并且提高列表渲染時的效率。 如不提供?`wx:key`,會報一個?`warning`, 如果明確知道該列表是靜態,或者不必關注其順序,可以選擇忽略。 示例代碼: [在開發者工具中預覽效果](https://developers.weixin.qq.com/s/tpg5tKmv6kZt "在開發者工具中預覽效果") ``` <switch wx:for="{{objectArray}}" wx:key="unique" style="display: block;"> {{item.id}} </switch> <button bindtap="switch"> Switch </button> <button bindtap="addToFront"> Add to the front </button> <switch wx:for="{{numberArray}}" wx:key="*this" style="display: block;"> {{item}} </switch> <button bindtap="addNumberToFront"> Add to the front </button> ``` ``` Page({ data: { objectArray: [ {id: 5, unique: 'unique_5'}, {id: 4, unique: 'unique_4'}, {id: 3, unique: 'unique_3'}, {id: 2, unique: 'unique_2'}, {id: 1, unique: 'unique_1'}, {id: 0, unique: 'unique_0'}, ], numberArray: [1, 2, 3, 4] }, switch: function(e) { const length = this.data.objectArray.length for (let i = 0; i < length; ++i) { const x = Math.floor(Math.random() * length) const y = Math.floor(Math.random() * length) const temp = this.data.objectArray[x] this.data.objectArray[x] = this.data.objectArray[y] this.data.objectArray[y] = temp } this.setData({ objectArray: this.data.objectArray }) }, addToFront: function(e) { const length = this.data.objectArray.length this.data.objectArray = [{id: length, unique: 'unique_' + length}].concat(this.data.objectArray) this.setData({ objectArray: this.data.objectArray }) }, addNumberToFront: function(e){ this.data.numberArray = [ this.data.numberArray.length + 1 ].concat(this.data.numberArray) this.setData({ numberArray: this.data.numberArray }) } }) ``` 注意: 當?`wx:for`?的值為字符串時,會將字符串解析成字符串數組 ``` <view wx:for="array"> {{item}} </view> ``` 等同于 ``` <view wx:for="{{['a','r','r','a','y']}}"> {{item}} </view> ``` 注意:?花括號和引號之間如果有空格,將最終被解析成為字符串 ``` <view wx:for="{{[1,2,3]}} "> {{item}} </view> ``` 等同于 ``` <view wx:for="{{[1,2,3] + ' '}}" > {{item}} </view> ``` 條件渲染 wx:if 在框架中,使用 wx:if="{{condition}}" 來判斷是否需要渲染該代碼塊: <view wx:if="{{condition}}"> True </view> 也可以用 wx:elif 和 wx:else 來添加一個 else 塊: <view wx:if="{{length > 5}}"> 1 </view> <view wx:elif="{{length > 2}}"> 2 </view> <view wx:else> 3 </view> block wx:if 因為 wx:if 是一個控制屬性,需要將它添加到一個標簽上。如果要一次性判斷多個組件標簽,可以使用一個 <block/> 標簽將多個組件包裝起來,并在上邊使用 wx:if 控制屬性。 <block wx:if="{{true}}"> <view> view1 </view> <view> view2 </view> </block> 注意: <block/> 并不是一個組件,它僅僅是一個包裝元素,不會在頁面中做任何渲染,只接受控制屬性。 wx:if vs hidden 因為 wx:if 之中的模板也可能包含數據綁定,所以當 wx:if 的條件值切換時,框架有一個局部渲染的過程,因為它會確保條件塊在切換時銷毀或重新渲染。 同時 wx:if 也是惰性的,如果在初始渲染條件為 false,框架什么也不做,在條件第一次變成真的時候才開始局部渲染。 相比之下,hidden 就簡單的多,組件始終會被渲染,只是簡單的控制顯示與隱藏。 一般來說,wx:if 有更高的切換消耗而 hidden 有更高的初始渲染消耗。因此,如果需要頻繁切換的情景下,用 hidden 更好,如果在運行時條件不大可能改變則 wx:if 較好。 # 模板 WXML提供模板(template),可以在模板中定義代碼片段,然后在不同的地方調用。 ### 定義模板 使用 name 屬性,作為模板的名字。然后在`<template/>`內定義代碼片段,如: ``` <!-- index: int msg: string time: string --> <template name="msgItem"> <view> <text> {{index}}: {{msg}} </text> <text> Time: {{time}} </text> </view> </template> ``` ### 使用模板 使用 is 屬性,聲明需要的使用的模板,然后將模板所需要的 data 傳入,如: ``` <template is="msgItem" data="{{...item}}"/> ``` ``` Page({ data: { item: { index: 0, msg: 'this is a template', time: '2016-09-15' } } }) ``` is 屬性可以使用 Mustache 語法,來動態決定具體需要渲染哪個模板: ``` <template name="odd"> <view> odd </view> </template> <template name="even"> <view> even </view> </template> <block wx:for="{{[1, 2, 3, 4, 5]}}"> <template is="{{item % 2 == 0 ? 'even' : 'odd'}}"/> </block> ``` ### 模板的作用域 模板擁有自己的作用域,只能使用 data 傳入的數據以及模板定義文件中定義的?`<wxs />`?模塊。 # 事件 ## 什么是事件 * 事件是視圖層到邏輯層的通訊方式。 * 事件可以將用戶的行為反饋到邏輯層進行處理。 * 事件可以綁定在組件上,當達到觸發事件,就會執行邏輯層中對應的事件處理函數。 * 事件對象可以攜帶額外信息,如 id, dataset, touches。 ## 事件的使用方式 * 在組件中綁定一個事件處理函數。 如`bindtap`,當用戶點擊該組件的時候會在該頁面對應的Page中找到相應的事件處理函數。 ``` <view id="tapTest" data-hi="WeChat" bindtap="tapName"> Click me! </view> ``` * 在相應的Page定義中寫上相應的事件處理函數,參數是event。 ``` Page({ tapName: function(event) { console.log(event) } }) ``` * 可以看到log出來的信息大致如下: ``` { "type":"tap", "timeStamp":895, "target": { "id": "tapTest", "dataset": { "hi":"WeChat" } }, "currentTarget": { "id": "tapTest", "dataset": { "hi":"WeChat" } }, "detail": { "x":53, "y":14 }, "touches":[{ "identifier":0, "pageX":53, "pageY":14, "clientX":53, "clientY":14 }], "changedTouches":[{ "identifier":0, "pageX":53, "pageY":14, "clientX":53, "clientY":14 }] } ``` ## 事件詳解 ### 事件分類 事件分為冒泡事件和非冒泡事件: 1. 冒泡事件:當一個組件上的事件被觸發后,該事件會向父節點傳遞。 2. 非冒泡事件:當一個組件上的事件被觸發后,該事件不會向父節點傳遞。 WXML的冒泡事件列表: | 類型 | 觸發條件 | 最低版本 | | --- | --- | --- | | touchstart | 手指觸摸動作開始 | | | touchmove | 手指觸摸后移動 | | | touchcancel | 手指觸摸動作被打斷,如來電提醒,彈窗 | | | touchend | 手指觸摸動作結束 | | | tap | 手指觸摸后馬上離開 | | | longpress | 手指觸摸后,超過350ms再離開,如果指定了事件回調函數并觸發了這個事件,tap事件將不被觸發 | [1.5.0](https://developers.weixin.qq.com/miniprogram/dev/framework/compatibility.html "基礎庫 1.5.0 開始支持,低版本需做兼容處理。") | | longtap | 手指觸摸后,超過350ms再離開(推薦使用longpress事件代替) | | | transitionend | 會在 WXSS transition 或 wx.createAnimation 動畫結束后觸發 | | | animationstart | 會在一個 WXSS animation 動畫開始時觸發 | | | animationiteration | 會在一個 WXSS animation 一次迭代結束時觸發 | | | animationend | 會在一個 WXSS animation 動畫完成時觸發 | | | touchforcechange | 在支持 3D Touch 的 iPhone 設備,重按時會觸發 | [1.9.90](https://developers.weixin.qq.com/miniprogram/dev/framework/compatibility.html "基礎庫 1.9.90 開始支持,低版本需做兼容處理。") | 注:除上表之外的其他組件自定義事件如無特殊聲明都是非冒泡事件,如[`<form/>`](https://developers.weixin.qq.com/miniprogram/dev/component/form.html)的`submit`事件,[`<input/>`](https://developers.weixin.qq.com/miniprogram/dev/component/input.html)的`input`事件,[`<scroll-view/>`](https://developers.weixin.qq.com/miniprogram/dev/component/scroll-view.html)的`scroll`事件,(詳見各個[組件](https://developers.weixin.qq.com/miniprogram/dev/component/index.html)) ### 事件綁定和冒泡 事件綁定的寫法同組件的屬性,以 key、value 的形式。 * key 以`bind`或`catch`開頭,然后跟上事件的類型,如`bindtap`、`catchtouchstart`。自基礎庫版本?[1.5.0](https://developers.weixin.qq.com/miniprogram/dev/framework/compatibility.html "基礎庫 1.5.0 開始支持,低版本需做兼容處理。")?起,在非[原生組件](https://developers.weixin.qq.com/miniprogram/dev/component/native-component.html)中,`bind`和`catch`后可以緊跟一個冒號,其含義不變,如`bind:tap`、`catch:touchstart`。 * value 是一個字符串,需要在對應的 Page 中定義同名的函數。不然當觸發事件的時候會報錯。 `bind`事件綁定不會阻止冒泡事件向上冒泡,`catch`事件綁定可以阻止冒泡事件向上冒泡。 如在下邊這個例子中,點擊 inner view 會先后調用`handleTap3`和`handleTap2`(因為tap事件會冒泡到 middle view,而 middle view 阻止了 tap 事件冒泡,不再向父節點傳遞),點擊 middle view 會觸發`handleTap2`,點擊 outer view 會觸發`handleTap1`。 ``` <view id="outer" bindtap="handleTap1"> outer view <view id="middle" catchtap="handleTap2"> middle view <view id="inner" bindtap="handleTap3"> inner view </view> </view> </view> ``` ### 事件的捕獲階段 自基礎庫版本?[1.5.0](https://developers.weixin.qq.com/miniprogram/dev/framework/compatibility.html "基礎庫 1.5.0 開始支持,低版本需做兼容處理。")?起,觸摸類事件支持捕獲階段。捕獲階段位于冒泡階段之前,且在捕獲階段中,事件到達節點的順序與冒泡階段恰好相反。需要在捕獲階段監聽事件時,可以采用`capture-bind`、`capture-catch`關鍵字,后者將中斷捕獲階段和取消冒泡階段。 在下面的代碼中,點擊 inner view 會先后調用`handleTap2`、`handleTap4`、`handleTap3`、`handleTap1`。 ``` <view id="outer" bind:touchstart="handleTap1" capture-bind:touchstart="handleTap2"> outer view <view id="inner" bind:touchstart="handleTap3" capture-bind:touchstart="handleTap4"> inner view </view> </view> ``` 如果將上面代碼中的第一個`capture-bind`改為`capture-catch`,將只觸發`handleTap2`。 ``` <view id="outer" bind:touchstart="handleTap1" capture-catch:touchstart="handleTap2"> outer view <view id="inner" bind:touchstart="handleTap3" capture-bind:touchstart="handleTap4"> inner view </view> </view> ``` ### 事件對象 如無特殊說明,當組件觸發事件時,邏輯層綁定該事件的處理函數會收到一個事件對象。 BaseEvent 基礎事件對象屬性列表: | 屬性 | 類型 | 說明 | | --- | --- | --- | | [type](https://developers.weixin.qq.com/miniprogram/dev/framework/view/wxml/event.html#type) | String | 事件類型 | | [timeStamp](https://developers.weixin.qq.com/miniprogram/dev/framework/view/wxml/event.html#timestamp) | Integer | 事件生成時的時間戳 | | [target](https://developers.weixin.qq.com/miniprogram/dev/framework/view/wxml/event.html#target) | Object | 觸發事件的組件的一些屬性值集合 | | [currentTarget](https://developers.weixin.qq.com/miniprogram/dev/framework/view/wxml/event.html#currenttarget) | Object | 當前組件的一些屬性值集合 | CustomEvent 自定義事件對象屬性列表(繼承 BaseEvent): | 屬性 | 類型 | 說明 | | --- | --- | --- | | [detail](https://developers.weixin.qq.com/miniprogram/dev/framework/view/wxml/event.html#detail) | Object | 額外的信息 | TouchEvent 觸摸事件對象屬性列表(繼承 BaseEvent): | 屬性 | 類型 | 說明 | | --- | --- | --- | | [touches](https://developers.weixin.qq.com/miniprogram/dev/framework/view/wxml/event.html#touches) | Array | 觸摸事件,當前停留在屏幕中的觸摸點信息的數組 | | [changedTouches](https://developers.weixin.qq.com/miniprogram/dev/framework/view/wxml/event.html#changedtouches) | Array | 觸摸事件,當前變化的觸摸點信息的數組 | 特殊事件:?`<canvas/>`?中的觸摸事件不可冒泡,所以沒有 currentTarget。 ### type 代表事件的類型。 ### timeStamp 頁面打開到觸發事件所經過的毫秒數。 ### target 觸發事件的源組件。 | 屬性 | 類型 | 說明 | | --- | --- | --- | | id | String | 事件源組件的id | | tagName | String | 當前組件的類型 | | [dataset](https://developers.weixin.qq.com/miniprogram/dev/framework/view/wxml/event.html#dataset) | Object | 事件源組件上由`data-`開頭的自定義屬性組成的集合 | ### currentTarget 事件綁定的當前組件。 | 屬性 | 類型 | 說明 | | --- | --- | --- | | id | String | 當前組件的id | | tagName | String | 當前組件的類型 | | [dataset](https://developers.weixin.qq.com/miniprogram/dev/framework/view/wxml/event.html#dataset) | Object | 當前組件上由`data-`開頭的自定義屬性組成的集合 | 說明: target 和 currentTarget 可以參考上例中,點擊 inner view 時,`handleTap3`?收到的事件對象 target 和 currentTarget 都是 inner,而?`handleTap2`?收到的事件對象 target 就是 inner,currentTarget 就是 middle。 #### dataset 在組件中可以定義數據,這些數據將會通過事件傳遞給 SERVICE。 書寫方式: 以`data-`開頭,多個單詞由連字符`-`鏈接,不能有大寫(大寫會自動轉成小寫)如`data-element-type`,最終在 event.currentTarget.dataset 中會將連字符轉成駝峰`elementType`。 示例: ``` <view data-alpha-beta="1" data-alphaBeta="2" bindtap="bindViewTap"> DataSet Test </view> ``` ``` Page({ bindViewTap:function(event){ event.currentTarget.dataset.alphaBeta === 1 // - 會轉為駝峰寫法 event.currentTarget.dataset.alphabeta === 2 // 大寫會轉為小寫 } }) ``` ### touches touches 是一個數組,每個元素為一個 Touch 對象(canvas 觸摸事件中攜帶的 touches 是 CanvasTouch 數組)。 表示當前停留在屏幕上的觸摸點。 #### Touch 對象 | 屬性 | 類型 | 說明 | | --- | --- | --- | | identifier | Number | 觸摸點的標識符 | | pageX, pageY | Number | 距離文檔左上角的距離,文檔的左上角為原點 ,橫向為X軸,縱向為Y軸 | | clientX, clientY | Number | 距離頁面可顯示區域(屏幕除去導航條)左上角距離,橫向為X軸,縱向為Y軸 | #### CanvasTouch 對象 | 屬性 | 類型 | 說明 | 特殊說明 | | --- | --- | --- | --- | | identifier | Number | 觸摸點的標識符 | | | x, y | Number | 距離 Canvas 左上角的距離,Canvas 的左上角為原點 ,橫向為X軸,縱向為Y軸 | | ### changedTouches changedTouches 數據格式同 touches。 表示有變化的觸摸點,如從無變有(touchstart),位置變化(touchmove),從有變無(touchend、touchcancel)。 ### detail 自定義事件所攜帶的數據,如表單組件的提交事件會攜帶用戶的輸入,媒體的錯誤事件會攜帶錯誤信息,詳見[組件](https://developers.weixin.qq.com/miniprogram/dev/component)定義中各個事件的定義。 點擊事件的`detail`?帶有的 x, y 同 pageX, pageY 代表距離文檔左上角的距離。 # 引用 WXML 提供兩種文件引用方式`import`和`include`。 ### import `import`可以在該文件中使用目標文件定義的`template`,如: 在 item.wxml 中定義了一個叫`item`的`template`: ``` <!-- item.wxml --> <template name="item"> <text>{{text}}</text> </template> ``` 在 index.wxml 中引用了 item.wxml,就可以使用`item`模板: ``` <import src="item.wxml"/> <template is="item" data="{{text: 'forbar'}}"/> ``` ### import 的作用域 import 有作用域的概念,即只會 import 目標文件中定義的 template,而不會 import 目標文件 import 的 template。 如:C import B,B import A,在C中可以使用B定義的`template`,在B中可以使用A定義的`template`,但是C不能使用A定義的`template`。 ``` <!-- A.wxml --> <template name="A"> <text> A template </text> </template> ``` ``` <!-- B.wxml --> <import src="a.wxml"/> <template name="B"> <text> B template </text> </template> ``` ``` <!-- C.wxml --> <import src="b.wxml"/> <template is="A"/> <!-- Error! Can not use tempalte when not import A. --> <template is="B"/> ``` ### include `include`?可以將目標文件除了?`<template/>`?`<wxs/>`?外的整個代碼引入,相當于是拷貝到?`include`?位置,如: ``` <!-- index.wxml --> <include src="header.wxml"/> <view> body </view> <include src="footer.wxml"/> ``` ``` <!-- header.wxml --> <view> header </view> ``` ``` <!-- footer.wxml --> <view> footer </view> ``` # WXSS WXSS(WeiXin Style Sheets)是一套樣式語言,用于描述 WXML 的組件樣式。 WXSS 用來決定 WXML 的組件應該怎么顯示。 為了適應廣大的前端開發者,WXSS 具有 CSS 大部分特性。同時為了更適合開發微信小程序,WXSS 對 CSS 進行了擴充以及修改。 與 CSS 相比,WXSS 擴展的特性有: * 尺寸單位 * 樣式導入 ### 尺寸單位 * rpx(responsive pixel): 可以根據屏幕寬度進行自適應。規定屏幕寬為750rpx。如在 iPhone6 上,屏幕寬度為375px,共有750個物理像素,則750rpx = 375px = 750物理像素,1rpx = 0.5px = 1物理像素。 | 設備 | rpx換算px (屏幕寬度/750) | px換算rpx (750/屏幕寬度) | | --- | --- | --- | | iPhone5 | 1rpx = 0.42px | 1px = 2.34rpx | | iPhone6 | 1rpx = 0.5px | 1px = 2rpx | | iPhone6 Plus | 1rpx = 0.552px | 1px = 1.81rpx | 建議:?開發微信小程序時設計師可以用 iPhone6 作為視覺稿的標準。 注意:?在較小的屏幕上不可避免的會有一些毛刺,請在開發時盡量避免這種情況。 ### 樣式導入 使用`@import`語句可以導入外聯樣式表,`@import`后跟需要導入的外聯樣式表的相對路徑,用`;`表示語句結束。 示例代碼: ``` /** common.wxss **/ .small-p { padding:5px; } ``` ``` /** app.wxss **/ @import "common.wxss"; .middle-p { padding:15px; } ``` ### 內聯樣式 框架組件上支持使用 style、class 屬性來控制組件的樣式。 * style:靜態的樣式統一寫到 class 中。style 接收動態的樣式,在運行時會進行解析,請盡量避免將靜態的樣式寫進 style 中,以免影響渲染速度。 ``` <view style="color:{{color}};" /> ``` * class:用于指定樣式規則,其屬性值是樣式規則中類選擇器名(樣式類名)的集合,樣式類名不需要帶上`.`,樣式類名之間用空格分隔。 ``` <view class="normal_view" /> ``` ### 選擇器 目前支持的選擇器有: | 選擇器 | 樣例 | 樣例描述 | | --- | --- | --- | | .class | `.intro` | 選擇所有擁有 class="intro" 的組件 | | #id | `#firstname` | 選擇擁有 id="firstname" 的組件 | | element | `view` | 選擇所有 view 組件 | | element, element | `view, checkbox` | 選擇所有文檔的 view 組件和所有的 checkbox 組件 | | ::after | `view::after` | 在 view 組件后邊插入內容 | | ::before | `view::before` | 在 view 組件前邊插入內容 | ### 全局樣式與局部樣式 定義在 app.wxss 中的樣式為全局樣式,作用于每一個頁面。在 page 的 wxss 文件中定義的樣式為局部樣式,只作用在對應的頁面,并會覆蓋 app.wxss 中相同的選擇器。 # 基礎組件 框架為開發者提供了一系列基礎組件,開發者可以通過組合這些基礎組件進行快速開發。詳細介紹請參考[組件文檔](https://developers.weixin.qq.com/miniprogram/dev/component/index.html)。 什么是組件: * 組件是視圖層的基本組成單元。 * 組件自帶一些功能與微信風格一致的樣式。 * 一個組件通常包括?`開始標簽`?和?`結束標簽`,`屬性`?用來修飾這個組件,`內容`?在兩個標簽之內。 ``` <tagname property="value"> Content goes here ... </tagname> ``` 注意:所有組件與屬性都是小寫,以連字符`-`連接 ### 屬性類型 | 類型 | 描述 | 注解 | | --- | --- | --- | | Boolean | 布爾值 | 組件寫上該屬性,不管是什么值都被當作?`true`;只有組件上沒有該屬性時,屬性值才為`false`。 如果屬性值為變量,變量的值會被轉換為Boolean類型 | | Number | 數字 | `1`,?`2.5` | | String | 字符串 | `"string"` | | Array | 數組 | `[ 1, "string" ]` | | Object | 對象 | `{ key: value }` | | EventHandler | 事件處理函數名 | `"handlerName"`?是?[Page](https://developers.weixin.qq.com/miniprogram/dev/framework/app-service/page.html)?中定義的事件處理函數名 | | Any | 任意屬性 | | ### 公共屬性 所有組件都有以下屬性: | 屬性名 | 類型 | 描述 | 注解 | | --- | --- | --- | --- | | id | String | 組件的唯一標示 | 保持整個頁面唯一 | | class | String | 組件的樣式類 | 在對應的 WXSS 中定義的樣式類 | | style | String | 組件的內聯樣式 | 可以動態設置的內聯樣式 | | hidden | Boolean | 組件是否顯示 | 所有組件默認顯示 | | data-* | Any | 自定義屬性 | 組件上觸發的事件時,會發送給事件處理函數 | | bind* / catch* | EventHandler | 組件的事件 | 詳見[事件](https://developers.weixin.qq.com/miniprogram/dev/framework/view/wxml/event.html) | ### 特殊屬性 幾乎所有組件都有各自定義的屬性,可以對該組件的功能或樣式進行修飾,請參考各個[組件](https://developers.weixin.qq.com/miniprogram/dev/component/index.html)的定義。 # WXS WXS(WeiXin Script)是小程序的一套腳本語言,結合?`WXML`,可以構建出頁面的結構。 ### 注意 1. wxs 不依賴于運行時的基礎庫版本,可以在所有版本的小程序中運行。 2. wxs 與 javascript 是不同的語言,有自己的語法,并不和 javascript 一致。 3. wxs 的運行環境和其他 javascript 代碼是隔離的,wxs 中不能調用其他 javascript 文件中定義的函數,也不能調用小程序提供的API。 4. wxs 函數不能作為組件的事件回調。 5. 由于運行環境的差異,在 iOS 設備上小程序內的 wxs 會比 javascript 代碼快 2 ~ 20 倍。在 android 設備上二者運行效率無差異。 以下是一些使用 WXS 的簡單示例: ### 頁面渲染 ``` <!--wxml--> <wxs module="m1"> var msg = "hello world"; module.exports.message = msg; </wxs> <view> {{m1.message}} </view> ``` 頁面輸出: ``` hello world ``` ### 數據處理 ``` // page.js Page({ data: { array: [1, 2, 3, 4, 5, 1, 2, 3, 4] } }) ``` ``` <!--wxml--> <!-- 下面的 getMax 函數,接受一個數組,且返回數組中最大的元素的值 --> <wxs module="m1"> var getMax = function(array) { var max = undefined; for (var i = 0; i < array.length; ++i) { max = max === undefined ? array[i] : (max >= array[i] ? max : array[i]); } return max; } module.exports.getMax = getMax; </wxs> <!-- 調用 wxs 里面的 getMax 函數,參數為 page.js 里面的 array --> <view> {{m1.getMax(array)}} </view> ``` 頁面輸出: ``` 5 ``` # WXS 模塊 WXS 代碼可以編寫在 wxml 文件中的?`<wxs>`?標簽內,或以?`.wxs`?為后綴名的文件內。 ## 模塊 每一個?`.wxs`?文件和?`<wxs>`?標簽都是一個單獨的模塊。 每個模塊都有自己獨立的作用域。即在一個模塊里面定義的變量與函數,默認為私有的,對其他模塊不可見。 一個模塊要想對外暴露其內部的私有變量與函數,只能通過?`module.exports`?實現。 ## .wxs 文件 在微信開發者工具里面,右鍵可以直接創建?`.wxs`?文件,在其中直接編寫 WXS 腳本。 示例代碼: ``` // /pages/comm.wxs var foo = "'hello world' from comm.wxs"; var bar = function(d) { return d; } module.exports = { foo: foo, bar: bar }; ``` 上述例子在?`/pages/comm.wxs`?的文件里面編寫了 WXS 代碼。該?`.wxs`?文件可以被其他的?`.wxs`?文件 或 WXML 中的?`<wxs>`?標簽引用。 ### module 對象 每個?`wxs`?模塊均有一個內置的?`module`?對象。 #### 屬性 * `exports`: 通過該屬性,可以對外共享本模塊的私有變量與函數。 示例代碼: [在開發者工具中預覽效果](https://developers.weixin.qq.com/s/KYgu1Km36pZP "在開發者工具中預覽效果") ``` // /pages/tools.wxs var foo = "'hello world' from tools.wxs"; var bar = function (d) { return d; } module.exports = { FOO: foo, bar: bar, }; module.exports.msg = "some msg"; ``` ``` <!-- page/index/index.wxml --> <wxs src="./../tools.wxs" module="tools" /> <view> {{tools.msg}} </view> <view> {{tools.bar(tools.FOO)}} </view> ``` 頁面輸出: ``` some msg 'hello world' from tools.wxs ``` ### require函數 在`.wxs`模塊中引用其他?`wxs`?文件模塊,可以使用?`require`?函數。 引用的時候,要注意如下幾點: * 只能引用?`.wxs`?文件模塊,且必須使用相對路徑。 * `wxs`?模塊均為單例,`wxs`?模塊在第一次被引用時,會自動初始化為單例對象。多個頁面,多個地方,多次引用,使用的都是同一個?`wxs`?模塊對象。 * 如果一個?`wxs`?模塊在定義之后,一直沒有被引用,則該模塊不會被解析與運行。 示例代碼: [在開發者工具中預覽效果](https://developers.weixin.qq.com/s/E4g94Kme6rZ6 "在開發者工具中預覽效果") ``` // /pages/tools.wxs var foo = "'hello world' from tools.wxs"; var bar = function (d) { return d; } module.exports = { FOO: foo, bar: bar, }; module.exports.msg = "some msg"; ``` ``` // /pages/logic.wxs var tools = require("./tools.wxs"); console.log(tools.FOO); console.log(tools.bar("logic.wxs")); console.log(tools.msg); ``` ``` <!-- /page/index/index.wxml --> <wxs src="./../logic.wxs" module="logic" /> ``` 控制臺輸出: ``` 'hello world' from tools.wxs logic.wxs some msg ``` ## `<wxs>`?標簽 | 屬性名 | 類型 | 默認值 | 說明 | | --- | --- | --- | --- | | module | String | | 當前?`<wxs>`?標簽的模塊名。必填字段。 | | src | String | | 引用 .wxs 文件的相對路徑。僅當本標簽為單閉合標簽或標簽的內容為空時有效。 | ### module 屬性 module 屬性是當前?`<wxs>`?標簽的模塊名。在單個 wxml 文件內,建議其值唯一。有重復模塊名則按照先后順序覆蓋(后者覆蓋前者)。不同文件之間的 wxs 模塊名不會相互覆蓋。 module 屬性值的命名必須符合下面兩個規則: * 首字符必須是:字母(a-zA-Z),下劃線(_) * 剩余字符可以是:字母(a-zA-Z),下劃線(_), 數字(0-9) 示例代碼: [在開發者工具中預覽效果](https://developers.weixin.qq.com/s/IzgmKKmn6tZ6 "在開發者工具中預覽效果") ``` <!--wxml--> <wxs module="foo"> var some_msg = "hello world"; module.exports = { msg : some_msg, } </wxs> <view> {{foo.msg}} </view> ``` 頁面輸出: ``` hello world ``` 上面例子聲明了一個名字為?`foo`?的模塊,將?`some_msg`?變量暴露出來,供當前頁面使用。 ### src 屬性 src 屬性可以用來引用其他的?`wxs`?文件模塊。 引用的時候,要注意如下幾點: * 只能引用?`.wxs`?文件模塊,且必須使用相對路徑。 * `wxs`?模塊均為單例,`wxs`?模塊在第一次被引用時,會自動初始化為單例對象。多個頁面,多個地方,多次引用,使用的都是同一個?`wxs`?模塊對象。 * 如果一個?`wxs`?模塊在定義之后,一直沒有被引用,則該模塊不會被解析與運行。 示例代碼: [在開發者工具中預覽效果](https://developers.weixin.qq.com/s/C7gYFKmh6vZI "在開發者工具中預覽效果") ``` // /pages/index/index.js Page({ data: { msg: "'hello wrold' from js", } }) ``` ``` <!-- /pages/index/index.wxml --> <wxs src="./../comm.wxs" module="some_comms"></wxs> <!-- 也可以直接使用單標簽閉合的寫法 <wxs src="./../comm.wxs" module="some_comms" /> --> <!-- 調用 some_comms 模塊里面的 bar 函數,且參數為 some_comms 模塊里面的 foo --> <view> {{some_comms.bar(some_comms.foo)}} </view> <!-- 調用 some_comms 模塊里面的 bar 函數,且參數為 page/index/index.js 里面的 msg --> <view> {{some_comms.bar(msg)}} </view> ``` 頁面輸出: ``` 'hello world' from comm.wxs 'hello wrold' from js ``` 上述例子在文件?`/page/index/index.wxml`?中通過?`<wxs>`?標簽引用了?`/page/comm.wxs`?模塊。 ### 注意 * `<wxs>`?模塊只能在定義模塊的 WXML 文件中被訪問到。使用?`<include>`?或?`<import>`?時,`<wxs>`?模塊不會被引入到對應的 WXML 文件中。 * `<template>`?標簽中,只能使用定義該?`<template>`?的 WXML 文件中定義的?`<wxs>`?模塊。 # 變量 ## 概念 * WXS 中的變量均為值的引用。 * 沒有聲明的變量直接賦值使用,會被定義為全局變量。 * 如果只聲明變量而不賦值,則默認值為?`undefined`。 * var表現與javascript一致,會有變量提升。 ``` var foo = 1; var bar = "hello world"; var i; // i === undefined ``` 上面代碼,分別聲明了?`foo`、?`bar`、?`i`?三個變量。然后,`foo`?賦值為數值?`1`?,`bar`?賦值為字符串?`"hello world"`。 ## 變量名 變量命名必須符合下面兩個規則: * 首字符必須是:字母(a-zA-Z),下劃線(_) * 剩余字符可以是:字母(a-zA-Z),下劃線(_), 數字(0-9) ## 保留標識符 以下標識符不能作為變量名: ``` delete void typeof null undefined NaN Infinity var if else true false require this function arguments return for while do break continue switch case default ``` # 注釋 WXS 主要有 3 種注釋的方法。 示例代碼: ``` <!-- wxml --> <wxs module="sample"> // 方法一:單行注釋 /* 方法二:多行注釋 */ /* 方法三:結尾注釋。即從 /* 開始往后的所有 WXS 代碼均被注釋 var a = 1; var b = 2; var c = "fake"; </wxs> ``` 上述例子中,所有 WXS 代碼均被注釋掉了。 > 方法三 和 方法二 的唯一區別是,沒有?`*/`?結束符。 > # 運算符 ## 基本運算符 示例代碼: ``` var a = 10, b = 20; // 加法運算 console.log(30 === a + b); // 減法運算 console.log(-10 === a - b); // 乘法運算 console.log(200 === a * b); // 除法運算 console.log(0.5 === a / b); // 取余運算 console.log(10 === a % b); ``` * 加法運算(`+`)也可以用作字符串的拼接。 ``` var a = '.w' , b = 'xs'; // 字符串拼接 console.log('.wxs' === a + b); ``` ## 一元運算符 示例代碼: ``` var a = 10, b = 20; // 自增運算 console.log(10 === a++); console.log(12 === ++a); // 自減運算 console.log(12 === a--); console.log(10 === --a); // 正值運算 console.log(10 === +a); // 負值運算 console.log(0-10 === -a); // 否運算 console.log(-11 === ~a); // 取反運算 console.log(false === !a); // delete 運算 console.log(true === delete a.fake); // void 運算 console.log(undefined === void a); // typeof 運算 console.log("number" === typeof a); ``` ## 位運算符 示例代碼: ``` var a = 10, b = 20; // 左移運算 console.log(80 === (a << 3)); // 無符號右移運算 console.log(2 === (a >> 2)); // 帶符號右移運算 console.log(2 === (a >>> 2)); // 與運算 console.log(2 === (a & 3)); // 異或運算 console.log(9 === (a ^ 3)); // 或運算 console.log(11 === (a | 3)); ``` ## 比較運算符 示例代碼: ``` var a = 10, b = 20; // 小于 console.log(true === (a < b)); // 大于 console.log(false === (a > b)); // 小于等于 console.log(true === (a <= b)); // 大于等于 console.log(false === (a >= b)); ``` ## 等值運算符 示例代碼: ``` var a = 10, b = 20; // 等號 console.log(false === (a == b)); // 非等號 console.log(true === (a != b)); // 全等號 console.log(false === (a === b)); // 非全等號 console.log(true === (a !== b)); ``` ## 賦值運算符 示例代碼: ``` var a = 10; a = 10; a *= 10; console.log(100 === a); a = 10; a /= 5; console.log(2 === a); a = 10; a %= 7; console.log(3 === a); a = 10; a += 5; console.log(15 === a); a = 10; a -= 11; console.log(-1 === a); a = 10; a <<= 10; console.log(10240 === a); a = 10; a >>= 2; console.log(2 === a); a = 10; a >>>= 2; console.log(2 === a); a = 10; a &= 3; console.log(2 === a); a = 10; a ^= 3; console.log(9 === a); a = 10; a |= 3; console.log(11 === a); ``` ## 二元邏輯運算符 示例代碼: ``` var a = 10, b = 20; // 邏輯與 console.log(20 === (a && b)); // 邏輯或 console.log(10 === (a || b)); ``` ## 其他運算符 示例代碼: ``` var a = 10, b = 20; //條件運算符 console.log(20 === (a >= 10 ? a + 10 : b + 10)); //逗號運算符 console.log(20 === (a, b)); ``` ## 運算符優先級 | 優先級 | 運算符 | 說明 | 結合性 | | --- | --- | --- | --- | | 20 | `(`?...?`)` | 括號 | n/a | | 19 | ...?`.`?... | 成員訪問 | 從左到右 | | | ...?`[`?...?`]` | 成員訪問 | 從左到右 | | | ...?`(`?...?`)` | 函數調用 | 從左到右 | | 17 | ...?`++` | 后置遞增 | n/a | | | ...?`--` | 后置遞減 | n/a | | 16 | `!`?... | 邏輯非 | 從右到左 | | | `~`?... | 按位非 | 從右到左 | | | `+`?... | 一元加法 | 從右到左 | | | `-`?... | 一元減法 | 從右到左 | | | `++`?... | 前置遞增 | 從右到左 | | | `--`?... | 前置遞減 | 從右到左 | | | `typeof`?... | typeof | 從右到左 | | | `void`?... | void | 從右到左 | | | `delete`?... | delete | 從右到左 | | 14 | ...?`*`?... | 乘法 | 從左到右 | | | ...?`/`?... | 除法 | 從左到右 | | | ...?`%`?... | 取模 | 從左到右 | | 13 | ...?`+`?... | 加法 | 從左到右 | | | ...?`-`?... | 減法 | 從左到右 | | 12 | ...?`<<`?... | 按位左移 | 從左到右 | | | ...?`>>`?... | 按位右移 | 從左到右 | | | ...?`>>>`?... | 無符號右移 | 從左到右 | | 11 | ...?`<`?... | 小于 | 從左到右 | | | ...?`<=`?... | 小于等于 | 從左到右 | | | ...?`>`?... | 大于 | 從左到右 | | | ...?`>=`?... | 大于等于 | 從左到右 | | 10 | ...?`==`?... | 等號 | 從左到右 | | | ...?`!=`?... | 非等號 | 從左到右 | | | ...?`===`?... | 全等號 | 從左到右 | | | ...?`!==`?... | 非全等號 | 從左到右 | | 9 | ...?`&`?... | 按位與 | 從左到右 | | 8 | ...?`^`?... | 按位異或 | 從左到右 | | 7 | ...?`|`?... | 按位或 | 從左到右 | | 6 | ...?`&&`?... | 邏輯與 | 從左到右 | | 5 | ...?`||`?... | 邏輯或 | 從左到右 | | 4 | ...?`?`?...?`:`?... | 條件運算符 | 從右到左 | | 3 | ...?`=`?... | 賦值 | 從右到左 | | | ...?`+=`?... | 賦值 | 從右到左 | | | ...?`-=`?... | 賦值 | 從右到左 | | | ...?`*=`?... | 賦值 | 從右到左 | | | ...?`/=`?... | 賦值 | 從右到左 | | | ...?`%=`?... | 賦值 | 從右到左 | | | ...?`<<=`?... | 賦值 | 從右到左 | | | ...?`>>=`?... | 賦值 | 從右到左 | | | ...?`>>>=`?... | 賦值 | 從右到左 | | | ...?`&=`?... | 賦值 | 從右到左 | | | ...?`^=`?... | 賦值 | 從右到左 | | | ...?`|=`?... | 賦值 | 從右到左 | | 0 | ...?`,`?... | 逗號 | 從左到右 |# 語句 ## if 語句 在 WXS 中,可以使用以下格式的?`if`?語句 : * `if (expression) statement`?: 當?`expression`?為 truthy 時,執行?`statement`。 * `if (expression) statement1 else statement2`?: 當?`expression`?為 truthy 時,執行?`statement1`。 否則,執行?`statement2` * `if ... else if ... else statementN`?通過該句型,可以在?`statement1`?~?`statementN`?之間選其中一個執行。 示例語法: ``` // if ... if (表達式) 語句; if (表達式) 語句; if (表達式) { 代碼塊; } // if ... else if (表達式) 語句; else 語句; if (表達式) 語句; else 語句; if (表達式) { 代碼塊; } else { 代碼塊; } // if ... else if ... else ... if (表達式) { 代碼塊; } else if (表達式) { 代碼塊; } else if (表達式) { 代碼塊; } else { 代碼塊; } ``` ## switch 語句 示例語法: ``` switch (表達式) { case 變量: 語句; case 數字: 語句; break; case 字符串: 語句; default: 語句; } ``` * `default`?分支可以省略不寫。 * `case`?關鍵詞后面只能使用:`變量`,`數字`,`字符串`。 示例代碼: ``` var exp = 10; switch ( exp ) { case "10": console.log("string 10"); break; case 10: console.log("number 10"); break; case exp: console.log("var exp"); break; default: console.log("default"); } ``` 輸出: ``` number 10 ``` ## for 語句 示例語法: ``` for (語句; 語句; 語句) 語句; for (語句; 語句; 語句) { 代碼塊; } ``` * 支持使用?`break`,`continue`?關鍵詞。 示例代碼: ``` for (var i = 0; i < 3; ++i) { console.log(i); if( i >= 1) break; } ``` 輸出: ``` 0 1 ``` ## while 語句 示例語法: ``` while (表達式) 語句; while (表達式){ 代碼塊; } do { 代碼塊; } while (表達式) ``` * 當`表達式`為 true 時,循環執行`語句`或`代碼塊`。 * 支持使用?`break`,`continue`?關鍵詞。 # 數據類型 WXS 語言目前共有以下幾種數據類型: * `number`?: 數值 * `string`?:字符串 * `boolean`:布爾值 * `object`:對象 * `function`:函數 * `array`?: 數組 * `date`:日期 * `regexp`:正則 ## number ### 語法 number 包括兩種數值:整數,小數。 ``` var a = 10; var PI = 3.141592653589793; ``` ### 屬性 * `constructor`:返回字符串?`"Number"`。 ### 方法 * `toString` * `toLocaleString` * `valueOf` * `toFixed` * `toExponential` * `toPrecision` > 以上方法的具體使用請參考?`ES5`?標準。 ## string ### 語法 string 有兩種寫法: ``` 'hello world'; "hello world"; ``` ### 屬性 * `constructor`:返回字符串?`"String"`。 * `length` > 除constructor外屬性的具體含義請參考?`ES5`?標準。 ### 方法 * `toString` * `valueOf` * `charAt` * `charCodeAt` * `concat` * `indexOf` * `lastIndexOf` * `localeCompare` * `match` * `replace` * `search` * `slice` * `split` * `substring` * `toLowerCase` * `toLocaleLowerCase` * `toUpperCase` * `toLocaleUpperCase` * `trim` > 以上方法的具體使用請參考?`ES5`?標準。 ## boolean ### 語法 布爾值只有兩個特定的值:`true`?和?`false`。 ### 屬性 * `constructor`:返回字符串?`"Boolean"`。 ### 方法 * `toString` * `valueOf` > 以上方法的具體使用請參考?`ES5`?標準。 ## object ### 語法 object 是一種無序的鍵值對。使用方法如下所示: ``` var o = {} //生成一個新的空對象 //生成一個新的非空對象 o = { 'string' : 1, //object 的 key 可以是字符串 const_var : 2, //object 的 key 也可以是符合變量定義規則的標識符 func : {}, //object 的 value 可以是任何類型 }; //對象屬性的讀操作 console.log(1 === o['string']); console.log(2 === o.const_var); //對象屬性的寫操作 o['string']++; o['string'] += 10; o.const_var++; o.const_var += 10; //對象屬性的讀操作 console.log(12 === o['string']); console.log(13 === o.const_var); ``` ### 屬性 * `constructor`:返回字符串?`"Object"`。 ``` console.log("Object" === {k:"1",v:"2"}.constructor) ``` ### 方法 * `toString`:返回字符串?`"[object Object]"`。 ## function ### 語法 function 支持以下的定義方式: ``` //方法 1 function a (x) { return x; } //方法 2 var b = function (x) { return x; } ``` function 同時也支持以下的語法(匿名函數,閉包等): ``` var a = function (x) { return function () { return x;} } var b = a(100); console.log( 100 === b() ); ``` ### arguments function 里面可以使用?`arguments`?關鍵詞。該關鍵詞目前只支持以下的屬性: * `length`: 傳遞給函數的參數個數。 * `[index]`: 通過?`index`?下標可以遍歷傳遞給函數的每個參數。 示例代碼: ``` var a = function(){ console.log(3 === arguments.length); console.log(100 === arguments[0]); console.log(200 === arguments[1]); console.log(300 === arguments[2]); }; a(100,200,300); ``` ### 屬性 * `constructor`:返回字符串?`"Function"`。 * `length`:返回函數的形參個數。 ### 方法 * `toString`:返回字符串?`"[function Function]"`。 示例代碼: ``` var func = function (a,b,c) { } console.log("Function" === func.constructor); console.log(3 === func.length); console.log("[function Function]" === func.toString()); ``` ## array ### 語法 array 支持以下的定義方式: ``` var a = []; //生成一個新的空數組 a = [1,"2",{},function(){}]; //生成一個新的非空數組,數組元素可以是任何類型 ``` ### 屬性 * `constructor`:返回字符串?`"Array"`。 * `length` > 除constructor外屬性的具體含義請參考?`ES5`?標準。 ### 方法 * `toString` * `concat` * `join` * `pop` * `push` * `reverse` * `shift` * `slice` * `sort` * `splice` * `unshift` * `indexOf` * `lastIndexOf` * `every` * `some` * `forEach` * `map` * `filter` * `reduce` * `reduceRight` > 以上方法的具體使用請參考?`ES5`?標準。 ## date ### 語法 生成 date 對象需要使用?`getDate`函數, 返回一個當前時間的對象。 ``` getDate() getDate(milliseconds) getDate(datestring) getDate(year, month[, date[, hours[, minutes[, seconds[, milliseconds]]]]]) ``` * 參數 * `milliseconds`: 從1970年1月1日00:00:00 UTC開始計算的毫秒數 * `datestring`: 日期字符串,其格式為:"month day, year hours:minutes:seconds" 示例代碼: ``` var date = getDate(); //返回當前時間對象 date = getDate(1500000000000); // Fri Jul 14 2017 10:40:00 GMT+0800 (中國標準時間) date = getDate('2017-7-14'); // Fri Jul 14 2017 00:00:00 GMT+0800 (中國標準時間) date = getDate(2017, 6, 14, 10, 40, 0, 0); // Fri Jul 14 2017 10:40:00 GMT+0800 (中國標準時間) ``` ### 屬性 * `constructor`:返回字符串 “Date”。 ### 方法 * `toString` * `toDateString` * `toTimeString` * `toLocaleString` * `toLocaleDateString` * `toLocaleTimeString` * `valueOf` * `getTime` * `getFullYear` * `getUTCFullYear` * `getMonth` * `getUTCMonth` * `getDate` * `getUTCDate` * `getDay` * `getUTCDay` * `getHours` * `getUTCHours` * `getMinutes` * `getUTCMinutes` * `getSeconds` * `getUTCSeconds` * `getMilliseconds` * `getUTCMilliseconds` * `getTimezoneOffset` * `setTime` * `setMilliseconds` * `setUTCMilliseconds` * `setSeconds` * `setUTCSeconds` * `setMinutes` * `setUTCMinutes` * `setHours` * `setUTCHours` * `setDate` * `setUTCDate` * `setMonth` * `setUTCMonth` * `setFullYear` * `setUTCFullYear` * `toUTCString` * `toISOString` * `toJSON` > 以上方法的具體使用請參考?`ES5`?標準。 ## regexp ### 語法 生成 regexp 對象需要使用?`getRegExp`函數。 ``` getRegExp(pattern[, flags]) ``` * 參數: * `pattern`: 正則表達式的內容。 * `flags`:修飾符。該字段只能包含以下字符: * `g`: global * `i`: ignoreCase * `m`: multiline。 示例代碼: ``` var a = getRegExp("x", "img"); console.log("x" === a.source); console.log(true === a.global); console.log(true === a.ignoreCase); console.log(true === a.multiline); ``` ### 屬性 * `constructor`:返回字符串?`"RegExp"`。 * `source` * `global` * `ignoreCase` * `multiline` * `lastIndex` > 除constructor外屬性的具體含義請參考?`ES5`?標準。 ### 方法 * `exec` * `test` * `toString` > 以上方法的具體使用請參考?`ES5`?標準。 ## 數據類型判斷 ### `constructor`?屬性 數據類型的判斷可以使用?`constructor`?屬性。 示例代碼: ``` var number = 10; console.log( "Number" === number.constructor ); var string = "str"; console.log( "String" === string.constructor ); var boolean = true; console.log( "Boolean" === boolean.constructor ); var object = {}; console.log( "Object" === object.constructor ); var func = function(){}; console.log( "Function" === func.constructor ); var array = []; console.log( "Array" === array.constructor ); var date = getDate(); console.log( "Date" === date.constructor ); var regexp = getRegExp(); console.log( "RegExp" === regexp.constructor ); ``` ### `typeof` 使用?`typeof`?也可以區分部分數據類型。 示例代碼: ``` var number = 10; var boolean = true; var object = {}; var func = function(){}; var array = []; var date = getDate(); var regexp = getRegExp(); console.log( 'number' === typeof number ); console.log( 'boolean' === typeof boolean ); console.log( 'object' === typeof object ); console.log( 'function' === typeof func ); console.log( 'object' === typeof array ); console.log( 'object' === typeof date ); console.log( 'object' === typeof regexp ); console.log( 'undefined' === typeof undefined ); console.log( 'object' === typeof null ); ``` # 基礎類庫 ## console `console.log`?方法用于在 console 窗口輸出信息。它可以接受多個參數,將它們的結果連接起來輸出。 ## Math ### 屬性 * `E` * `LN10` * `LN2` * `LOG2E` * `LOG10E` * `PI` * `SQRT1_2` * `SQRT2` > 以上屬性的具體使用請參考?`ES5`?標準。 ### 方法 * `abs` * `acos` * `asin` * `atan` * `atan2` * `ceil` * `cos` * `exp` * `floor` * `log` * `max` * `min` * `pow` * `random` * `round` * `sin` * `sqrt` * `tan` > 以上方法的具體使用請參考?`ES5`?標準。 ## JSON ### 方法 * `stringify(object)`: 將?`object`?對象轉換為?`JSON`?字符串,并返回該字符串。 * `parse(string)`: 將?`JSON`?字符串轉化成對象,并返回該對象。 示例代碼: ``` console.log(undefined === JSON.stringify()); console.log(undefined === JSON.stringify(undefined)); console.log("null"===JSON.stringify(null)); console.log("111"===JSON.stringify(111)); console.log('"111"'===JSON.stringify("111")); console.log("true"===JSON.stringify(true)); console.log(undefined===JSON.stringify(function(){})); console.log(undefined===JSON.parse(JSON.stringify())); console.log(undefined===JSON.parse(JSON.stringify(undefined))); console.log(null===JSON.parse(JSON.stringify(null))); console.log(111===JSON.parse(JSON.stringify(111))); console.log("111"===JSON.parse(JSON.stringify("111"))); console.log(true===JSON.parse(JSON.stringify(true))); console.log(undefined===JSON.parse(JSON.stringify(function(){}))); ``` ## Number ### 屬性 * `MAX_VALUE` * `MIN_VALUE` * `NEGATIVE_INFINITY` * `POSITIVE_INFINITY` > 以上屬性的具體使用請參考?`ES5`?標準。 ## Date ### 屬性 * `parse` * `UTC` * `now` > 以上屬性的具體使用請參考?`ES5`?標準。 ## Global ### 屬性 * `NaN` * `Infinity` * `undefined` > 以上屬性的具體使用請參考?`ES5`?標準。 ### 方法 * `parseInt` * `parseFloat` * `isNaN` * `isFinite` * `decodeURI` * `decodeURIComponent` * `encodeURI` * `encodeURIComponent` > 以上方法的具體使用請參考?`ES5`?標準。 > # 獲取界面上的節點信息 ## WXML節點信息 [節點信息查詢 API](https://developers.weixin.qq.com/miniprogram/dev/api/wxml/wx.createSelectorQuery.html)?可以用于獲取節點屬性、樣式、在界面上的位置等信息。 最常見的用法是使用這個接口來查詢某個節點的當前位置,以及界面的滾動位置。 示例代碼: ``` const query = wx.createSelectorQuery() query.select('#the-id').boundingClientRect(function(res){ res.top // #the-id 節點的上邊界坐標(相對于顯示區域) }) query.selectViewport().scrollOffset(function(res){ res.scrollTop // 顯示區域的豎直滾動位置 }) query.exec() ``` 上述示例中,?`#the-id`?是一個節點選擇器,與 CSS 的選擇器相近但略有區別,請參見?[SelectorQuery.select](https://developers.weixin.qq.com/miniprogram/dev/api/wxml/SelectorQuery.select.html)?的相關說明。 在自定義組件中,推薦使用?`this.createSelectorQuery`?來代替?`wx.createSelectorQuery`?,這樣會將選擇器選取范圍定在這個自定義組件內。 ## WXML節點布局相交狀態 [節點布局相交狀態 API](https://developers.weixin.qq.com/miniprogram/dev/api/wxml/wx.createIntersectionObserver.html)?可用于監聽兩個或多個組件節點在布局位置上的相交狀態。這一組API常常可以用于推斷某些節點是否可以被用戶看見、有多大比例可以被用戶看見。 這一組API涉及的主要概念如下。 * 參照節點:監聽的參照節點,取它的布局區域作為參照區域。如果有多個參照節點,則會取它們布局區域的?交集?作為參照區域。頁面顯示區域也可作為參照區域之一。 * 目標節點:監聽的目標,默認只能是一個節點(使用?`selectAll`?選項時,可以同時監聽多個節點)。 * 相交區域:目標節點的布局區域與參照區域的相交區域。 * 相交比例:相交區域占參照區域的比例。 * 閾值:相交比例如果達到閾值,則會觸發監聽器的回調函數。閾值可以有多個。 以下示例代碼可以在目標節點(用選擇器?`.target-class`?指定)每次進入或離開頁面顯示區域時,觸發回調函數。 示例代碼: ``` Page({ onLoad: function(){ wx.createIntersectionObserver().relativeToViewport().observe('.target-class', (res) => { res.id // 目標節點 id res.dataset // 目標節點 dataset res.intersectionRatio // 相交區域占目標節點的布局區域的比例 res.intersectionRect // 相交區域 res.intersectionRect.left // 相交區域的左邊界坐標 res.intersectionRect.top // 相交區域的上邊界坐標 res.intersectionRect.width // 相交區域的寬度 res.intersectionRect.height // 相交區域的高度 }) } }) ``` 以下示例代碼可以在目標節點(用選擇器?`.target-class`?指定)與參照節點(用選擇器?`.relative-class`?指定)在頁面顯示區域內相交或相離,且相交或相離程度達到目標節點布局區域的20%和50%時,觸發回調函數。 示例代碼: ``` Page({ onLoad: function(){ wx.createIntersectionObserver(this, { thresholds: [0.2, 0.5] }).relativeTo('.relative-class').relativeToViewport().observe('.target-class', (res) => { res.intersectionRatio // 相交區域占目標節點的布局區域的比例 res.intersectionRect // 相交區域 res.intersectionRect.left // 相交區域的左邊界坐標 res.intersectionRect.top // 相交區域的上邊界坐標 res.intersectionRect.width // 相交區域的寬度 res.intersectionRect.height // 相交區域的高度 }) } }) ``` 在自定義組件中,推薦使用?`this.createIntersectionObserver`?來代替?`wx.createIntersectionObserver`?,這樣會將選擇器選取范圍定在這個自定義組件內。 # 響應顯示區域變化 ## 顯示區域尺寸 顯示區域指小程序界面中可以自由布局展示的區域。在默認情況下,小程序顯示區域的尺寸自頁面初始化起就不會發生變化。但以下兩種方式都可以改變這一默認行為。 ### 在手機上啟用屏幕旋轉支持 從小程序基礎庫版本?[2.4.0](https://developers.weixin.qq.com/miniprogram/dev/framework/compatibility.html "基礎庫 2.4.0 開始支持,低版本需做兼容處理。")?開始,小程序在手機上支持屏幕旋轉。使小程序中的頁面支持屏幕旋轉的方法是:在?`app.json`?的?`window`?段中設置?`"pageOrientation": "auto"`?,或在頁面 json 文件中配置?`"pageOrientation": "auto"`?。 以下是在單個頁面 json 文件中啟用屏幕旋轉的示例。 代碼示例: ``` { "pageOrientation": "auto" } ``` 如果頁面添加了上述聲明,則在屏幕旋轉時,這個頁面將隨之旋轉,顯示區域尺寸也會隨著屏幕旋轉而變化。 ### 在 iPad 上啟用屏幕旋轉支持 從小程序基礎庫版本?[2.3.0](https://developers.weixin.qq.com/miniprogram/dev/framework/compatibility.html "基礎庫 2.3.0 開始支持,低版本需做兼容處理。")?開始,在 iPad 上運行的小程序可以支持屏幕旋轉。使小程序支持 iPad 屏幕旋轉的方法是:在?`app.json`?中添加?`"resizable": true`?。 代碼示例: ``` { "resizable": true } ``` 如果小程序添加了上述聲明,則在屏幕旋轉時,小程序將隨之旋轉,顯示區域尺寸也會隨著屏幕旋轉而變化。注意:在 iPad 上不能單獨配置某個頁面是否支持屏幕旋轉。 ## Media Query 有時,對于不同尺寸的顯示區域,頁面的布局會有所差異。此時可以使用 media query 來解決大多數問題。 代碼示例: ``` .my-class { width: 40px; } @media (min-width: 480px) { /* 僅在 480px 或更寬的屏幕上生效的樣式規則 */ .my-class { width: 200px; } } ``` ## 屏幕旋轉事件 有時,僅僅使用 media query 無法控制一些精細的布局變化。此時可以使用 js 作為輔助。 在 js 中讀取頁面的顯示區域尺寸,可以使用?[selectorQuery.selectViewport](https://developers.weixin.qq.com/miniprogram/dev/api/wxml/SelectorQuery.selectViewport.html)?。 頁面尺寸發生改變的事件,可以使用?`wx.onWindowResize`?頁面的?`onResize`?來監聽。對于自定義組件,可以使用 resize 生命周期來監聽。回調函數中將返回顯示區域的尺寸信息。 代碼示例: ``` wx.onWindowResize(function(res) { res.size.windowWidth // 新的顯示區域寬度 res.size.windowHeight // 新的顯示區域高度 }) ``` ``` Page({ onResize(res) { res.size.windowWidth // 新的顯示區域寬度 res.size.windowHeight // 新的顯示區域高度 } }) ``` ``` Component({ pageLifetimes: { resize(res) { res.size.windowWidth // 新的顯示區域寬度 res.size.windowHeight // 新的顯示區域高度 } } }) ``` Bug & tips: * Bug: Android 微信版本 6.7.3 中,?`live-pusher`?組件在屏幕旋轉時方向異常。 # 組件模板和樣式 類似于頁面,自定義組件擁有自己的?`wxml`?模板和?`wxss`?樣式。 ### 組件模板 組件模板的寫法與頁面模板相同。組件模板與組件數據結合后生成的節點樹,將被插入到組件的引用位置上。 在組件模板中可以提供一個?`<slot>`?節點,用于承載組件引用時提供的子節點。 代碼示例: [在開發者工具中預覽效果](https://developers.weixin.qq.com/s/1udXLnmi6KY2 "在開發者工具中預覽效果") ``` <!-- 組件模板 --> <view class="wrapper"> <view>這里是組件的內部節點</view> <slot></slot> </view> ``` ``` <!-- 引用組件的頁面模板 --> <view> <component-tag-name> <!-- 這部分內容將被放置在組件 <slot> 的位置上 --> <view>這里是插入到組件slot中的內容</view> </component-tag-name> </view> ``` 注意,在模板中引用到的自定義組件及其對應的節點名需要在?`json`?文件中顯式定義,否則會被當作一個無意義的節點。除此以外,節點名也可以被聲明為[抽象節點](https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/generics.html)。 ### 模板數據綁定 與普通的 WXML 模板類似,可以使用數據綁定,這樣就可以向子組件的屬性傳遞動態數據。 代碼示例: ``` <!-- 引用組件的頁面模板 --> <view> <component-tag-name prop-a="{{dataFieldA}}" prop-b="{{dataFieldB}}"> <!-- 這部分內容將被放置在組件 <slot> 的位置上 --> <view>這里是插入到組件slot中的內容</view> </component-tag-name> </view> ``` 在以上例子中,組件的屬性?`propA`?和?`propB`?將收到頁面傳遞的數據。頁面可以通過?`setData`?來改變綁定的數據字段。 注意:這樣的數據綁定只能傳遞 JSON 兼容數據。自基礎庫版本?[2.0.9](https://developers.weixin.qq.com/miniprogram/dev/framework/compatibility.html "基礎庫 2.0.9 開始支持,低版本需做兼容處理。")?開始,還可以在數據中包含函數(但這些函數不能在 WXML 中直接調用,只能傳遞給子組件)。 ### 組件wxml的slot 在組件的wxml中可以包含?`slot`?節點,用于承載組件使用者提供的wxml結構。 默認情況下,一個組件的wxml中只能有一個slot。需要使用多slot時,可以在組件js中聲明啟用。 ``` Component({ options: { multipleSlots: true // 在組件定義時的選項中啟用多slot支持 }, properties: { /* ... */ }, methods: { /* ... */ } }) ``` 此時,可以在這個組件的wxml中使用多個slot,以不同的?`name`?來區分。 ``` <!-- 組件模板 --> <view class="wrapper"> <slot name="before"></slot> <view>這里是組件的內部細節</view> <slot name="after"></slot> </view> ``` 使用時,用?`slot`?屬性來將節點插入到不同的slot上。 ``` <!-- 引用組件的頁面模板 --> <view> <component-tag-name> <!-- 這部分內容將被放置在組件 <slot name="before"> 的位置上 --> <view slot="before">這里是插入到組件slot name="before"中的內容</view> <!-- 這部分內容將被放置在組件 <slot name="after"> 的位置上 --> <view slot="after">這里是插入到組件slot name="after"中的內容</view> </component-tag-name> </view> ``` ### 組件樣式 組件對應?`wxss`?文件的樣式,只對組件wxml內的節點生效。編寫組件樣式時,需要注意以下幾點: * 組件和引用組件的頁面不能使用id選擇器(`#a`)、屬性選擇器(`[a]`)和標簽名選擇器,請改用class選擇器。 * 組件和引用組件的頁面中使用后代選擇器(`.a .b`)在一些極端情況下會有非預期的表現,如遇,請避免使用。 * 子元素選擇器(`.a>.b`)只能用于?`view`?組件與其子節點之間,用于其他組件可能導致非預期的情況。 * 繼承樣式,如?`font`?、?`color`?,會從組件外繼承到組件內。 * 除繼承樣式外,?`app.wxss`?中的樣式、組件所在頁面的的樣式對自定義組件無效。 ``` #a { } /* 在組件中不能使用 */ [a] { } /* 在組件中不能使用 */ button { } /* 在組件中不能使用 */ .a > .b { } /* 除非 .a 是 view 組件節點,否則不一定會生效 */ ``` 除此以外,組件可以指定它所在節點的默認樣式,使用?`:host`?選擇器(需要包含基礎庫?[1.7.2](https://developers.weixin.qq.com/miniprogram/dev/framework/compatibility.html "基礎庫 1.7.2 開始支持,低版本需做兼容處理。")?或更高版本的開發者工具支持)。 代碼示例: [在開發者工具中預覽效果](https://developers.weixin.qq.com/s/jAgvwKm16bZD "在開發者工具中預覽效果") ``` /* 組件 custom-component.wxss */ :host { color: yellow; } ``` ``` <!-- 頁面的 WXML --> <custom-component>這段文本是黃色的</custom-component> ``` ### 外部樣式類 有時,組件希望接受外部傳入的樣式類(類似于?`view`?組件的?`hover-class`?屬性)。此時可以在?`Component`?中用?`externalClasses`?定義段定義若干個外部樣式類。這個特性從小程序基礎庫版本?[1.9.90](https://developers.weixin.qq.com/miniprogram/dev/framework/compatibility.html "基礎庫 1.9.90 開始支持,低版本需做兼容處理。")?開始支持。 注意:在同一個節點上使用普通樣式類和外部樣式類時,兩個類的優先級是未定義的,因此最好避免這種情況。 代碼示例: ``` /* 組件 custom-component.js */ Component({ externalClasses: ['my-class'] }) ``` ``` <!-- 組件 custom-component.wxml --> <custom-component class="my-class">這段文本的顏色由組件外的 class 決定</custom-component> ``` 這樣,組件的使用者可以指定這個樣式類對應的 class ,就像使用普通屬性一樣。 代碼示例: [在開發者工具中預覽效果](https://developers.weixin.qq.com/s/rbgNNKmE6bZK "在開發者工具中預覽效果") ``` <!-- 頁面的 WXML --> <custom-component my-class="red-text" /> ``` ``` .red-text { color: red; } ``` ### 全局樣式類 使用外部樣式類可以讓組件使用指定的組件外樣式類,如果希望組件外樣式類能夠完全影響組件內部,可以將組件構造器中的`options.addGlobalClass`字段置為`true`。這個特性從小程序基礎庫版本?[2.2.3](https://developers.weixin.qq.com/miniprogram/dev/framework/compatibility.html "基礎庫 2.2.3 開始支持,低版本需做兼容處理。")?開始支持。 > 當開放了全局樣式類,存在外部樣式污染組件樣式的風險,請謹慎選擇。 代碼示例: [在開發者工具中預覽效果](https://developers.weixin.qq.com/s/yNPLQvm87b1F "在開發者工具中預覽效果") ``` /* 組件 custom-component.js */ Component({ options: { addGlobalClass: true, } }) ``` ``` <!-- 組件 custom-component.wxml --> <text class="red-text">這段文本的顏色由組件外的 class 決定</text> ``` ``` /* 組件外的樣式定義 */ .red-text { color: red; } ``` # Component構造器 ## 定義段與示例方法 Component構造器可用于定義組件,調用Component構造器時可以指定組件的屬性、數據、方法等。 | 定義段 | 類型 | 是否必填 | 描述 | 最低版本 | | --- | --- | --- | --- | --- | | properties | Object Map | 否 | 組件的對外屬性,是屬性名到屬性設置的映射表,屬性設置中可包含三個字段,?`type`?表示屬性類型、?`value`?表示屬性初始值、?`observer`?表示屬性值被更改時的響應函數 | | | data | Object | 否 | 組件的內部數據,和?`properties`?一同用于組件的模板渲染 | | | methods | Object | 否 | 組件的方法,包括事件響應函數和任意的自定義方法,關于事件響應函數的使用,參見?[組件事件](https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/events.html) | | | behaviors | String Array | 否 | 類似于mixins和traits的組件間代碼復用機制,參見?[behaviors](https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/behaviors.html) | | | created | Function | 否 | 組件生命周期函數,在組件實例進入頁面節點樹時執行,注意此時不能調用?`setData` | | | attached | Function | 否 | 組件生命周期函數,在組件實例進入頁面節點樹時執行 | | | ready | Function | 否 | 組件生命周期函數,在組件布局完成后執行,此時可以獲取節點信息(使用?[SelectorQuery](https://developers.weixin.qq.com/miniprogram/dev/api/wxml/SelectorQuery.html)?) | | | moved | Function | 否 | 組件生命周期函數,在組件實例被移動到節點樹另一個位置時執行 | | | detached | Function | 否 | 組件生命周期函數,在組件實例被從頁面節點樹移除時執行 | | | relations | Object | 否 | 組件間關系定義,參見?[組件間關系](https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/relations.html) | | | externalClasses | String Array | 否 | 組件接受的外部樣式類,參見?[外部樣式類](https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/wxml-wxss.html) | | | options | Object Map | 否 | 一些選項(文檔中介紹相關特性時會涉及具體的選項設置,這里暫不列舉) | | | lifetimes | Object | 否 | 組件生命周期聲明對象,組件的生命周期:`created`、`attached`、`ready`、`moved`、`detached`將收歸到`lifetimes`字段內進行聲明,原有聲明方式仍舊有效,如同時存在兩種聲明方式,則`lifetimes`字段內聲明方式優先級最高 | [2.2.3](https://developers.weixin.qq.com/miniprogram/dev/framework/compatibility.html "基礎庫 2.2.3 開始支持,低版本需做兼容處理。") | | pageLifetimes | Object | 否 | 組件所在頁面的生命周期聲明對象,支持頁面的?`show`?、?`hide`?、?`resize`?生命周期 | [2.2.3](https://developers.weixin.qq.com/miniprogram/dev/framework/compatibility.html "基礎庫 2.2.3 開始支持,低版本需做兼容處理。")?;?`resize`為?[2.4.0](https://developers.weixin.qq.com/miniprogram/dev/framework/compatibility.html "基礎庫 2.4.0 開始支持,低版本需做兼容處理。") | | definitionFilter | Function | 否 | 定義段過濾器,用于自定義組件擴展,參見?[自定義組件擴展](https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/extend.html) | [2.2.3](https://developers.weixin.qq.com/miniprogram/dev/framework/compatibility.html "基礎庫 2.2.3 開始支持,低版本需做兼容處理。") | 生成的組件實例可以在組件的方法、生命周期函數和屬性?`observer`?中通過?`this`?訪問。組件包含一些通用屬性和方法。 | 屬性名 | 類型 | 描述 | | --- | --- | --- | | is | String | 組件的文件路徑 | | id | String | 節點id | | dataset | String | 節點dataset | | data | Object | 組件數據,包括內部數據和屬性值 | | properties | Object | 組件數據,包括內部數據和屬性值(與?`data`?一致) | | 方法名 | 參數 | 描述 | | --- | --- | --- | | setData | Object?`newData` | 設置data并執行視圖層渲染 | | hasBehavior | Object?`behavior` | 檢查組件是否具有?`behavior`?(檢查時會遞歸檢查被直接或間接引入的所有behavior) | | triggerEvent | String?`name`, Object?`detail`, Object?`options` | 觸發事件,參見?[組件事件](https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/events.html) | | createSelectorQuery | | 創建一個?[SelectorQuery](https://developers.weixin.qq.com/miniprogram/dev/api/wxml/SelectorQuery.html)?對象,選擇器選取范圍為這個組件實例內 | | createIntersectionObserver | | 創建一個?[IntersectionObserver](https://developers.weixin.qq.com/miniprogram/dev/api/wxml/IntersectionObserver.html)?對象,選擇器選取范圍為這個組件實例內 | | selectComponent | String?`selector` | 使用選擇器選擇組件實例節點,返回匹配到的第一個組件實例對象(會被?`wx://component-export`?影響) | | selectAllComponents | String?`selector` | 使用選擇器選擇組件實例節點,返回匹配到的全部組件實例對象組成的數組 | | getRelationNodes | String?`relationKey` | 獲取這個關系所對應的所有關聯節點,參見?[組件間關系](https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/relations.html) | | groupSetData | Function?`callback` | 立刻執行?`callback`?,其中的多個?`setData`?之間不會觸發界面繪制(只有某些特殊場景中需要,如用于在不同組件同時 setData 時進行界面繪制同步) | 代碼示例: [在開發者工具中預覽效果](https://developers.weixin.qq.com/s/GqVTnvmq7g1m "在開發者工具中預覽效果") ``` Component({ behaviors: [], properties: { myProperty: { // 屬性名 type: String, // 類型(必填),目前接受的類型包括:String, Number, Boolean, Object, Array, null(表示任意類型) value: '', // 屬性初始值(可選),如果未指定則會根據類型選擇一個 observer: function(newVal, oldVal, changedPath) { // 屬性被改變時執行的函數(可選),也可以寫成在methods段中定義的方法名字符串, 如:'_propertyChange' // 通常 newVal 就是新設置的數據, oldVal 是舊數據 } }, myProperty2: String // 簡化的定義方式 }, data: {}, // 私有數據,可用于模板渲染 lifetimes: { // 生命周期函數,可以為函數,或一個在methods段中定義的方法名 attached: function () { }, moved: function () { }, detached: function () { }, }, // 生命周期函數,可以為函數,或一個在methods段中定義的方法名 attached: function () { }, // 此處attached的聲明會被lifetimes字段中的聲明覆蓋 ready: function() { }, pageLifetimes: { // 組件所在頁面的生命周期函數 show: function () { }, hide: function () { }, resize: function () { }, }, methods: { onMyButtonTap: function(){ this.setData({ // 更新屬性和數據的方法與更新頁面數據的方法類似 }) }, // 內部方法建議以下劃線開頭 _myPrivateMethod: function(){ // 這里將 data.A[0].B 設為 'myPrivateData' this.setData({ 'A[0].B': 'myPrivateData' }) }, _propertyChange: function(newVal, oldVal) { } } }) ``` 注意:在?`properties`?定義段中,屬性名采用駝峰寫法(`propertyName`);在?`wxml`?中,指定屬性值時則對應使用連字符寫法(`component-tag-name property-name="attr value"`),應用于數據綁定時采用駝峰寫法(`attr="{{propertyName}}"`)。 ## 使用 Component 構造器構造頁面 事實上,小程序的頁面也可以視為自定義組件。因而,頁面也可以使用?`Component`?構造器構造,擁有與普通組件一樣的定義段與實例方法。但此時要求對應 json 文件中包含?`usingComponents`?定義段。 此時,組件的屬性可以用于接收頁面的參數,如訪問頁面?`/pages/index/index?paramA=123&paramB=xyz`?,如果聲明有屬性?`paramA`?或?`paramB`?,則它們會被賦值為?`123`?或?`xyz`?。 頁面的生命周期方法(即?`on`?開頭的方法),應寫在?`methods`?定義段中。 代碼示例: ``` { "usingComponents": {} } ``` ``` Component({ properties: { paramA: Number, paramB: String, }, methods: { onLoad: function() { this.data.paramA // 頁面參數 paramA 的值 this.data.paramB // 頁面參數 paramB 的值 } } }) ``` #### Bug & Tips: * 使用?`this.data`?可以獲取內部數據和屬性值,但不要直接修改它們,應使用?`setData`?修改。 * 生命周期函數無法在組件方法中通過?`this`?訪問到。 * 屬性名應避免以 data 開頭,即不要命名成?`dataXyz`?這樣的形式,因為在 WXML 中,?`data-xyz=""`?會被作為節點 dataset 來處理,而不是組件屬性。 * 在一個組件的定義和使用時,組件的屬性名和 data 字段相互間都不能沖突(盡管它們位于不同的定義段中)。 * 從基礎庫?[2.0.9](https://developers.weixin.qq.com/miniprogram/dev/framework/compatibility.html "基礎庫 2.0.9 開始支持,低版本需做兼容處理。")?開始,對象類型的屬性和 data 字段中可以包含函數類型的子字段,即可以通過對象類型的屬性字段來傳遞函數。低于這一版本的基礎庫不支持這一特性。 * `bug`?: 對于 type 為 Object 或 Array 的屬性,如果通過該組件自身的 this.setData 來改變屬性值的一個子字段,則依舊會觸發屬性 observer ,且 observer 接收到的?`newVal`?是變化的那個子字段的值,?`oldVal`?為空,?`changedPath`?包含子字段的字段名相關信息。 # 組件間通信與事件 ## 組件間通信 組件間的基本通信方式有以下幾種。 * WXML 數據綁定:用于父組件向子組件的指定屬性設置數據,僅能設置 JSON 兼容數據(自基礎庫版本?[2.0.9](https://developers.weixin.qq.com/miniprogram/dev/framework/compatibility.html "基礎庫 2.0.9 開始支持,低版本需做兼容處理。")?開始,還可以在數據中包含函數)。具體在?[組件模板和樣式](https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/wxml-wxss.html)?章節中介紹。 * 事件:用于子組件向父組件傳遞數據,可以傳遞任意數據。 * 如果以上兩種方式不足以滿足需要,父組件還可以通過?`this.selectComponent`?方法獲取子組件實例對象,這樣就可以直接訪問組件的任意數據和方法。 ## 監聽事件 事件系統是組件間通信的主要方式之一。自定義組件可以觸發任意的事件,引用組件的頁面可以監聽這些事件。關于事件的基本概念和用法,參見?[事件](https://developers.weixin.qq.com/miniprogram/dev/framework/view/wxml/event.html)。 監聽自定義組件事件的方法與監聽基礎組件事件的方法完全一致: 代碼示例: ``` <!-- 當自定義組件觸發“myevent”事件時,調用“onMyEvent”方法 --> <component-tag-name bindmyevent="onMyEvent" /> <!-- 或者可以寫成 --> <component-tag-name bind:myevent="onMyEvent" /> ``` ``` Page({ onMyEvent: function(e){ e.detail // 自定義組件觸發事件時提供的detail對象 } }) ``` ## 觸發事件 自定義組件觸發事件時,需要使用?`triggerEvent`?方法,指定事件名、detail對象和事件選項: 代碼示例: [在開發者工具中預覽效果](https://developers.weixin.qq.com/s/DFfYSKmI6vZD "在開發者工具中預覽效果") ``` <!-- 在自定義組件中 --> <button bindtap="onTap">點擊這個按鈕將觸發“myevent”事件</button> ``` ``` Component({ properties: {} methods: { onTap: function(){ var myEventDetail = {} // detail對象,提供給事件監聽函數 var myEventOption = {} // 觸發事件的選項 this.triggerEvent('myevent', myEventDetail, myEventOption) } } }) ``` 觸發事件的選項包括: | 選項名 | 類型 | 是否必填 | 默認值 | 描述 | | --- | --- | --- | --- | --- | | bubbles | Boolean | 否 | false | 事件是否冒泡 | | composed | Boolean | 否 | false | 事件是否可以穿越組件邊界,為false時,事件將只能在引用組件的節點樹上觸發,不進入其他任何組件內部 | | capturePhase | Boolean | 否 | false | 事件是否擁有捕獲階段 | 關于冒泡和捕獲階段的概念,請閱讀?[事件](https://developers.weixin.qq.com/miniprogram/dev/framework/view/wxml/event.html)?章節中的相關說明。 代碼示例: [在開發者工具中預覽效果](https://developers.weixin.qq.com/s/UGfljKm66zZ1 "在開發者工具中預覽效果") ``` // 頁面 page.wxml <another-component bindcustomevent="pageEventListener1"> <my-component bindcustomevent="pageEventListener2"></my-component> </another-component> ``` ``` // 組件 another-component.wxml <view bindcustomevent="anotherEventListener"> <slot /> </view> ``` ``` // 組件 my-component.wxml <view bindcustomevent="myEventListener"> <slot /> </view> ``` ``` // 組件 my-component.js Component({ methods: { onTap: function(){ this.triggerEvent('customevent', {}) // 只會觸發 pageEventListener2 this.triggerEvent('customevent', {}, { bubbles: true }) // 會依次觸發 pageEventListener2 、 pageEventListener1 this.triggerEvent('customevent', {}, { bubbles: true, composed: true }) // 會依次觸發 pageEventListener2 、 anotherEventListener 、 pageEventListener1 } } }) ```
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看