Weex BindingX 嚐鮮

圖片描述

前言

三月初,阿里巴巴開源的一套基於 Weex、React Native 的富交互解決方案 「BindingX」。提供了一種稱之爲 「Expression Binding」 的機制能夠在 Weex、React Native 上讓手勢等複雜交互操做以60fps的幀率流暢執行,而不會致使卡頓,於是帶來了更優秀的用戶體驗。html

背景

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

這就得從源頭提及,他到底解決了什麼問題。vue

咱們知道,Weex 和 React Native 一樣都是三層結構,「 JS 層、 Native 層、 Bridge 層」,Native 層負責視覺繪製、事件收集,JS 層負責視覺控制、事件處理,Bridge 層是 JS 層和 Native 層的溝通橋樑,負責指令「翻譯」。以 Weex 爲例:android

想讓 Native 層作一些複雜的交互操做時,JS 層就須要不停得處理從 Native 層收集來的事件而後做出「及時」響應,若是響應「不及時」就會致使視覺卡頓。ios

怎麼樣纔算是「及時」呢?git

咱們常說 60fps 幀率是流暢的基礎,這就意味着,一次有效的刷新須要在 1/60 s 內完成,若是 JS 層從事件接受、處理、回饋到 Native 繪製新的視圖完成超過了 16.67ms 將會出現「視覺卡頓」。github

另外,即便每一次更新均可以徹底控制在 16.67ms 內,大量的通信操做也會消耗掉過多的 CPU,以致於加大了 Crash 的風險express

若是不突破這層瓶頸,此類技術將很難達到一個新的高度。weex

BindingX 就是解決這個問題的。app

原理

BindingX 提出的 「Expression Binding」 將具體的手勢控制行爲以 「表達式」 的方式傳遞給 Native,監控「被綁定元素」上發生的手勢操做並輸出過程當中橫向「x」和縱向「y」的偏移量,所以咱們便可將「x,y」做爲表達式「f(x),f(y)」的入參,針對性的對某一目標元素的樣式進行「綁定變化」。函數

而這因此操做都是在 Native 層獨立完成的,大大減少了 JS 層和 Bridge 層的壓力。

「無 Binding 模式」

「Binding 模式」

表達式

表達式,是由數字、運算符、變量等以能求得有意義數值的字符串。譬如, x\*3+10 就是一個表達式,當x被賦值時,整個表達式就會有一個明確的結果。經過表達式,咱們就能夠描述一個具體的交互行爲,好比咱們但願x從0變化到100時,透明度能從1變化到0.5,那麼表達式能夠描述爲: f(alpha) = 1-(x/100)*0.5 也能夠是 f(alpha) = 1-x/200 只不過第一種表達式更直白。

下面舉一個簡單的例子。

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

就這麼簡單,幾行代碼便可綁定 foo_view 實現視圖隨手勢移動的交互。固然複雜的也有,只不過都是由這麼一個個小的交互堆積而成的。

除了基本的四則運算外,還支持三元運算符、數學函數等高級語法,基本能夠知足絕大部分的場景。

事件類型

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

Do it

怎麼樣能快速體驗呢?

跟上個人腳步

playground

官方雖然也提供了 試驗田 https://alibaba.github.io/bindingx/playground,但語法均爲 Rax 但 DSL,並很多 Weex 對外的 Vue 版本,咱們沒法在線編輯查看效果,只能使用阿里系App「如淘寶、閒魚、飛豬」掃碼體驗效果。

這些都不是咱們想要的。

固然方法老是有的。

直接將 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

嚴選 demo 引入 BindingX

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

下面我基於嚴選的 Demo 進行的小試用。

升級 ios platform

要想使用 BindingX 插件,就必須使本身的 platform 支持。方法很簡單,只須要將 platforms/ios/Podfile 進行升級修改便可。

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

隨後執行一遍 pod install 便可安裝成功。如出現錯誤提示,按提示 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>
                <!-- 省略非關鍵代碼 -->
            </div>
            <div class="fbs">
                <!-- 省略非關鍵代碼 -->
            </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>

實現的效果就是最多見的我的信息頁,title 背景隨着滾動事件變換大小。

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

寫在最後

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

近期工做繁重,通宵寫文章,如發現文章殘瑕處,敬請諒解!

相關連接

做者: 木羽 zwwill
首發地址: https://github.com/zwwill/blog/issues/20
相關文章
相關標籤/搜索