百度智能小程序框架 視圖層

2018-07-09 14:46 更新

視圖層介紹


框架的視圖層由模板語法與 CSS 規(guī)范 編寫,由組件來進(jìn)行展示。

將邏輯層的數(shù)據(jù)渲染到視圖層,同時(shí)將視圖層的事件傳遞給邏輯層。

視圖層 SWAN 用來描述 XML 的結(jié)構(gòu)。CSS 用來描述樣式。

組件是視圖的基本單位,是獨(dú)立的數(shù)據(jù)、邏輯、視圖的封裝單元。

SWAN 模板語法


SWAN 是框架設(shè)計(jì)的一套標(biāo)簽語言,由組件、事件處理系統(tǒng)構(gòu)成的一套頁面結(jié)構(gòu)。下面一些簡單的例子來說明 SWAN 模板 的簡單用法。

數(shù)據(jù)綁定

<!-- data-demo.swan-->
<view>Hello, {{name}}</view>
// data-demo.js
Page({
    data: {
        name: 'SWAN'
    }
});

循環(huán)

<!-- for-demo.swan-->
<view>
    <view s-for="p,index in persons">
        {{index}}: {{p.name}}
    </view>
</view>
// for-demo.js
Page({
    data: {
        persons: [
            {name: 'Curry'},
            {name: 'Thompson'},
            {name: 'Durant'},
            {name: 'Green'},
            {name: 'Cousins'}
        ]
    }
});

條件

<!-- if-demo.swan-->
<view s-if="is4G">4G</view>
<view s-elif="isWifi">Wifi</view>
<view s-else>Other</view>
// if-demo.js
Page({
    data: {
        is4G: true,
        isWifi: false
    }
});

模板

<!-- template-demo.swan-->
<template name="tagCard">
    <view>
        <text>標(biāo)簽: {{tag}}</text>
        <text>昵稱: {{nickname}}</text>
    </view>
</template>

<template name="personCard">
    <view>
        <text>位置: {{pos}}</text>
        <text>姓名: {{name}}</text>
    </view>
</template>

<template name="teamCard">
    <view s-for="item, index in teams">
        <text>球隊(duì): {{index}} - {{item}}</text>
    </view>
</template>

<template name="ageCard">
    <view>
        <text>年齡: {{age}}</text>
    </view>
</template>

<template is="personCard" data="{{person}}" />
<!-- 對象字面量 -->
<template is="teamCard" data="{{ {teams} }}" />
<template is="tagCard" data="{{ {tag, nickname: 'king'} }}" />
<template is="ageCard" data="{{ {...person} }}" />
// template-demo.js
Page({
    data: {
        person: {name: 'Lebron James', pos: 'SF', age: 33},
        teams: ['Cleveland Cavaliers', 'Miami Heat', 'Los Angeles Lakers'],
        tag: 'basketball'
    }
});

事件處理

<!-- event-demo.swan-->
<view class="view-more" bindtap="loadMore">
    點(diǎn)擊加載更多
</view>
// event-demo.js
Page({
    data: {
        firstScreen: true
    },
    loadMore: function () {
        console.log('加載更多被點(diǎn)擊');
    }
});

具體更詳細(xì)的用法請看下面的章節(jié):數(shù)據(jù)綁定、循環(huán)、條件、模板、事件處理、引用

數(shù)據(jù)綁定


SWAN 模板中的動(dòng)態(tài)數(shù)據(jù),都從邏輯層 Page 中 data 對象來。

基礎(chǔ)數(shù)據(jù)綁定

數(shù)據(jù)綁定和許多模板引擎一樣,數(shù)據(jù)包裹在雙大括號里面。

內(nèi)容

<!-- data-demo.swan -->
<view>
    Hello My {{ name }}
</view>
// data-demo.js
Page({
    data: {
        name: 'SWAN'
    }
});

屬性綁定

<!-- attr-demo.swan -->
<view class="c-{{className}}">屬性綁定</view>
// attr-demo.js
Page({
    data: {
        className: 'blue'
    }
});

控制屬性(不需要被雙大括號包裹)

<!-- condition-demo.swan -->
<view s-if="flag"></view>
// condition-demo.js
Page({
    data: {
        flag: true
    }
});

運(yùn)算

SWAN 模板 提供了豐富的表達(dá)式類型支持,讓使用者在編寫視圖模板時(shí)更方便。

  • 數(shù)據(jù)訪問(普通變量、屬性訪問)
  • 一元否定
  • 二元運(yùn)算
  • 二元關(guān)系
  • 三元條件
  • 括號
  • 字符串
  • 數(shù)值
  • 布爾

通過下面例子列舉支持的表達(dá)式類型。

<!-- operation-demo.swan -->

<!-- 普通變量 -->
<text>{{name}}</text>

<!-- 屬性訪問 -->
<text>{{person.name}}</text>
<text>{{persons[1]}}</text>

<!-- 一元否定 -->
<text>{{!isOK}}</text>
<text>{{!!isOK}}</text>

<!-- 二元運(yùn)算 -->
<text>{{num1 + num2}}</text>
<text>{{num1 - num2}}</text>
<text>{{num1 * num2}}</text>
<text>{{num1 / num2}}</text>
<text>{{num1 + num2 * num3}}</text>

<!-- 二元關(guān)系 -->
<text>{{num1 > num2}}</text>
<text>{{num1 !== num2}}</text>

<!-- 三元條件 -->
<text>{{num1 > num2 ? num1 : num2}}</text>

<!-- 括號 -->
<text>{{a * (b + c)}}</text>

<!-- 數(shù)值 -->
<text>{{num1 + 200}}</text>

<!-- 字符串 + 三元條件 -->
<text>{{item ? ',' + item : ''}}</text>

<!-- 三元運(yùn)算 -->
<checkbox checked="{{flag ? true : false}}"></checkbox>

<!-- 數(shù)組字面量 -->
<text>{{ ['john', 'tony', 'lbj'] }}</text>

對象字面量(對象字面量是三個(gè)大括號包裹)

對象字面量支持了在模板里重組對象以及使用擴(kuò)展運(yùn)算符 … 來展開對象。

<!-- template-demo.swan-->
<template name="tagCard">
    <view>
        <text>標(biāo)簽: {{tag}}</text>
        <text>昵稱: {{nickname}}</text>
    </view>
</template>

<template name="personCard">
    <view>
        <text>位置: {{pos}}</text>
        <text>姓名: {{name}}</text>
    </view>
</template>

<template name="teamCard">
    <view s-for="item, index in teams">
        <text>球隊(duì): {{index}} - {{item}}</text>
    </view>
</template>

<template name="ageCard">
    <view>
        <text>年齡: {{age}}</text>
    </view>
</template>

<template is="personCard" data="{{person}}" />
<!-- 對象字面量 -->
<template is="teamCard" data="{{ {teams} }}" />
<template is="tagCard" data="{{ {tag, nickname: 'king'} }}" />
<template is="ageCard" data="{{ {...person} }}" />
// template-demo.js
Page({
    data: {
        person: {name: 'Lebron James', pos: 'SF', age: 33},
        teams: ['Cleveland Cavaliers', 'Miami Heat', 'Los Angeles Lakers'],
        tag: 'basketball'
    }
});

循環(huán)


s-for

通過循環(huán)渲染列表是常見的場景。通過在元素上作用 s-for 指令,我們可以渲染一個(gè)列表。

默認(rèn)情況

默認(rèn)不寫情況下,下標(biāo)索引是為 index,數(shù)組當(dāng)前變量名默認(rèn)為 item。

<!-- for-demo.swan-->
<view>
    <view s-for="persons">
        {{index}}: {{item.name}}
    </view>
</view>
// for-demo.js
Page({
    data: {
        persons: [
            {name: 'Curry'},
            {name: 'Thompson'},
            {name: 'Durant'},
            {name: 'Green'},
            {name: 'Cousins'}
        ]
    }
});

簡寫

通過簡寫的方式,指定下標(biāo)索引和數(shù)組當(dāng)前變量名。

<!-- for-demo.swan-->
<view>
    <view s-for="p,index in persons">
        {{index}}: {{p.name}}
    </view>
</view>

也可以通過使用 s-for-index 來指定下標(biāo)索引,s-for-item 來指定數(shù)組當(dāng)前變量名。

<!-- for-demo.swan-->
<view>
    <view s-for="persons" s-for-index="idx" s-for-item="p">
        {{idx}}: {{p.name}}
    </view>
</view>

條件


s-if

通過 s-if 指令,我們可以為元素指定條件。當(dāng)條件成立時(shí)元素可見,當(dāng)條件不成立時(shí)元素不存在。通過 s-elif 指令可以給 s-if 增加一個(gè)額外條件分支塊。通過 s-else 指令可以給 s-if 增加一個(gè)不滿足條件的分支塊。s-else 指令沒有值。

<!-- if-demo.swan-->
<view s-if="is4G">4G</view>
<view s-elif="isWifi">Wifi</view>
<view s-else>Other</view>
// if-demo.js
Page({
    data: {
        is4G: true,
        isWifi: false
    }
});

block s-if

block 虛擬組件,在渲染時(shí)不會(huì)包含自身,只會(huì)渲染其內(nèi)容??梢杂脕礓秩疽唤M組件或者標(biāo)簽。

<!-- if-demo.swan-->
<block s-if="flag">
  <view> name </view>
  <view> age </view>
</block>

模板


SWAN 提供模板 template 的用法,旨在提高工程化和代碼可維護(hù)性,可以在模板中定義代碼片段,并被外界注入值,然后在合適的時(shí)機(jī)調(diào)用。

定義模板

name 屬性,定義了模板的名字。

<!-- template-demo.swan-->
<template name="personCard">
    <view>
        <text>位置: {{pos}}</text>
        <text>姓名: {{name}}</text>
    </view>
</template>

使用模板

通過 is 屬性,聲明需要使用的模板,data 是所需要傳入到模板的值,注意對象字面量的使用方法,以及對象字面量是三個(gè)大括號包裹。

<!-- template-demo.swan-->
<template is="personCard" data="{{person}}" />
// template-demo.js
Page({
    data: {
        person: {name: 'Lebron James', pos: 'SF', age: 33}
    }
});

事件處理


事件介紹

事件提供了一種可以將用戶的行為從視圖層反饋到邏輯層進(jìn)行處理的通訊方式。觸發(fā)綁定在組件上的事件的時(shí)候,就會(huì)執(zhí)行邏輯層中對應(yīng)的事件處理函數(shù),同時(shí)也可以傳遞數(shù)據(jù),例如 id , dataset 等。

使用事件的簡單 demo

目標(biāo):在組件中綁定一個(gè)事件處理函數(shù) bindtap 。

模板:

<view id="swanTap" data-say="hello" bindtap="tapHandle"> 點(diǎn)擊 </view>

定義事件的處理函數(shù):

Page({
  tapHandle: function(e) {
    swan.showToast(e.currentTarget.dataset.say);
  }
});

可以看到,當(dāng)用戶點(diǎn)擊組件時(shí)能夠打提示 hello 。

事件的分類

與瀏覽器的 DOM 事件類似,智能小程序的視圖中事件分為冒泡事件和非冒泡事件。冒泡事件指的是當(dāng)組件上的事件被觸發(fā)后,該事件會(huì)向父節(jié)點(diǎn)傳遞。非冒泡事件指的是當(dāng)組件上的事件被觸發(fā)后,該事件不會(huì)向父節(jié)點(diǎn)傳遞。在 SWAN 提供的事件中,冒泡事件如下列表展示,不在列表展示的事件均為非冒泡事件。

事件類型 觸發(fā)時(shí)機(jī)
tap 觸摸后馬上離開
longtap 觸摸后超過350ms再離開(推薦使用 longpress 事件代替)
longpress 觸摸后超過350ms再離開,如果是指定了事件回調(diào)函數(shù)并觸發(fā)了這個(gè)事件,tap 事件將不被觸發(fā)
touchstart 觸摸開始時(shí)
touchmove 觸摸后移動(dòng)時(shí)
touchcancel 觸摸后被打斷時(shí),如來電等
touchend 觸摸結(jié)束時(shí)
transitionend 會(huì)在 transition 或 swan.createAnimation 動(dòng)畫結(jié)束后觸發(fā)
animationstart 會(huì)在 animation 動(dòng)畫開始時(shí)觸發(fā)
animationiteration 會(huì)在 animation 一次迭代結(jié)束時(shí)觸發(fā)
animationend 會(huì)在 animation 動(dòng)畫完成時(shí)觸發(fā)

事件綁定和冒泡

事件綁定在組件上,與屬性的寫法相同,都是以 key、value 的形式。

key 以 bind 或 catch 開頭,銜接事件類型,例如 bindtap、catchtouchcancel。也可以在 bind 和 catch 后可以緊跟一個(gè)冒號,如 bind:tap、catch:touchstart,其功能不變。bind 與 catch 的區(qū)別是 bind 事件綁定不會(huì)阻止冒泡事件向上冒泡,catch 事件綁定可以阻止冒泡事件向上冒泡。value 對應(yīng)的是在 Page 中定義同名的函數(shù),否則在事件觸發(fā)時(shí)執(zhí)行函數(shù)會(huì)拋出異常。

下面看一個(gè)例子:

<view id="wrap" bindtap="handleTap1">
  wrap
  <view id="module" catchtap="handleTap2">
    module
    <view id="text" bindtap="handleTap3">
      text
    </view>
  </view>
</view>

效果:用戶點(diǎn)擊 text 會(huì)先后調(diào)用 handleTap3 和 handleTap2。這是因?yàn)?tap 事件冒泡到了 module,而 module 阻止了 tap 事件冒泡,不再向父節(jié)點(diǎn)傳遞。用戶點(diǎn)擊 module 會(huì)觸發(fā) handleTap2。用戶點(diǎn)擊 wrap 會(huì)觸發(fā) handleTap1。

事件的捕獲

捕獲階段是位于冒泡階段之前,在捕獲階段中,事件到達(dá)節(jié)點(diǎn)的順序與冒泡階段恰好相反。在捕獲階段監(jiān)聽的方式是采用 capture-bind、capture-catch 關(guān)鍵字,后者將中斷捕獲階段和取消冒泡階段。

舉個(gè)例子:

<view id="wrap" bind:touchstart="handleTap1" capture-bind:touchstart="handleTap2">
  wrap
  <view id="inner" bind:touchstart="handleTap3" capture-bind:touchstart="handleTap4">
    text
  </view>
</view>

效果:text 會(huì)先后調(diào)用 handleTap2、handleTap4、handleTap3、handleTap1。

事件對象

默認(rèn)當(dāng)組件觸發(fā)事件時(shí),邏輯層綁定事件的處理函數(shù)會(huì)收到一個(gè)默認(rèn)參數(shù),就是事件對象。

下面是事件對象詳細(xì)屬性列表:

屬性 類型 說明
type String 事件的類型
timeStamp Integer 事件觸發(fā)的時(shí)間戳(毫秒)
target Object 觸發(fā)事件的組件的屬性值集合,詳細(xì)屬性參見 target
currentTarget Object 當(dāng)前組件的一些屬性值集合,詳細(xì)屬性參見 currentTarget
detail Object 自定義事件對象屬性列表,詳細(xì)屬性參見 detail
touches Array 觸摸事件類型存在,存放當(dāng)前停留在屏幕中的觸摸點(diǎn)信息的數(shù)組,touch 詳細(xì)屬性參見 touch
changedTouches Array 觸摸事件類型存在,存放當(dāng)前變化的觸摸點(diǎn)信息的數(shù)組, changedTouch changedTouch

下面是事件對象的屬性為屬性值集合時(shí)的詳細(xì)信息。

target

屬性 類型 說明
id String 觸發(fā)事件組件的 id
tagName String 觸發(fā)事件組件的類型
dataset Object 觸發(fā)事件組件上由data-開頭的自定義屬性組成的集合,詳細(xì)屬性參見 dataset

currentTarget

屬性 類型 說明
id String 事件綁定的組件的 id
tagName String 事件綁定的組件的類型
dataset Object 事件綁定的組件上由data-開頭的自定義屬性組成的集合,詳細(xì)屬性參見 dataset

detail

是自定義事件所攜帶的數(shù)據(jù),具體詳見組件定義中各個(gè)事件的定義。

dataset

在組件的事件被觸發(fā)時(shí),也可以傳遞自定義的數(shù)據(jù)。書寫方式: 以 data- 開頭,多個(gè)單詞由連字符-鏈接,不能有大寫(大寫會(huì)自動(dòng)轉(zhuǎn)成小寫),最終的 - 在 dataset 中會(huì)將連字符轉(zhuǎn)成駝峰式寫法。如組件上data-car-color屬性值的讀取方式是: event.currentTarget.dataset.carColor。

touch

屬性 類型 說明
identifier Number 觸摸點(diǎn)的標(biāo)識符
clientX, clientY Number 距離頁面可顯示區(qū)域(屏幕除去導(dǎo)航條)左上角的X軸與Y軸的距離
pageX, pageY Number 距離文檔左上角的X軸與Y軸的距離

changedTouch

數(shù)據(jù)格式同 touches,指的是有變化的觸摸點(diǎn),如 touchstart(開始),touchmove(變化),touchend,touchcancel(結(jié)束)等。

點(diǎn)擊事件的 detail 帶有的 x, y 同 pageX, pageY 代表距離文檔左上角的距離。

引用


SWAN 可以通過import和include來引用文件。

import

通過import和template配合使用,可以將代碼分離以及復(fù)用。

<!-- personCard.swan-->
<template name="personCard">
    <view>
        <text>位置: {{pos}}</text>
        <text>姓名: {{name}}</text>
    </view>
</template>

在personCard.swan里定義了一個(gè)模板,在index.swan里引用文件,并使用它的模板。

<!-- index.swan-->
<import src="./personCard.swan" />
<template is="personCard" data="{{person}}" />

include

通過include可以將目標(biāo)模板,整個(gè)(除了 template)引入到當(dāng)前的位置,相當(dāng)于inline。

<!-- detail.swan-->
<include src="header.swan" />
<view class="detail">body</view>
<!-- header.swan-->
<view class="header">header</view>

CSS


CSS 是描述 SWAN 的樣式語言。支持 CSS 的屬性。在此基礎(chǔ)上,做了一些編譯支持:

  • 尺寸單位
  • 樣式導(dǎo)入

尺寸單位

對于自適應(yīng)的單位,推薦使用 CSS3 vw 為單位,vw 代表視窗( Viewport )的寬度為1%。同時(shí)也支持 rpx,規(guī)定屏幕寬為750rpx。在 iPhone X 上,屏幕寬度為375px,共有750個(gè)物理像素,則750rpx = 375px = 750物理像素,1rpx = 0.5px = 1物理像素。

樣式導(dǎo)入

為了工程化和代碼復(fù)用,我們支持 @import 語句,導(dǎo)入 CSS 文件。

/* header.css */
.header {
    padding: 8px;
}
/* index.css */
@import "header.css";
.body {
    padding: 12px;
}

組件


SWAN 框架為開發(fā)者提供了一系列組件,可以讓開發(fā)者基于這些基礎(chǔ)組件快速開發(fā)。詳情請見組件文檔

以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號