隨着電競業務的不斷髮展,頁面功能愈來愈多,交互邏輯更加複雜,相似無限滾動、上拉刷新、橫豎切換滾動等形式在業務中已經是標配,通過重重優化後在H5中的體驗一直達不到理想狀態,沒錯,種種卡,H5的性能太差! 是持續優化仍是破然後立選擇新的技術方向呢?咱們選擇了更有效的後者。css
爲何選擇weex
相對H5來講,weex帶來的用戶體驗更好,它結合了H5和Native各自的優點,既能像H5同樣快速迭代,又能和Native同樣流暢。
次嘗試新方案、新技術時都將面臨着許多問題,企鵝電競接入weex也不例外,咱們在使用weex進行設計還原時並非像H5同樣順利,爲了不小夥伴重複踩坑,本文將主要圍繞H5與weex的區別以及weex ui開發時遇到的問題進行說明。html
本文將從如下幾個方面對Weex進行介紹:
H5與Weex的區別vue
- 項目結構
- 標籤
- 引入sass
- sass變量
weex ui開發踩坑node
- 通用樣式
- 佈局
- 組件
- 動畫
- UI性能
H5與Weex的區別
項目結構
因爲weex和H5是兩套不一樣的技術方案,代碼組織方式、構建工具、和開發側對接方式都會不一樣。android
下圖是電競重構稿H5與weex目錄結構對比,以前H5開發是基於jinja模版,採用grunt構建,在release中生成相應的html文件,而weex則主要在src中開發組件,採用webpack編譯,最終會在dist中生成相對應地web和weex版jsbundle文件,再由weex.html生成的二維碼查看weex版頁面效果。webpack
此外weex下的src目錄內容是與開發側保持一致的,這樣的好處在於開發人員只須要關注組件的結構變化,其它資源直接更新替換便可。ios
標籤
weex只提供了17個組件,如div、text、image等,其中text和H5中p標籤等同,文字只能放到text下,text中不能嵌套其餘標籤。css3
引入sass
- 安裝sass依賴的npm包:sass-loader、node-sass、sass-loader、stylus-loader。
- 在build文件夾下webpack.base.conf.js的rules裏面添加配置。
rules:{ { test: /\.(scss|css)$/, loader: 'vue-style-loader!css-loader!sass-loader!stylus-loader?indentedSyntax', } }er-width:$border.width; }
- style中修改lang=「stylus」
sass變量
weex中的sass變量相似於對象的寫法:web
//variable.scss $border={ color: #E9E9E9 width:2px }
@import "./variable.scss"; .border{ border-color:$border.color; border-width:$border.width; }
weex ui踩坑
通用樣式
一、border
weex不支持使用border建立三角形,web能夠正常顯示,而ios和android上顯示的是矩形,建議使用圖片代替。
npm
二、transform
一、rotate角度儘可能避免設置負數,某些部分安卓機型會不生效。
二、不支持transform:skew 對於這一類角標須要作傾斜處理能夠採用 圖片加 漸變代碼處理。
三、圖片
一、weex提供了image組件,但只支持遠程圖片連接。
二、避免在image標籤上使用v-for,不然會致使安卓上圖片渲染異常(如slider中的圖片)。
四、透明度
如下是涉及到顏色的相關屬性對透明度的支持度列表。如圖:
注意:box-shadow (自己不支持android),background-image不支持IOS透明。
五、點擊態
項目比較常見的點擊態多半是透明度的變化,如按鈕、列表、連接等,css的作法是添加僞類 (:active),weex中也一樣支持,可是weex須要在原樣式中添加 opacity:1,不然點擊後回不到初始狀態;此外,:active使用時,background-image在ios下會失效。例如:
<template> <div class="ui-btn"> <text class="ui-btn-text">下載</text> </div> </template> <style scoped> .ui-btn{ opacity: 1; /*必須添加*/ } .ui-btn:active{ opacity: .5; } </style>
六、文本截斷
以下圖,要實現下面的效果:
文本從限制1行到不限制能夠用lines:0;
<template> <text class="info-text" @click="textClick" :style="textStyle">城市賽戰報,《王者榮耀》城市賽鄭州站歡樂落幕城市賽戰報,《王者榮耀》城市賽鄭州站歡樂落幕城市賽戰報,《王者榮耀》城市賽鄭州站歡樂落幕城市賽戰報,《王者榮耀》城市賽鄭州站歡樂落幕</text> </template> <style scoped> .info-text{ lines:1; text-overflow:ellipsis; } </style> <script> export default { data(){ return { textStyle:{} }; }, methods:{ textClick(){ this.textStyle = { lines:0 } } } } </script> </style>
七、層級問題
例如,有a、b、c、d 四層結構,其中a、b、c均爲absolute定位,z-index由大到小,d爲普通結構,咱們知道在css中a層應該是處於最上方,d在最下方,那麼在weex中表現如何呢?
<div class="wrapper"> <div class="box a">a</div> <div class="box b">b</div> <div class="box c">c</div> <div class="d">d</div> </div>
能夠看到web和ios、android的表現不一致,ios、android中是以代碼中dom順序來依次添加的,和z-index無關,後面加載的視圖會覆蓋前面的視圖。因此要保證web、ios、android三端表現一致,改變dom書寫順序便可。
<div class="d"></div> <div class="box c"></div> <div class="box b"></div> <div class="box a"></div>
八、安卓遮擋問題
安卓環境下容器若是設置了寬高,那麼子元素不能超出容器範圍。
建議:fixed定位不會受父容器影響,若是須要超出限制,子元素能夠設置fixed
九、v-if問題
在作一些操做切換狀態時(如按鈕點擊置灰),應儘可能避免使用v-if,使用v-if會閃,且部分安卓機子會發生不可描述的事情(如部分三星機型會出現按鈕文字居頂),可採用添加class的方式。
佈局
一、單行文本與圖片並排方案
目前項目中存在這樣的情形,暱稱與直播標籤並排,暱稱文字短時直播要跟隨,暱稱很長時要作溢出截斷(超出時加…) 。
這種佈局方式在css中要作到很容易,而在weex中利用提供的flex佈局確很難實現,最後的解決方案是經過js動態設置文字與標籤父級的寬度,從而控制文字的溢出。
<template> <div class="wrapper" @appear="onappear"> <div class="info-container" ref='info-container'> <div class="info" ref='info' :class="isFullText?['info-full']:[]"> <text class="nick-text">{ {isFullText}}企鵝電競企鵝電競企鵝電競企鵝電競</text> <img src="http://119.29.8.64/vipstyle/egame/app/weex/tab/ERICKCHEN-MC0/dist/static/img/live.b467410.png" class="live-image"> </div> </div> </div> </template> <style scoped lang="stylus"> .info-full{ width:300px; } </style> <script> const dom = weex.requireModule('dom') export default { data(){ return { isFullText:false }; }, methods:{ onappear(){ dom.getComponentRect(this.$refs['info'],option1=>{ dom.getComponentRect(this.$refs['info-container'],option2=>{ if(option1.size.width>=option2.size.width){ this.isFullText=true; } }) }); } } } </script>
二、多行文本與圖片並排方案
場景一:圖片位於段落左側
css的float能夠作到圖文混排,而weex只提供了flex佈局,而且text組件之間也不能進行嵌套,沒法作到這種圖文混排效果,不過weex的text組件比較奇特,那就是text組件中的空格是照代碼原樣輸出的。例如:
<text> 戰國鬼才傳,這個名字想必不少人聽都沒有聽過吧,這個名字說實話真的不是很吸引人…</text>
那麼運行效果以下圖:
因此解決的方案能夠利用填充空格給圖片預留位置,先計算一個空格的寬度,再計算這張圖片所須要的空格數量,最後空格鏈接字符串輸出。
結構代碼:
<template> <div class="wrapper"> <scroller class="scroller"> <div @appear="handleAppear"> <text>空格寬度:{ {spaceWidth}}-空格數量:{ {spaceNum}}</text> <text class="demo-text" ref="demo-text1"> test</text> <text class="demo-text" ref="demo-text2">test</text> </div> <div class="rich"> <div class="rich-icon"></div> <text class="rich-text" :style="textStyle">{ {content}}</text> </div> </scroller> </div> </template>
樣式:
<style scoped> .demo-text{ position: absolute; font-size: 32px;/*文字大小與須要加空格文字大小保持一致*/ opacity: 0; } .rich{ position: relative; } .rich-icon{ position: absolute; left:0; top:4px; width: 120px; height: 32px; background-color: red; } .rich-text{ font-size: 32px; } </style>
核心代碼:
<script> const dom = weex.requireModule('dom'); export default { data(){ return { spaceWidth:0,//空格寬度 spaceNum:0,//所需空格數量 opacity:0,//初始透明度爲0,避免文案抖動 content:'王者榮耀遊戲中的鑽石用來作什麼最合算?王者榮耀鑽石用來幹什麼最好?在王者榮耀中鑽石並非惟一通用的貨幣,在遊戲中還有金幣和點券,小編我的以爲鑽石在遊戲中並無其餘兩種貨幣有優點。' }; }, computed:{ textStyle(){ return { opacity:this.opacity } } }, methods:{ handleAppear(){ setTimeout(()=>{ this.setTextContent(); },30) }, async setTextContent(){ const text1El = this.$refs['demo-text1']; const text2El = this.$refs['demo-text2']; let textSize1,textSize2; await this.getSpaceSize(text1El,(data)=>{ textSize1 = data; }); await this.getSpaceSize(text2El,(data)=>{ textSize2 = data; }); this.spaceWidth=Math.abs(textSize1-textSize2)/10; this.content=this.getSpaceNum(); this.opacity=1; }, getSpaceSize(el,callback){ return new Promise(function (resolve) { dom.getComponentRect(el, option => { if(option.result){ resolve(callback(option.size.width)); } }); }) }, getSpaceNum(){ this.spaceNum = Math.ceil(120 / this.spaceWidth);//120爲紅色區塊寬度 return new Array(this.spaceNum).join(' ')+ this.content; } } } </script>
場景二:圖片位於段落末尾
很遺憾,目前這種特殊文本以及圖片置於段落末尾並無找到相應的解決方案,只能依賴終端添加相應的富文本功能。
組件
一、命名
組件命名應避免使用JS關鍵字和保留字,以及weex提供的組件名稱,如用loading做爲組件名稱,在ios與android中將呈現空白。
二、自定義slider組件
weex自己提供了slider組件,但輪播圖指示器(indicator)只能修改顏色與位置,大小卻沒法更改,因此須要自定義slider組件。
weex輪播圖指示器效果
電競項目輪播圖指示器效果
weex slider提供了change事件,能夠獲取到當前播放的序號,從而作到自定義輪播指示器。 可是當中遇到一個詭異問題:若是「div.indicator-item」的內容爲空的話,H5中的指示器並不會隨着圖片切換而變化(樣式不生效),div中須要添加內容才行。如下是示例代碼:
<div class="indicator-item" v-for="(item,index) in data" ...> { {index}}/*添加內容,解決H5中class切換樣式不生效問題*/ </div> <template> <div class="slider-container" :style="sliderStyle"> <slider class="slider" :interval="interval" @change="change" :auto-play="autoPlay"> <div class="slider-item" v-for="img in data" > <image class="slider-image" :style="sliderStyle" resize="cover" :src="img.src"></image> </div> </slider> <div class="slider-indicator"> <div class="indicator-item" v-for="(item,index) in data" :class="[current == index ? 'indicator-active' : '']"> { {index}} </div> </div> </div> </template>
動畫
關鍵幀動畫是很常見的一種動畫,css3中能夠利用@keyframes規則達到動畫效果。
weex中提供了transition,能夠傳入相應的style,經過setInterval控制動畫循環播放,但setInterval比較耗性能,建議終端對weex sdk進行改造,加入相應的循環播放功能。
<template> <div class="wrapper"> <div class="demo" ref="demo"></div> </div> </template> <style scoped> .demo{ width: 200px; height: 200px; background-color: gold; } </style> <script> import * as animation from './animation.js' export default { mounted() { setTimeout(()=>{ setInterval(() => { animation.run(this.$refs.demo); }, 2100); },200) } } </script>
animation.js
const animation = weex.requireModule('animation'); export function transition(el, opts,dd) { let duration = dd || 400 if (!el) { return Promise.resolve(); } return new Promise(function (resolve) { animation.transition(el, { duration: duration, timingFunction: 'linear', delay: 0, ...opts }, resolve); }) } export async function run(el, obj) { await transition(el, { styles: { backgroundColor: 'red', } },0.0001) await transition(el, { styles: { backgroundColor: 'purple', } },1000) await transition(el, { styles: { backgroundColor: 'lime', } },1000) }
性能
安卓下打開「調試GPU過分繪製」選項,打開以後選擇「顯示過分區域繪製」後,會發現手機界面基本被藍色,淡綠,淡紅,深紅所填充,這幾種顏色表明了不一樣程度的繪製狀況,其中藍色繪製最少,而深紅色繪製最多,可能會形成頁面卡頓,應避免出現大面積紅色區域。
優化建議:
一、儘可能不要設置背景色;
二、不要過分嵌套,結構儘可能扁平化;
本文同步分享在 博客「xiangzhihong8」(CSDN)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。