Weex 开发 [Weex]
前几天看知乎,Evan You 叫 Weex 作 Vue-Native😊
本文主要学习如何使用 Weex 常用组件进行开发工作,再根据开发过程中遇到的问题,完善补充。
Tips
不支持相对单位
em,rem等,只能使用px;不支持
css组合写法,只能设置一个属性值,如border: 1 solid red;<image>在ios平台border不支持设置不同的radius;不支持百分比
根布局必须是
<div>、<scroller>事件最好定义成有意义的形式,不然有时会出问题,例如
@change="change"监听change事件没问题,但是@scroll="scroll"就会出现监听不到的问题。标签属性一定要写成标签属性的形式
porperty=value,不能用css属性代替,有些属性在Android上面支持,但是在ios那边不支持。当不是根元素的
div嵌套列表时,比如list,列表在ios上无法显示出来,要显式的指定div的高度,有点类似两个可滑动的组件套在一起,无法测量高度的情况。使用
:style支持动态设置多个属性时,如果值带有单位,则一定要使用''包含,中间以逗号分隔,如:style="{width:'750px',color:red,height:height+'px'}"
盒模型
Weex 盒模型的 box-sizing 默认为 border-box,即盒子的宽高包含内容、内边距和边框的宽度,不包含外边距的宽度。
width/height - 指的是 content + padding + border 部分的尺寸
1 | .frame{ |
padding - 内边距,content 和 border 之间的距离
1 | .frame{ |
margin - 外边距,元素与元素之间的距离
1 | .frame{ |
border - 边框
1 | .frame{ |
FlexBox
flexbox 是 CSS3.0 新的布局模式,Weex 对它进行了部分的支持。
flexbox 是唯一的默认的布局模式,不需要指定 display: flex;,默认所有的容器类元素都是 flex 容器。
布局方向
1 | .frame{ |
主轴方向元素的排列
1 | .frame{ |
侧轴方向元素的排列。
1 | .frame{ |
flex 成员项
flex 属性定义了 flex 成员项可以占用容器中剩余空间的大小。如果所有的成员项设置相同的值 flex: 1,它们将平均分配剩余空间. 如果一个成员项设置的值为 flex: 2,其它的成员项设置的值为 flex: 1,那么这个成员项所占用的剩余空间是其它成员项的 2 倍。
1 | .frame{ |
pseudo
主要支持 active,focus,enabled,disabled。所有组件支持 active,只有 input 和 textarea 支持 focus。
在客户端中,active 表示组件被按压时的状态,focus 表示组件获取到焦点时的状态,enabled 表示可用时的状态,disable 表示不可用时的状态。
在 ios 上,enable 没有效果。
优先级:
1 | active > focus > enable |
div
不可嵌套层级过深,控制在 10 层以内,避免性能问题;
不能在 div 中直接写文字,需要使用 <text> 组件;
即使高度超出范围 div 也不能滑动;
web
不支持 click 和 longpress 事件
标签属性
1 | // 加载的地址 |
事件,event 里面内容很多
1 | // 页面开始加载 |
video
内部只能包含 <text> 标签
标签属性
1 | // 播放地址 |
事件
1 | // 每次开始播放,自动播放或者暂停后播放都会触发 |
switch
标签属性
1 | checked = true // 是否选中 |
文档中提到,下面的样式不能使用,测试发现,width/height、margin、border 这些属性都是可以使用的,不过确实有部分属性在 ios 上面没有效果。
1 | width |
事件
1 | // 状态切换时触发 |
A
它是一个容器类的标签,看 Android 这边的源码,是继承自 div 标签,a 和 html 里面的 a 标签差不多,但是不能包含文本,如果要有文本需要使用 <text> 标签。
点击之后会调用一个名为 event 的 module 的 openURL 方法,这个 module 需要我们来注入到 sdk 中,参数就是 href。
1 | <a class="button" href="http://g.tbcdn.cn/ali-wireless-h5/res/0.0.16/hello.js"> |
image
「image」标签用来显示图片,必须指定 width 和 height,否则无法显示,不能包含子组件,
标签属性
1 | // 显示的图片地址 |
事件
1 | // 图片加载成功监听 |
方法
1 | // 将图片保存到本地 |
text + input + textarea
文本样式汇总
1 | .mytext { |
「text-decoration」,已经支持前后带有空格显示,当带有空格时,如果加了 decoration,在 android 上面空格的地方也会有装饰,ios 只会在文字的地方有。
「font-family」,在生命周期方法 beforeCreate 为页面加载一套字体
1 | beforeCreate() { |
text
组件 text 具有 value 属性,用来表示显示的值,当 value 和内容都指定时,将会显示内容的值。
1 | <text class='mytext' value="test1"> test2 </text> |
input
组件 input 标签属性,需要注意的是如果标签中间写了文案,会显示在组件下方。
1 | maxlength = 10 // 可以输入的最长长度 |
伪类
1 | .myinput:active { |
支持的 css 属性
1 | 同样支持 color,font-size,fone-weight,font-style,text-align 属性 |
事件
1 | @input 输入监听,每次输入内容变化,会调 |
方法,为 input 组件设置 ref="input_ref"
1 | var el = this.$refs["input_ref"]; |
textarea
多行文本输入 textarea 和 input 基本类似,
他们俩的差别:
事件上,textarea 不支持 @return 事件
方法上, 均支持
标签属性上,增加了 rows 属性,不支持 return-key-type,max-length,type,支持的属性汇总如下:
1 | rows = 3 // 指定组件的高度,默认2 |
slider + indicator
slider 默认高度会占满屏幕,所以必须为 slider 指定一个高度,而 indicator 也会继承这个高度。
1 | <slider class="slider" interval=3000 auto-play=true infinite=true @change="changePage" @scroll="scrollSlider "> |
slider 标签属性
1 | interval = 3000; // 播放时间间隔 |
slider css 属性
1 | .slider{ |
indicator 常用属性
1 | .indicator{ |
事件
1 | // change 事件,当页面滑动到下一页时触发 |
scroller
对客户端来说是不可复用元素的列表
滑动方向 - 可以垂直或者水平滑动,flex 和 scroll 的方向必须一致。
1 | 两者方向必须一致 |
实现一个 tab 导航
1 | <scroller class="scroller" scroll-direction=horizontal @scroll='scrollerScroll'> |
常用标签属性,同样支持一些列表统一的标签属性 列表标签属性
1 | // 滑动方向,默认 vertical |
支持 loadmore 事件,见 列表 loadmore
支持 scroll 事件,见 列表 scroll
支持 resetLoadmore,见 列表 resetLoadmore
支持 scrollToElement,见 列表 scrollToElement
list + waterfall + cell + header
把他们放在一起是因为他们一起完成了一个列表的显示,其实 waterfall 和 list 是一样的, 类似 Android 上面当年的 ListView 和 GridView,当然现在都已经被 RecyclerView 代替了,他们表现的都是一个 垂直列表,而 waterfall 支持多列的显示,
使用 cell 生成列表的每一项,header 其实是 cell 的子类,它可以在滑动出屏幕时,固定在屏幕顶端,实现悬挂的效果。
列表中只支持 cell 、header、refresh、loading 和 使用 fix 定位的组件,其他组件不能正确渲染。
实现一个简单的列表显示,需要格外注意的是,v-for 的语句要写在 cell 上面,这样才能保证生成多个 cell,开始的时候我写在了 div 上面,其实是在一个 cell 里面生成了多个 div,这样就无法实现回收和复用。
1 | <list style="height:500px;" @loadmore="loadmorelist"> |
header
这个 header 用起来坑比较多,汇总一下:
- 在
list里面用header,默认是一样悬挂效果,就是当header向上将要被滑出屏幕时会固定在屏幕顶端,但是向下滑出时不会固定在底端。 list里面header上面的cell不能全部使用v-for生成,如果是的话,对header没有挤压效果,header会一直在顶部,就好像v-for生成的那些cell没有压在header上面,但是一旦有一个不是v-for生成的,就好了,这应该是个bug;waterfall里面使用header时,默认是没有悬挂效果的,会像普通的cell一样跟着整个列表一起走,这样可以实现单列和多列并存的效果。- 如果希望
waterfall里面有悬挂效果,要对header设置position:sticky;,使用这个属性,他不会滑出屏幕,不管上面还是下面都会挂住。 - 在
list中使用sticky没什么效果,在waterfall中一方面可以使用sticky对header做悬挂效果,另一方面cell如果设置了sticky会变成跨越正行,类似header
使用 header 标签实现悬挂效果
<header/> 标签是 list 可以渲染的标签之一,当 header 到达顶部时,会吸附在屏幕顶部,<header/> 不一定要在顶部,可以在列表的任何位置,当这一项,被滑动到顶端时,会吸附在顶部,不会划出屏幕。
ps:同样的效果,如果在 cell 上面使用 position:fixed; 在 Android 可以正确显示,但是在 ios 没有任何效果
使用方法很简单,只需要将某一项使用 <header> 包含即可。
1 | <list> |
waterfall
👮如果是一个 list 套在 div 里面显示没问题,但是如果是 waterfall 就不行,看到有报错说无法解析 auto,当然设置成固定值也不行,解决方案是给 waterfall 一个固定的宽度,让他可以计算,就没问题了。
瀑布流 waterfall 支持多列显示,因此相比 list 多了一些属性,但是 list 的属性和事件他也是支持的。
「waterfall」 特有属性,column-width 和 column-count 不能同时指定为 auto 无法计算将无法显示。
1 | 当某个属性指定为 auto 时,会使用下面的约束来计算 auto 对应的值。 |
common
「waterfall 和 list」 常用属性 - 支持列表统一的标签属性 列表标签属性
「waterfall 和 list」 支持 loadmore 事件,见 列表 loadmore
「waterfall 和 list」 支持 scroll 事件,见 列表 scroll
「waterfall 和 list」 支持 resetLoadmore,见 列表 resetLoadmore
「waterfall 和 list」 支持 scrollToElement,见 列表 scrollToElement
列表
在 weex 指的就是 scroller 和 list 了,这里汇总一些公共的属性和方法,方便管理和对比。
类似 scroller 和 list 都属于列表,他们有一些通用的属性和方法,提取出来统一介绍,⚠️ 不允许相同方向的列表互相嵌套
列表标签属性
1 | // 屏幕底部到页面底部的距离,用来触发 loadmore,默认 0 |
列表事件
1 | @loadmore 加载更多事件,横向滑动时,`loadmore` 不能触发 |
方法
resetLoadmore(node,options)
重置 loadmore,如果进行过一次 loadmore 之后,列表内容没有发生变更,则再次滑动到末尾时,不会触发 loadmore 事件,需要使用 resetLoadmore() 来重置状态。
1 | scroller.resetLoadmore(node,options) |
scrollToElement(node,options)
使得列表滑动到指定的 node,需要使用 dom module 来操作
ps:使用过程中发现 waterfall 组件的 scrollToElement 在 andorid 上是将指定项滚动到屏幕底部,ios 是滚动到顶部,list 和 scroller 正常,都是到顶部。
1 | scrollToElement(node,options) |
示例,对一个横向列表进行操作,使得点击的那个子元素自动滑动到居中显示
1 | <scroller class="scroller" scroll-direction='horizontal'> |
在 click 事件中,滑动 scroller
由于我每一个子项的宽度设置为了 150px,而 weex 默认屏幕是 750px,一次屏幕内正好可以放置 5 个子项,距离左边 300px 即可居中。
1 | changeTab(index){ |
refresh + loading
使用 refresh 和 loading 实现加载数据的效果,refresh 是下拉刷新数据,loading 是上拉加载更多数据,他们只有在被 list 和 scroller 包含时才能正确渲染,接下来将会以 list 为例简单学习一下使用方法,在 scroller 是一样的。在用法上,refresh 和 loading 也基本相同,只是显示的位置不同和一些事件名字不同。
「diaplay」属性来决定组件的展示和隐藏,display 值为 show 或 hide。仅隐藏 <indicator>,<loading> 其他子组件依然可见,loading 事件仍会被触发,因此我们要实现刷新的效果需要动态的修改 display 的值。
1 | <refresh :display="isRefreshing?'show':'hide'"></refresh> |
「<loading-indicator>」 是内置一个组件,显示是一个带动画效果的圆形进度条,就是系统默认的加载动画,需要注意的是宽高必须指定,不然默认是0无法显示,可以使用 color 属性来更改进度条的颜色。
1 | <loading-indicator style='color:red;width:40px;height:40px;'></loading-indicator> |
事件,<refresh> 有 @refresh 事件,<loading> 有 @loading 事件,他们都会在滑动距离超过整个组件的高度时被触发,可以在这里面做加载数据的操作。
另外 <refresh> 还有一个自己的事件,@pullingdown 事件会返回组件滑动过程中的一些数据,不过这个监听在 andorid 和 ios 上面的数据差别比较大。
1 | event => |
完整的带有刷新和加载功能的代码
1 | <list> |
默认 isFreshing 和 isLoading 自然都是 false,当刷新时,更改组件的状态为显示,开始加载数据,并且延时 1s 后将组件隐藏。
1 | refreshList(){ |
config
文档说明使用 weex.config 获取,但是测试发现不行,需要使用 this.$getConfig() 获取到,调查发现 weex.config 需要 weex 版本 >=0.9.5 才可以,而我使用官方的 playground 版本是 0.9.4。
默认以宽度为 750px 做适配渲染,要获得 750px 下的屏幕高度,可以通过 height = 750/deviceWidth*deviceHeight 公式获得,可以使用到 CSS 中,用来设置全屏尺寸。
数据结构:
1 | config |
目前维护的几个项目,求 ✨✨✨✨
- SocialSdk 登录分享功能原生接入
- LightAdapter 轻量级适配器
- ImageEditor 图片处理,裁剪旋转,贴纸涂鸦,滤镜等
- WeexCube Weex 容器方案
- Kotlin 学习系列总结,共计 22 篇
- 本文链接: http://cdevlab.top/article/41ed2d2f/
- 版权声明: 版权所有,转载请注明出处!