腾讯DeepOcean原创文章:dopro.io/egame-weex-…

随着电竞业务的不断发展,页面功能越来越多,交互逻辑更加复杂,类似无限滚动、上拉刷新、横竖切换滚动等形式在业务中已是标配,经过重重优化后在H5中的体验一直达不到理想状态,没错,种种卡,H5的性能太差! 是持续优化还是破而后立选择新的技术方向呢?我们选择了更有效的后者。

为什么选择weex

相对H5来说,weex带来的用户体验更好,它结合了H5和Native各自的优势,既能像H5一样快速迭代,又能和Native一样流畅。

H5 Weex Native
开发成本
维护更新 简单 简单 复杂
用户体验
发版审核 不需要 不需要 需要
跨平台性

项目中每一次尝试新方案、新技术时都将面临着许多问题,企鹅电竞接入weex也不例外,我们在使用weex进行设计还原时并不是像H5一样顺利,为了避免小伙伴重复踩坑,本文将主要围绕H5与weex的区别以及weex ui开发时遇到的问题进行说明。

H5与Weex的区别

  • 项目结构
  • 标签
  • 引入sass
  • sass变量

weex ui开发踩坑

  • 通用样式
  • 布局
  • 组件
  • 动画
  • UI性能

H5与Weex的区别

项目结构

由于weex和H5是两套不同的技术方案,代码组织方式、构建工具、和开发侧对接方式都会不同。

下图是电竞重构稿H5与weex目录结构对比,之前H5开发是基于jinja模版,采用grunt构建,在release中生成相应的html文件,而weex则主要在src中开发组件,采用webpack编译,最终会在dist中生成相对应地web和weex版jsbundle文件,再由weex.html生成的二维码查看weex版页面效果。

此外weex下的src目录内容是与开发侧保持一致的,这样的好处在于开发人员只需要关注组件的结构变化,其它资源直接更新替换即可。

标签

weex只提供了17个组件,如div、text、image等,其中text和H5中p标签等同,文字只能放到text下,text中不能嵌套其他标签。

引入sass

1、安装sass依赖的npm包:sass-loader、node-sass、sass-loader、stylus-loader

2、在build文件夹下webpack.base.conf.js的rules里面添加配置

  1. rules:{
  2. {
  3. test: /\.(scss|css)$/,
  4. loader: 'vue-style-loader!css-loader!sass-loader!stylus-loader?indentedSyntax',
  5. }
  6. }er-width:$border.width;
  7. }

3、style中修改lang="stylus"

sass变量

weex中的sass变量类似于对象的写法

  1. //variable.scss
  2. $border={
  3. color: #E9E9E9
  4. width:2px
  5. }
  1. @import "./variable.scss";
  2. .border{
  3. border-color:$border.color;
  4. border-width:$border.width;
  5. }

weex ui开发踩坑

通用样式

1、border

weex不支持使用border创建三角形,web可以正常显示,而ios和android上显示的是矩形,建议使用图片代替

web: ios、android:

2、transform

1、rotate角度尽量避免设置负数,某些部分安卓机型会不生效

2、不支持transform:skew 对于这一类角标需要做倾斜处理可以采用 图片加  渐变代码处理

3、图片

1、weex提供了image组件,但只支持远程图片链接

2、避免在image标签上使用v-for,否则会导致安卓上图片渲染异常(如slider中的图片)

4、透明度

以下是涉及到颜色的相关属性对透明度的支持度列表,

注意:box-shadow (本身不支持android),background-image不支持IOS透明

属性 IOS Android H5
color 支持 支持 支持
opacity 支持 支持 支持
border-color 支持 支持 支持
box-shadow 支持 不支持 支持
background-color 支持 支持 支持
background-image 不支持 支持 支持

5、点击态

项目比较常见的点击态多半是透明度的变化,如按钮、列表、链接等,css的做法是添加伪类 (:active),weex中也同样支持,但是weex需要在原样式中添加 opacity:1,否则点击后回不到初始状态;此外,:active使用时,background-image在ios下会失效。

  1. <template>  
  2.    <div class="ui-btn">
  3.        <text class="ui-btn-text">下载</text>
  4.    </div>
  5. </template>
  6. <style scoped>
  7.    .ui-btn{
  8.        opacity: 1; /*必须添加*/
  9.    }
  10.    .ui-btn:active{
  11.        opacity: .5;
  12.    }
  13. </style>

6、文本截断

文本从限制1行到不限制可以用lines:0;

  1. <template>
  2.    <text class="info-text"
  3.          @click="textClick"
  4.          :style="textStyle">城市赛战报,《王者荣耀》城市赛郑州站欢乐落幕城市赛战报,《王者荣耀》城市赛郑州站欢乐落幕城市赛战报,《王者荣耀》城市赛郑州站欢乐落幕城市赛战报,《王者荣耀》城市赛郑州站欢乐落幕</text>
  5. </template>
  6. <style scoped>
  7.    .info-text{
  8.        lines:1;
  9.        text-overflow:ellipsis;
  10.    }
  11. </style>
  12. <script>
  13.    export default {
  14.        data(){
  15.            return {
  16.                textStyle:{}
  17.            };
  18.        },
  19.        methods:{
  20.            textClick(){
  21.                this.textStyle = {
  22.                    lines:0
  23.                }
  24.            }
  25.        }
  26.    }
  27. </script>
  28. </style>

7、层级问题

例如有a、b、c、d 四层结构,其中a、b、c均为absolute定位,z-index由大到小,d为普通结构,我们知道在css中a层应该是处于最上方,d在最下方,那么在weex中表现如何呢?

  1. <div class="wrapper">
  2. <div class="box a">a</div>
  3. <div class="box b">b</div>
  4. <div class="box c">c</div>
  5. <div class="d">d</div>
  6. </div>
  7. &nbsp;

web  native

可以看到web和ios、android的表现不一致,ios、android中是以代码中dom顺序来依次添加的,和z-index无关,后面加载的视图会覆盖前面的视图。

所以要保证web、ios、android三端表现一致,改变dom书写顺序即可。

  1. <div class="d"></div>
  2. <div class="box c"></div>
  3. <div class="box b"></div>
  4. <div class="box a"></div>

8、安卓下遮挡问题

安卓下容器如果设置了宽高,那么子元素不能超出容器范围

[cc lang="html"]

[/cc]

web、ios android

建议:fixed定位不会受父容器影响,如果需要超出限制,子元素可以设置fixed

9、v-if问题

在做一些操作切换状态时(如按钮点击置灰),应尽量避免使用v-if,使用v-if会闪,且部分安卓机子会发生不可描述的事情(如部分三星机型会出现按钮文字居顶),可采用添加class的方式

布局

1、单行文本与图片并排方案

目前项目中存在这样的情形,昵称与直播标签并排,昵称文字短时直播要跟随,昵称很长时要做溢出截断(超出时加...)

这种布局方式在css中要做到很容易,而在weex中利用提供的flex布局确很难实现,最后的解决方案是通过js动态设置文字与标签父级的宽度,从而控制文字的溢出

  1. <template>
  2.    <div class="wrapper"  @appear="onappear">
  3.        <div class="info-container" ref='info-container'>
  4.            <div class="info" ref='info' :class="isFullText?['info-full']:[]">
  5.                <text class="nick-text">{{isFullText}}企鹅电竞企鹅电竞企鹅电竞企鹅电竞</text>
  6.                <img src="http://119.29.8.64/vipstyle/egame/app/weex/tab/ERICKCHEN-MC0/dist/static/img/live.b467410.png" class="live-image">
  7.            </div>
  8.        </div>
  9.    </div>
  10. </template>
  11. <style scoped lang="stylus">
  12.    .info-full{
  13.        width:300px;
  14.    }
  15. </style>
  16. <script>
  17. const dom = weex.requireModule('dom')
  18.    export default {
  19.        data(){
  20.            return {
  21.                isFullText:false
  22.            };
  23.        },
  24.        methods:{
  25.            onappear(){
  26.                dom.getComponentRect(this.$refs['info'],option1=>{
  27.                        dom.getComponentRect(this.$refs['info-container'],option2=>{
  28.                            if(option1.size.width>=option2.size.width){
  29.                                this.isFullText=true;
  30.                            }
  31.                        })
  32.                    });
  33.            }
  34.        }
  35.    }
  36. </script>

2、多行文本与图片并排方案

场景一:图片位于段落左侧

css的float可以做到图文混排,而weex只提供了flex布局,并且text组件之间也不能进行嵌套,无法做到这种图文混排效果,不过weex的text组件比较奇特,那就是text组件中的空格是照代码原样输出的,如

  1. <text>              战国鬼才传,这个名字想必很多人听都没有听过吧,这个名字说实话真的不是很吸引人…</text>

文案效果:

所以解决的方案可以利用填充空格给图片预留位置,先计算一个空格的宽度,再计算这张图片所需要的空格数量,最后空格连接字符串输出。

ios、android效果如下(红色色块为图片区域):

结构

  1. <template>
  2.    <div class="wrapper">
  3.      <scroller class="scroller">
  4.        <div @appear="handleAppear">
  5.            <text>空格宽度:{{spaceWidth}}-空格数量:{{spaceNum}}</text>
  6.            <text class="demo-text" ref="demo-text1">          test</text>
  7.            <text class="demo-text" ref="demo-text2">test</text>
  8.        </div>
  9.        <div class="rich">
  10.          <div class="rich-icon"></div>
  11.          <text class="rich-text" :style="textStyle">{{content}}</text>
  12.        </div>
  13.      </scroller>  
  14.    </div>
  15. </template>

样式

  1. <style scoped>
  2.    .demo-text{
  3.        position: absolute;
  4.        font-size: 32px;/*文字大小与需要加空格文字大小保持一致*/
  5.        opacity: 0;
  6.    }
  7.    .rich{
  8.      position: relative;
  9.    }
  10.    .rich-icon{
  11.      position: absolute;
  12.      left:0;
  13.      top:4px;
  14.      width: 120px;
  15.      height: 32px;
  16.      background-color: red;
  17.    }
  18.    .rich-text{
  19.      font-size: 32px;
  20.    }
  21. </style>

核心代码

  1. <script>
  2.    const dom = weex.requireModule('dom');
  3.    export default {
  4.        data(){
  5.            return {
  6.                spaceWidth:0,//空格宽度
  7.                spaceNum:0,//所需空格数量
  8.                opacity:0,//初始透明度为0,避免文案抖动
  9.                content:'王者荣耀游戏中的钻石用来做什么最合算?王者荣耀钻石用来干什么最好?在王者荣耀中钻石并不是唯一通用的货币,在游戏中还有金币和点券,小编个人觉得钻石在游戏中并没有其他两种货币有优势。'
  10.            };
  11.        },
  12.        computed:{
  13.                textStyle(){
  14.                  return {
  15.                    opacity:this.opacity
  16.                  }
  17.                }
  18.        },
  19.        methods:{
  20.            handleAppear(){
  21.                setTimeout(()=>{
  22.                    this.setTextContent();
  23.                },30)
  24.            },
  25.            async setTextContent(){
  26.                const text1El = this.$refs['demo-text1'];
  27.                const text2El = this.$refs['demo-text2'];
  28.                let textSize1,textSize2;
  29.                await this.getSpaceSize(text1El,(data)=>{
  30.                    textSize1 = data;
  31.                });
  32.                await this.getSpaceSize(text2El,(data)=>{
  33.                    textSize2 = data;
  34.                });
  35.                this.spaceWidth=Math.abs(textSize1-textSize2)/10;
  36.                this.content=this.getSpaceNum();
  37.                this.opacity=1;
  38.            },
  39.            getSpaceSize(el,callback){
  40.              return new Promise(function (resolve) {
  41.                  dom.getComponentRect(el, option => {
  42.                     if(option.result){
  43.                          resolve(callback(option.size.width));
  44.                     }
  45.                  });
  46.              })
  47.            },
  48.            getSpaceNum(){
  49.              this.spaceNum = Math.ceil(120 / this.spaceWidth);//120为红色区块宽度
  50.              return new Array(this.spaceNum).join(' ')+ this.content;
  51.            }
  52.        }
  53.    }
  54. </script>
场景二:图片位于段落末尾

很遗憾,目前这种特殊文本以及图片置于段落末尾并没有找到相应的解决方案,只能依赖终端添加相应的富文本功能。

组件

1、命名

组件命名应避免使用JS关键字和保留字,以及weex提供的组件名称,如用loading作为组件名称,在ios与android中将呈现空白。

错误示例:

  1. <template>
  2.    <div class="wrapper">
  3.        <Loading></Loading>/*改用其它名称*/
  4.    </div>
  5. </template>
  6. <script>
  7. import Loading from './demo'
  8.    export default {
  9.        components:{
  10.            Loading
  11.        }
  12.    }
  13. </script>    

2、自定义slider组件

weex本身提供了slider组件,但轮播图指示器(indicator)只能修改颜色与位置,大小却无法更改,所以需要自定义slider组件

weex轮播图指示器效果:

电竞项目轮播图指示器效果

weex slider提供了change事件,可以获取到当前播放的序号,从而做到自定义轮播指示器。 但是当中遇到一个诡异问题:如果“div.indicator-item”的内容为空的话,H5中的指示器并不会随着图片切换而变化(样式不生效),div中需要添加内容才行

  1. <div class="indicator-item"  v-for="(item,index) in data" ...>
  2. {{index}}/*添加内容,解决H5中class切换样式不生效问题*/
  3. </div>

完整结构如下:

  1. <template>
  2.    <div class="slider-container" :style="sliderStyle">
  3.        <slider class="slider" :interval="interval" @change="change" :auto-play="autoPlay">
  4.            <div class="slider-item" v-for="img in data" >
  5.                <image class="slider-image" :style="sliderStyle"  resize="cover" :src="img.src"></image>
  6.            </div>
  7.        </slider>
  8.        <div class="slider-indicator">
  9.            <div class="indicator-item"  v-for="(item,index) in data" :class="[current == index ? 'indicator-active' : '']">
  10.                {{index}}
  11.            </div>
  12.        </div>
  13.    </div>
  14. </template>

动画

关键帧动画是很常见的一种动画,css3中可以利用@keyframes规则达到动画效果

css3: [cc lang="css"]

[/cc] 效果如图:

weex中提供了transition,可以传入相应的style,通过setInterval控制动画循环播放,但setInterval比较耗性能,建议终端对weex sdk进行改造,加入相应的循环播放功能

  1. <template>
  2.    <div class="wrapper">
  3.        <div class="demo" ref="demo"></div>
  4.    </div>
  5. </template>
  6. <style scoped>
  7.    .demo{
  8.        width: 200px;
  9.        height: 200px;
  10.        background-color: gold;
  11.    }
  12. </style>
  13. <script>
  14. import * as animation from './animation.js'
  15.    export default {
  16.        mounted() {
  17.            setTimeout(()=>{
  18.                setInterval(() => {
  19.                    animation.run(this.$refs.demo);
  20.                }, 2100);
  21.            },200)
  22.        }
  23.    }
  24. </script>

animation.js

  1. const animation = weex.requireModule('animation');
  2. export function transition(el, opts,dd) {
  3.  let duration = dd || 400
  4.  if (!el) {
  5.    return Promise.resolve();
  6.  }
  7.  return new Promise(function (resolve) {
  8.      animation.transition(el, {
  9.          duration: duration,
  10.          timingFunction: 'linear',
  11.          delay: 0,
  12.          ...opts
  13.      }, resolve);
  14.  })
  15. }
  16. export async function run(el, obj) {
  17.  await transition(el, {
  18.      styles: {
  19.          backgroundColor: 'red',
  20.      }
  21.  },0.0001)
  22.  await transition(el, {
  23.      styles: {
  24.          backgroundColor: 'purple',
  25.      }
  26.  },1000)
  27.  await transition(el, {
  28.      styles: {
  29.          backgroundColor: 'lime',
  30.      }  
  31.  },1000)
  32. }

UI性能

安卓下打开“调试GPU过度绘制”选项,打开之后选择“显示过度区域绘制”后,会发现手机界面基本被蓝色,淡绿,淡红,深红所填充,这几种颜色代表了不同程度的绘制情况,其中蓝色绘制最少,而深红色绘制最多,可能会造成页面卡顿,应避免出现大面积红色区域。

优化建议:

1、尽量不要设置背景色

2、不要过度嵌套,结构尽量扁平化

最后

weex目前仍在不断的完善中,过程中遇到的问题将不断被修复,后续将持续更新。

欢迎关注"腾讯DeepOcean"微信公众号,每周为你推送前端、人工智能、SEO/ASO等领域相关的原创优质技术文章:

看小编搬运这么辛苦,关注一个呗:)

企鹅电竞weex实践——UI开发篇相关推荐

  1. 企鹅电竞weex实践之UI篇

    随着电竞业务的不断发展,页面功能越来越多,交互逻辑更加复杂,类似无限滚动.上拉刷新.横竖切换滚动等形式在业务中已是标配,经过重重优化后在H5中的体验一直达不到理想状态,没错,种种卡,H5的性能太差! ...

  2. Weex实战分享|企鹅电竞Weex实践和性能优化

    渠宏伟 企鹅电竞前端团队Leader H5页面存在的问题 H5页面对比终端的不足,第一,加载慢:第二,交互差. 加载耗时比较长,因为它受限于Webview,Webview在Android上启动就比较慢 ...

  3. weex android 性能,跨越适配性能那道坎,企鹅电竞Android weex优化

    作者:龙泉,腾讯企鹅电竞工程师 商业转载请联系腾讯WeTest获得授权,非商业转载请注明出处. WeTest 导读 企鹅电竞从17年6月接入weex,到现在已经有一年半的时间,这段时间里面,针对遇到的 ...

  4. 企鹅电竞Web P2P实践

    前言:本文是基于SwarmCloud创始人在2018腾讯Live开发者大会上的演讲整理而成. 项目背景 我们知道,Adobe宣布2020年将停止Flash的更新.实际上,Flash本身就存在很多问题, ...

  5. Flutter 布局之企鹅电竞

    本人主要在知乎上发布相关Flutter文章,知乎了解下: https://www.zhihu.com/people/qiang-fu-5-67/activities 我们来实战剖析下"企鹅电 ...

  6. mfc程序转化为qt_以“企鹅电竞小程序”改版为例,讲解如何将用户核心路径转化为设计语言...

    前言 用户路径是指用户达到目标时一系列的操作.我们可以将用户在产品中由开始到结束的整个过程划分成很多节点,用户从一个节点到另一个节点的过程可以被视为是一条路径.用户路径主要分为两种:一种是用户找寻信息 ...

  7. 企鹅电竞宣布将于6月7日终止运营

    4月7日消息,企鹅电竞官网今日发布退市公告,称由于业务发展策略的变更 ,<企鹅电竞>(包括其网页端.App端.PC端.TV端.H5.微信小程序)以及<企鹅电竞直播助手>(包括其 ...

  8. python 发送企鹅电竞弹幕(简单版)

    相信大家在看过小编上次的获取弹幕,也一定想要知道怎么发送弹幕.那么今天小编也来介绍一下怎么发送弹幕. 但是事先声明,小编也不喜欢水军.希望大家能不破坏弹幕界的和谐和安宁.如果你玩啥水军,官方把规则改了 ...

  9. python获取企鹅电竞弹幕信息

    https://blog.csdn.net/bimo123/article/details/81162067 由于百度云盘经常更新所以以后的百度云链接会在评论区贴上.谢谢 相信大家已经看过乙站的弹幕获 ...

最新文章

  1. 从神经元谈到深度神经网络
  2. 4个计算机视觉领域用作迁移学习的模型
  3. SAP S4HANA Buiness Partner名词解析
  4. plotplayer声道设置原声
  5. SMGP3.0协议的概念知识
  6. LinuxWorld 2007:Linux从狂热走向理性
  7. gorm的零值问题:默认仅更新非零值
  8. 常用模块(数据序列化 json、pickle、shelve)
  9. cocos2d-x游戏实例(18)-纵版射击游戏(5)
  10. sonar-checkstyle plugin源码
  11. QT学习笔记(五):Qt5的8种标准对话框示例
  12. ajax post 变options,关于ajax:JQuery POST请求转换为OPTIONS。 为什么?
  13. Lubuntu16.4.3定制教程
  14. phpredis 报错 “Function Redis::setTimeout() is deprecated” 解决方法
  15. 学python语言有前途吗-在成都学Python有发展前景吗?
  16. 阶段3 2.Spring_07.银行转账案例_6 测试转账并分析案例中的问题
  17. 扫描二维码 打开 小程序或是H5网页
  18. linux只打包空目录,linux 打包当前文件夹下所有文件的方法
  19. pycharm设置文件模板
  20. 全球都在建智慧城市,智慧城市究竟什么样?中通服创立科技告诉你

热门文章

  1. 房产中介小程序版v8.1.71房产小程序 房产中介小程序 二手房小程序
  2. tws耳机哪个品牌好?双十二tws蓝牙耳机推荐
  3. 使用人人开源的代码生成器生成开发代码
  4. 宝塔邮件服务器订阅系统,宝塔服务器上搭建邮局系统#使用宝塔邮局管理器搭建私人邮局实现收发邮件功能...
  5. 智能运维之时间序列预测中的经典时序模型
  6. Unity程序化地形教程 第二期 噪声图的完善和更多细节添加
  7. SSM毕设项目煤矿应急指挥系统59d56(java+VUE+Mybatis+Maven+Mysql)
  8. xmpp_XMPP的完整形式是什么?
  9. HP1280打印机A4能打印,A3不能打印故障解决
  10. HTML5+CSS:01个人简历表