imfenghuang / blog

some notes
4 stars 0 forks source link

weex 踩坑记录 #6

Open imfenghuang opened 6 years ago

imfenghuang commented 6 years ago

全局安装 weex-toolkit

在进行这一步操作时,建议使用 npm 官方源,使用 taobao 源的话的容易出不明问题。可以使用 nrm 管理源

$ npm install -g nrm
$ nrm ls // 查看源列表
$ nrm use npm // 切换源
$ npm install -g weex-toolkit

安装 weex-debugger

安装完 weex-toolkit 之后,第一次使用 weex debug 命令时,weex 会自动检查是否已经安装了 weex-debugger,没有安装的话,会帮你自动 install。问题就出在这儿,由于墙的问题,自动 install 时, puppetter 下载不下来,报 TIMEOUT,此时,可以尝试官方推荐的做法:

$ npm config set registry https://registry.npm.taobao.org/
$ npm config set PUPPETEER_DOWNLOAD_HOST https://storage.googleapis.com.cnpmjs.org

尝试上述方法之后能安装成功的话最好,但我就遇到了意外情况:

error code ELIFECYCLE
error errno 1
error puppeteer@1.0.0 install: `node install.js`
error Exit status 1
error Failed at the puppeteer@1.0.0 install script.
error This is probably not a problem with npm. There is likely additional logging output above.

此时,进入 c:/user/用户名/.xtoolkit 目录,删除 node_modules 文件夹,然后在此目录下执行

$ cnpm install weex-debugger

等待 weex-debugger 安装完毕,再次运行 weex debug 命令,看是否安装正确。

此时,我还遇到了一些情况, weex-debugger 安装告警,缺少 babel-core 依赖,通过

cnpm install babel-core 

解决,或者,在 c:/user/用户名/.xtoolkit 建立一个 package.json 文件,添加如下代码:

{
  "dependencies": {
    "babel-core": "^6.26.0"
  }
}

之后,执行 npm installbable-core 安装完,还可以在当前目录下按需添加 .babelrc 文件

补充:2018.03.20

weex :class 不支持对象语法绑定class,使用数组语法

// 无效
<div :class="{acitve: true}"></div>

// 有效
<div :class="[ index>0 ? 'active' : 'unactive' ]"></div>

补充:2018.03.21

  1. 猜测由于受到系统(安卓,iOS)自身的限制,weex 组件部分效果在安卓和 iOS 系统上表现并不一致。比如 slider 组件使用 index :{number} 切换时,切换效果不一样。一开始在 iOS 上体验到了切换时优美地过渡,在安卓 playground 上却怎么也调试不出来,还以为自己的代码哪儿出问题了,后来才反应过来是效果本身就不一样。

  2. 今天在调试时发现,在安卓机上显示的好好的页面,在 iOS 上竟然是白屏,weex debugger 上也没有看到报错信息。之后发现是样式上少指定了 width 或者 height。对于看不到报错,但是又看不到页面的,可以在样式下排查一下,先加个背景色,看背景色是否正常显示,再调整 width height 这些样式。从目前的实践来看,不指定 width height 很容易在 iOS 上出问题。

补充:2018.03.23

  1. 在使用 sliderscroller 组件模拟制作 tab 切换时,如果使用 :index 指定 slider 到哪一帧,在安卓机上表现有问题。比如,我指定显示第三帧,当我下滑到该位置时,slider 会显示第一帧和第三帧的内容,向右滑动切换到前一帧,再向左滑动切换会第三帧,则之前出现在该位置的第一帧的内容不再显示。目前发现,这个 slider 如果时首屏出现,则没有问题,只有在非首屏出现时,且为安卓机时,有问题(playground打开页面调试看到的,app还没有测试)。不知道时 weex 的问题,还是我代码的问题,明天再看下仔细代码看。

补充:2018.04.08

1. fetch 问题

普通情况下,基于 jQuery 或者 zepto 使用 Ajax 传递数据时,默认编码是 Content-Type: application/x-www-form-urlencoded 向服务器传递数据时,会把表单数据转换成键值对,同时,请求头还会带上 x-requested-with: XMLHttpRequest ,而 weex 异步请求使用的是 Fetch,基于 Promise ,数据编码是 Content-Type: application/json,传递的是 json 字符串。 这种情况下,服务器端如果是基于 x-requested-with 来判断请求是否为 ajax 请求时,一般服务器会报修相关错误,比如 kohana 框架底层:

$this->request->is_ajax();

public function is_ajax() {
    return ($this->requested_with() === 'xmlhttprequest');
}

可以判断当前请求是否为 json 视图界面,当然,这个判断一般底层童鞋都写好了,前端童鞋可以直接调方法。 另外需要注意的是,服务器端需要对入参进行一步操作,转成键值对像。

2. tab 组件问题

因为 weex 不支持 v-show / display:none,所以,在实现 tab 组件时有一些问题,比如,每个 tab-panel 不等高,同时,每个 tab-panel 内都包含一个异步请求,绑定在 tab-panel 的 appear 事件上,此时,切换 tab 时,每个 tab-panel 的异步请求都会重新被发起。这个问题比较尴尬,暂时还没想好怎么解决。待后续解决了再来补充。

补充:2018.05.18

overflow差异

todo iOS overflow 默认是 visible 的,而安卓默认 hidden,因此在实践中,制作吸顶导航栏的时候,遇到了问题,需要在安卓端自己计算导航栏展开后的高度,并添加到外层节点上面。

children pureChilren 差异

补充:2018.06.18

min-height下flex垂直居中无效

在 iOS 下给一个 div 设置了 min-height,但是,垂直居中无法生效

.div{
    min-height: 100px;
    justify-content: center;
    align-item: center;
    flex-direction: column;
}
.text{
    display:block;
}

补充:2018.07.09

weex中使用自定义指令更新 vnode-dom

业务有图片懒加载,数据曝光上报的需求。刚开始使用修改标识符的方案,即监听图片的appear事件,默认 fe_flag 为 flase,图片的 src 为默认空白图片,当 appear 触发的时候,修改图片的 fe_flag 为 true,显示正确的图片。

<image :src="fe_flag ? imgUrl : defaultImgUrl" @appear="appearHandler"></iamge>

但是,这种方案有一个问题,即需要在每个组件内重复写上面的代码。 通过查找资料和同事讨论,决定使用自定义指令方案,全局引入 lazy-img,在需要的懒加载和数据曝光上报的地方,使用 v-lazy-img="imgUrl"。 目前遇到的问题就是 slider 组件内部嵌套的 image 的 appear 事件,无法在其自动轮播时,自动触发。

参考资料:

  1. Weex 中的 virtual-DOM 介绍 https://yq.aliyun.com/articles/59179
  2. 自定义指令 https://cn.vuejs.org/v2/guide/custom-directive.html

appear 事件不触发问题

在 slider 组件内,嵌套使用 image 组件,同时给 image 组件添加 appear 事件监听,当 slider 组件自动轮播时,image 组件上 appear 事件没有触发,需要手动上下滚动外层 list 组件,才能触发 slider 内 image 组件上的 appear 事件。

解决办法:在外层 list 里添加了一个 cell,ref 为 blank,高度为0,监听 list 的 scroll 事件获取 contentOffset.y 偏移量,并赋值给 this.$refs["blank"].scrollY = e.contentOffset.Y",监听 slider 的 change 事件,change 触发后执行 scrollToElement,滑动 scrollY+1 位置,再在 nextTick 时,滑动到 scrollY 位置。

<list @scroll="scrollHandler">
    <cell ref="blank"></cell>
</list>

scrollHandler: function (e) {
    this.$refs['blank'].scrollY = e.contentOffset.y;
},

<slider @change="changeHandler">
    <image></image>
</slider>

changeHandler: function (e){
    let _this = this,
        scrollY = _this.$root.$refs['blank'].scrollY ? _this.$root.$refs['blank'].scrollY : 1; // 第一次进来,scrollY 为 undefined,取 0 的话,安卓下有问题,自动轮播后还是无法触发appear事件,抖动无效?取 1 的话,第二张图轮播时出不来,要等到 change 到第三张的时候才能出来

    G_DOM.scrollToElement(_this.$root.$refs['blank'], {
        offset: Math.abs(scrollY) + 1,
        animated: false
    });

    this.$nextTick(function(){
        G_DOM.scrollToElement(_this.$root.$refs['blank'], {
            offset: Math.abs(scrollY),
            animated: false
        });
    })
}

补充:2018.09.04

字体对齐问题

需求里有一行文字,两种字体大小,需要底部对齐。直接使用 align-items: flex-end 并不能让文字对齐,把 line-height 设置成与 font-size 一样大,可以解决这个问题。 一般来说,行高是大于字体大小的,文字上下有一定的留白,让行高等于字体大小之后,把上下的留白给“剔除“了。 此时,如果还不能底部对齐,还可以通过 transform:translate() 或 绝对定位 进行细微调整。

补充:2018.10.17

scroll 事件

监听 <scroller>scroll 事件时,需要给对应的 <scroller> 组件指定高度,否则 scroll 事件监听无效

补充:2018.10.25

iOS 下的 <list>

<list><cell> 在移出可视区的时候,内存回收,进入可视区的时候,<cell> 内存的元素会重新初始化,如果初始化的节点过多,导致滑动的时候页面出现卡顿。因此,对于结构简单,且可复用结构较多的情况,优先使用 <list>

补充:2019.05.24

像素误差

业务中有一个列表的高度需要提前占位,使用的方法是列表 item 定高,然后计算出总高度(列表 item 数量提前已知)。实际体验下来效果 ok,但是在某些安卓手机上,某些数量下,最后一个列表 item 元素没有正常显示。排查后发现,高度不够,导致最后一个元素渲染的位置出错。为什么会这样呢? 具体分析:weex 使用 750 定宽,展示和渲染页面。而 client 设配上物理像素越来越高,375->750->1080->2k等,逻辑像素则更是鱼龙混杂,375、414、360、320等等,特别是安卓,碎片化更是严重。 这种情况下,在像素转换的时候,很容易产生小数位。这些小数位的在 client 设备上计算时,保留的位数可能不一样,有的保留2位,有的保留4位。由此导致最终的计算结果存在误差,在一定情况下,影响页面的渲染。 如何解决类似业务中的问题呢?我的解决方法如下:

height = item.height * list.num;
// 向上取整,增加高度容错
height = Math.ceil(height/weex.config.env.scale)*weex.config.env.scale;
return height;

补充:2019.07.10

min-height 单位未转化问题

业务中使用了 :style="{minHeight: computedHeight} 其中 computedHeight = '100px',一般情况下,构建之后,样式上会嵌入一层 px2rem 的计算。但是 min-height 没有。 具体原因还没定位到,初步怀疑是 render 底层对样式属性做了限制。 --> 补充: 2019.07.26

// vue-loader 内 post-css 插件的顺序,对上面单位的处理有影响
require('postcss-plugin-px2rem')({ }),
require('postcss-plugin-weex')(),

补充:2019.07.26

iOS 9 weex 0.18 sdk 在文字对齐渲染时有问题。

font-size: 18px;
line-height: 18px;
overflow: hidden

上述样式渲染出来的文字(中文),顶部可能会被遮挡掉一部分,而weex web(webview)下是正常的

imfenghuang commented 4 years ago

补充:2020.06.30

使用自定义字体时,注意引号

// error
p {
    font-family: 'aaa-big';
}

// right
p {
    font-family: aaa-big;
}
const DOM = weex.requireModule('dom');
DOM.addRule('fontFace', {
    fontFamily: 'aaa-big',
    src: 'xxx'
});