微信小程序WXS之谜【10bet】

来源:http://www.chinese-glasses.com 作者:Web前端 人气:167 发布时间:2020-04-29
摘要:时间: 2019-09-14阅读: 592标签: 小程序 微信创造了 WXS ,除了提高性能,还有什么原因? 管道.jpeg 微信为何要创造 WXS 由于微信小程序 技术生态比较闭合,导致很多现代前端框架很多积累

时间: 2019-09-14阅读: 592标签: 小程序

10bet 1

微信创造了 WXS ,除了提高性能,还有什么原因?

管道.jpeg

微信为何要创造 WXS

由于微信小程序 技术生态比较闭合,导致很多 现代前端框架很多积累出的成果都没有实现(可能未来会逐一实现). 用惯了现代 再耍小程序 总感觉很不顺手.

WXS(WeiXin Script)是微信创造的一套脚本语言,它的官方说法是:“WXS 与 JavaScript 是不同的语言,有自己的语法,并不和 JavaScript 一致”。

需要结果的请直接看最后的WXS

那微信为何要脱离 JavaScript ,单独创造一套语言呢?这要从微信小程序的底层逻辑(运行环境)讲起。小程序的运行环境分为逻辑层和视图层,分别由 2 个线程管理,其中:

View Filter

filter 理解为管道加工处理, 你扔给我一组数据 经过各种不同类型的管道加工 产出新的数据 但是又不会影响修改原数据, 最终展示给用户.

现有前端框架filter一般:

 time | dateTime('yyy-mm-dd')

使用 | 作为管道符 传递参数进行序列化

WXML模板和WXSS样式工作在视图层,界面使用WebView进行渲染。JavaScript 代码工作在逻辑层,运行在 JsCore 或 v8 里。

缺陷:

截止目前,小程序官方并没有管道实现方式,以下列出了替代几种方案,供大家选择使用.

小程序在视图层与逻辑层两个线程间提供了数据传输和事件系统。这样的分离设计,带来了显而易见的好处:逻辑和视图分离,即使业务逻辑计算非常繁忙,也不会阻塞渲染和用户在视图层上的交互。

直接修改原数据

在请求完成之后 对返回值data进行一次数据处理 比如 抽象一个_formatListData方法对 返回进行二次处理.

 _formatListData(list) {
     return list.map((item) => {
          let date = FormatUtil.getDateTime(item.childBirth);
          item.filterChildBirth = `${date.y}-${date.M}-${date.d}`;
      return item;
    }
}

这种方式会给原数据添加新字段 filterChildBirth (原字段为 childBirth) . 最终展示也是显示filterChildBirth 到view上面,多个需要filter的字段都通过这种方式去处理,很明显 对一些业务型filter倒还好 如果遇到filter需要 共享 就比较坑.

但同时也带来了明显的坏处:视图层(webview)中不能运行 JS,而逻辑层 JS 又无法直接修改页面 DOM,数据更新及事件系统只能靠线程间通讯,但跨线程通信的成本极高,特别是需要频繁通信的场景。

ES6 get

data : {
  time : 1511748300571
}

 get time (){    
  return FormatUtil.getDate(this.data.time);
}

通过get方法来实现对字段显示过滤. 只能操作对象 对数组中的item 比较无力.

什么是需要频繁通讯的场景?最典型的例子就是用户持续交互的情况,比如触摸、滚动等。我们以侧滑菜单为例,假设在页面上滑动 A 元素,要求 B 元素跟随移动,一次滑动操作(touchmove)的响应过程如下:

WXS

微信小程序的架构分为 app-service 和 page-frame,分别运行于不同的线程。你在开发时写的所有 JS 都是运行在 app-service 线程里的,而每个页面各自的 WXML/WXSS 则运行在 page-frame 中。app-service 与 page-frame 之间通过桥协议通信(包括 setData 调用、canvas指令和各种DOM事件),涉及消息序列化、跨线程通信与evaluateJavascript()。这个架构的好处是:分开了业务主线程和显示界面,即便业务主线程非常繁忙,也不会阻塞用户在 page-frame 上的交互。一个小程序可以有多个 page-frame (webview),页面间切换动画比SPA更流畅。坏处是:在 page-frame 上无法调用业务 JS。跨线程通信的成本很高,不适合需要频繁通信的场景。业务 JS 无法直接控制 DOM。
作者:鲁小夫
链接:https://www.zhihu.com/question/64322737/answer/223446446

了解了wxs 设计初衷,我们也就知道能做什么事情了.
wxs 目前主要是增强 wxml 标签的表达能力

ps : 因为运行在不同线程所以 js与wxs 不能相互引用的. 这就有可能在js中使用公共方法 在wxs中需要重新写一份(为了共享filter) 造成代码冗余.

通过wxs 实现共享filter:

  1. 首先我们建立共享filter文件夹,实现一个日期格式化
![](https://upload-images.jianshu.io/upload_images/326507-b29a1af47d4c2feb.png)

image.png
  1. WXS 实现日期格式化(es6语法不能使用)

     var DateFr = {
    
      getDate: function (time, splitStr) {
    
     if (!time) return '';
    
     var date =getDate(time);
     var M = date.getMonth() + 1;
     var y = date.getFullYear();
     var d = date.getDate();
    
     if (M < 10) M = "0" + M;
     if (d < 10) d = "0" + d;
    
     if (splitStr)
       return y +splitStr + M +splitStr+d;
     else
       return {
         y: y,
         M: M,
         d: d
       };
       }
     }
    
     module.exports = {
       getDate: DateFr.getDate
     }
    
  2. 在业务页面wxml中引用wxs

       <wxs module="dateFr" src="../../../../filter/dateFr.wxs"></wxs>
    

    使用filter

        <text >{{dateFr.getTime(item.createdAt,':')}}</text>
    

touchmove 事件从视图层(Webview)传递到逻辑层,中间会由微信客户端(Native)做中转。

结尾

wxs 基本满足filter的场景:
共享filter场景 采用3
业务filter很多场景 采用1,3
简单业务filter 数据非数组型场景 采用2
小程序还有很长的路要走,仍需继续努力.

逻辑层处理touchmove事件,计算需移动的位置,然后再通过setData传递到视图层,中间同样会由微信客户端(Native)做中转。

一次touchmove的响应需要经过 视图层、Native、逻辑层三者之间 2 个完整来回的通信,通信的耗时开销较大,用户的交互就会出现延时卡顿的情况。

除了滚动、拖动交互外,在 for 循环里对数据做格式修改,也会造成逻辑层和视图层频繁通讯。

本文由10bet发布于Web前端,转载请注明出处:微信小程序WXS之谜【10bet】

关键词:

最火资讯