三月初,阿里巴巴開源的一套基於 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 官方文檔》。
怎麼樣能快速體驗呢?跟上個人腳步
官方雖然也提供了 試驗田 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,感興趣的能夠 star 一下
https://github.com/zwwill/yanxuan-weex-demo
下面我基於嚴選的 Demo 進行的小試用。
要想使用 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