Weex BindingX 嘗鮮

前言

三月初,阿里巴巴開源的一套基于 Weex、React Native 的富交互解決方案 「BindingX」。提供了一種稱之為 「Expression Binding」 的機制可以在 Weex、React Native 上讓手勢等復(fù)雜交互操作以60fps的幀率流暢執(zhí)行,而不會導(dǎo)致卡頓,因而帶來了更優(yōu)秀的用戶體驗。

背景

聽上去「高大上」,那為啥要造這個輪子呢?

這就得從源頭說起,他到底解決了什么問題。

我們知道,Weex 和 React Native 同樣都是三層結(jié)構(gòu),「 JS 層、 Native 層、 Bridge 層」,Native 層負(fù)責(zé)視覺繪制、事件收集,JS 層負(fù)責(zé)視覺控制、事件處理,Bridge 層是 JS 層和 Native 層的溝通橋梁,負(fù)責(zé)指令「翻譯」。以 Weex 為例:

image

想讓 Native 層做一些復(fù)雜的交互操作時,JS 層就需要不停得處理從 Native 層收集來的事件然后作出「及時」響應(yīng),如果響應(yīng)「不及時」就會導(dǎo)致視覺卡頓。

怎么樣才算是「及時」呢?

我們常說 60fps 幀率是流暢的基礎(chǔ),這就意味著,一次有效的刷新需要在 1/60 s 內(nèi)完成,如果 JS 層從事件接受、處理、回饋到 Native 繪制新的視圖完成超過了 16.67ms 將會出現(xiàn)「視覺卡頓」。

另外,即使每一次更新都可以完全控制在 16.67ms 內(nèi),大量的通訊操作也會消耗掉過多的 CPU,以至于加大了 Crash 的風(fēng)險

如果不突破這層瓶頸,此類技術(shù)將很難達(dá)到一個新的高度。

BindingX 就是解決這個問題的。

原理

BindingX 提出的 「Expression Binding」 將具體的手勢控制行為以 「表達(dá)式」 的方式傳遞給 Native,監(jiān)控「被綁定元素」上發(fā)生的手勢操作并輸出過程中橫向「x」和縱向「y」的偏移量,因此我們即可將「x,y」作為表達(dá)式「f(x),f(y)」的入?yún)ⅲ槍π缘膶δ骋荒繕?biāo)元素的樣式進(jìn)行「綁定變化」。

而這所以操作都是在 Native 層獨立完成的,大大減小了 JS 層和 Bridge 層的壓力。

「無 Binding 模式」

image

「Binding 模式」

image

表達(dá)式

表達(dá)式,是由數(shù)字、運算符、變量等以能求得有意義數(shù)值的字符串。譬如, x\*3+10 就是一個表達(dá)式,當(dāng)x被賦值時,整個表達(dá)式就會有一個明確的結(jié)果。通過表達(dá)式,我們就可以描述一個具體的交互行為,比如我們希望x從0變化到100時,透明度能從1變化到0.5,那么表達(dá)式可以描述為: f(alpha) = 1-(x/100)*0.5 也可以是 f(alpha) = 1-x/200 只不過第一種表達(dá)式更直白。

下面舉一個簡單的例子。

/* 簡碼 */
bindingx.bind({
      anchor:foo_view.ref  ,                    //==> 事件的觸發(fā)者
      eventType:'pan',                          //==> 事件類型
      props: [
          {
            element:foo_view.ref,               //==> 要改變的視圖的引用或者id
            property:'transform.translateX',    //==> 要改變的屬性
            expression:'x+0'                    //==> 表達(dá)式
          }
        ]
    });

就這么簡單,幾行代碼即可綁定 foo_view 實現(xiàn)視圖隨手勢移動的交互。當(dāng)然復(fù)雜的也有,只不過都是由這么一個個小的交互堆積而成的。

除了基本的四則運算外,還支持三元運算符、數(shù)學(xué)函數(shù)等高級語法,基本可以滿足絕大部分的場景。

事件類型

前面的例子中用到了 pan 手勢,除手勢外,BindingX 還支持「列表的滾動 scroll」、「動畫 timing」甚至是「陀螺儀感 orientation」,每種事件類型使用方式大致相同,也有注意點,詳細(xì)請參閱《bindingx 官方文檔》

Do it

怎么樣能快速體驗?zāi)兀?/p>

跟上我的腳步

playground

官方雖然也提供了 試驗田 https://alibaba.github.io/bindingx/playground,但語法均為 Rax 但 DSL,并不少 Weex 對外的 Vue 版本,我們無法在線編輯查看效果,只能使用阿里系A(chǔ)pp「如淘寶、閑魚、飛豬」掃碼體驗效果。

這些都不是我們想要的。

當(dāng)然方法總是有的。

直接將 BindingX 的官方代碼 clone 下來,上面有支持 Vue 版本的 Weex Playground。

bindingx/weex/playground/[ios|android]

ios 和 android 選一個用工具安裝到自己的手機上。此處就不多解釋了,不會的問下 google,或者下方留言。

使用 http://dotwe.org/vue/ 在線編輯,掃碼看效果。

給大家分享幾個 Vue 版本的 demo。

http://dotwe.org/vue/e50f76a6c13337b6fa4201a045c5dc0c

http://dotwe.org/vue/2dff486956044ea59b3d38a2cf20b506

http://dotwe.org/vue/64998432f2a249f5cb35b4de0040526d

http://dotwe.org/vue/cd942c4bee9c4b7bcceda4e3aaf94c70

嚴(yán)選 demo 引入 BindingX

這是很早以前的一個小 Demo,感興趣的可以 star 一下
https://github.com/zwwill/yanxuan-weex-demo

下面我基于嚴(yán)選的 Demo 進(jìn)行的小試用。

升級 ios platform

要想使用 BindingX 插件,就必須使自己的 platform 支持。方法很簡單,只需要將 platforms/ios/Podfile 進(jìn)行升級修改即可。

source 'git@github.com/CocoaPods/Specs.git'
platform :ios, '8.0'                                    #最低8.0
#inhibit_all_warnings!

def common
    pod 'WeexSDK', '0.17.0'                         #升級至 0.17.0
    pod 'Weexplugin', :path=>'./Weexplugin/'
    pod 'WXDevtool'
    pod 'SDWebImage', '3.7.5'
    pod 'SocketRocket', '0.4.2'
    pod 'BindingX'                                     #增加 BindingX
end

target 'WeexDemo' do
    common
end

target 'WeexUITestDemo' do
    common
end

隨后執(zhí)行一遍 pod install 即可安裝成功。如出現(xiàn)錯誤提示,按提示 fix 掉即可。

小試牛刀

Vue 的引入方式不同于 Rax,需要使用 weex.requireModule() API。

<template>
    <div class="wrapper">
        <image ref="headerBg" resize="cover" src="http://cdn.zwwill.com/yanxuan/imgs/bg5.png"></image>
        <scroller ref="contentScroller">
            <div>
                <!-- 省略非關(guān)鍵代碼 -->
            </div>
            <div class="fbs">
                <!-- 省略非關(guān)鍵代碼 -->
            </div>
        </scroller>
    </div>
</template>

<script>
    const binding = weex.requireModule('bindingx');    //引入 bindingx
    export default {
        mounted(){
            this.headerBgBinding();
        },
        beforeDestroy(){
            this.headerBgBindingDestory();
        },
        methods: {
            headerBgBinding(){
                let self = this,
                    scroller = self.$refs.contentScroller.ref,
                    headerBg = self.$refs.headerBg.ref;
                    
                let bindingResult = binding && binding.bind({
                    eventType:'scroll',
                    anchor:scroller,
                    props:[
                        {
                            element:headerBg,
                            property:'transform.scale',
                            expression:{
                                origin:'y<0?(1-y/500):(1+y/500)'
                            }
                        },
                        {
                            element:headerBg,
                            property:'transform.translateY',
                            expression:{
                                origin:'-y/2'
                            }
                        }
                    ]
                },function(e){
                });
                self.gesToken = bindingResult.token;
            }
            headerBgBindingDestory(){
                let self = this;
                if(self.gesToken != 0) {
                    binding.unbind({
                      eventType:'scroll',
                      token:self.gesToken
                    })
                    self.gesToken = 0;
                  }
            }
        }
    }
</script>

實現(xiàn)的效果就是最常見的個人信息頁,title 背景隨著滾動事件變換大小。

效果動圖 http://cdn.zwwill.com/yanxuan/resource/bindingx2.gif

image

寫在最后

Weex 有了 BindingX 如虎添翼。效率更高性!能更穩(wěn)定!同期開源的還有 GCanvas 也是一把神器。

近期工作繁重,通宵寫文章,如發(fā)現(xiàn)文章殘瑕處,敬請諒解!

相關(guān)鏈接

作者: 木羽 zwwill
首發(fā)地址:https://github.com/zwwill/blog/issues/20

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容