热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

谜之wxs,uniapp如何用它大幅提升性能

小程序里有几个谜一样的存在,微信的WXS、支付宝的SJS、百度的Filter。很多开发者都不明白为什么要造这种语言脚本的轮子出来,甚至很多开发者根本不

小程序里有几个谜一样的存在,微信的WXS、支付宝的SJS、百度的Filter。

很多开发者都不明白为什么要造这种语言脚本的轮子出来,甚至很多开发者根本不知道它们的存在。

其实几大小程序平台创造它们,都是为了解决性能问题,但不得不吐槽下,设计的实在是很难用,文档也语焉不详。

uni-app支持将WXSSJSFilter编译到这3家小程序平台,同时还在App和H5实现了WXS的解析。为什么做这些事?也是为了性能。

uni-ui库新版中的swiperaction组件,就是列表项向左滑动时拉出几个挤压式联动的菜单按钮,这种流畅的跟手动画,正是借助于WXS机制实现的。

微信为何要创造WXS

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

那微信为何要脱离 Javascript ,单独创造一套语言呢?这要从微信小程序的底层逻辑(运行环境)讲起。

小程序的运行环境分为逻辑层和视图层,分别由2个线程管理,其中:

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

小程序在视图层与逻辑层两个线程间提供了数据传输和事件系统。这样的分离设计,带来了显而易见的好处:

  • 逻辑和视图分离,即使业务逻辑计算非常繁忙,也不会阻塞渲染和用户在视图层上的交互

但同时也带来了明显的坏处:

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

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

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

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

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

其实这类通信损耗问题,在业内由来已久,react native和weex都有类似问题,weex提供了bindingx来解决。

但对于小程序来讲,这类问题解决起来更容易。其实视图层的webview,是有js环境的,只不过过去不给开发者开放。

如果在视图层的js直接处理滚动或拖动交互、直接处理数据格式,就能避免大量通信损耗。

但对于小程序平台而言,大量开放webview里的js编写,违反了它的初衷,比如开发者会直接操作dom,影响性能体验。所以小程序平台提出一种新规范,限制webview里可运行的js的能力。这就是wxs、sjs、filter的由来。

从本质来讲,wxs、sjs、filter是一种被限制过的、运行在视图层webview里的js。它并不是真的发明了一种新语言。

WXS特征及适用场景

WXS具备如下特征:

  • WXS是可以在视图层(webview)中运行的JS
  • WXS无法修改业务数据,仅能设置当前组件的classstyle
  • WXS是被限制过的Javascript,可以进行一些简单的逻辑运算
  • WXS可以监听touch事件,处理滚动、拖动交互

故可以得出WXS的适用场景,主要包括:

  • 用户交互频繁、仅需改动组件样式(比如布局位置),无需改动数据内容的场景,比如侧滑菜单、索引列表、滚动渐变等
  • 纯粹的逻辑计算,比如文本、日期格式化,通过WXS可以模拟实现Vue框架的过滤器,如下是一个通过wxs便捷实现首字母大写的示例:

//首字母大写var capitalize = function(value) {if (!value) return ''value = value.toString()return value.charAt(0).toUpperCase() + value.slice(1)}module.exports = {capitalize: capitalize}

{{m1.capitalize(title)}}


uni-app如何支持WXS

uni-app遵循Vue单文件组件(SFC)规范,组件/样式/脚本是写在一个.vue文件中的,但微信小程序是多文件分离(wxml/wxss/js/json)的,所以在微信端的主要工作是扩展vue-template-compiler,解析template/style/script节点,并正确生成到对应的wxml/wxss/js文件中,具体编译工作如下图:

Tips-1:关于标签重构为

  1. 在 wxs 文件中,处理 touch 事件逻辑,通过 translateX 移动元素位置

function touchstart(e, ins) {//记录开始位置及动画状态var pageX = e.touches[0].pageX;....
}function touchmove(e, ownerInstance) {var instance = e.instance;var pageX = e.touches[0].pageX;//获取当前移动位置//计算偏移位置var x = Math.max(-instance.getState().position[1].width, Math.min((value), 0));//设置左侧元素移动位置instance.setStyle({transform: 'translateX(' + x + 'px)'}) //循环右侧挤压式联动菜单var btnIns = ownerInstance.selectAllComponents('.button-hock');for (var i = 0; i }function touchend(e, ownerInstance) {var instance = e.instance;var state = instance.getState()//根据当前移动位置,实现菜单项的自动展开或回弹move(state.left, -40, instance, ownerInstance)
}

该示例的完整源码参考github

更多平台的兼容性

uni-app的App端也是一个小程序引擎,所以想要在App端实现流畅的跟手拖动,也需要实现类似wxs的机制。

其实H5平台倒不存在逻辑层和视图层通讯折损的问题,但为了平台兼容性拉齐,uni-app在H5端也实现了wxs机制。

这样编写wxs代码,在uni-app中可同时运行在App端、H5端、微信小程序端。

因百度小程序的Filter过滤器、支付宝小程序的SJS和微信小程序的WXS在语法上差异较大,uni-app只支持单独编写百度小程序的Filter过滤器和支付宝小程序的SJS,这两种脚本无法跨多端,仅支持自有平台。开发者若需使用,可分别编写wxs/filter/sjs脚本,然后依次通过script引用,uni-app编译器会根据目标平台,分别编译发行,如下为示例代码:
示例代码要有条件编译








后续

用运行在视图层的js解决通讯阻塞,可能很多人都没意识到。希望本文能给大家解惑,解开WXS之谜。

其实小程序的性能体验优化,仍然有大量空间。DCloud团队在这个领域研究了6年,清楚当前的优势,也清楚当前的问题。我们会继续分享这些问题及对应的解决方案,为小程序产业发展贡献力量。

本文涉及的uni-uiswiperaction组件,代码开源在https://github.com/dcloudio/uni-ui,uni-app框架代码开源在 https://github.com/dcloudio/uni-app,欢迎大家 star 或提交 pr。


推荐阅读
  • 技术周报·2021-05-07-小编推荐向现代Javascript转型原文标题:Publish,ship,andinstallmodernJavaScriptforfaste ... [详细]
  • Android Studio Bumblebee | 2021.1.1(大黄蜂版本使用介绍)
    本文介绍了Android Studio Bumblebee | 2021.1.1(大黄蜂版本)的使用方法和相关知识,包括Gradle的介绍、设备管理器的配置、无线调试、新版本问题等内容。同时还提供了更新版本的下载地址和启动页面截图。 ... [详细]
  • 本文介绍了RPC框架Thrift的安装环境变量配置与第一个实例,讲解了RPC的概念以及如何解决跨语言、c++客户端、web服务端、远程调用等需求。Thrift开发方便上手快,性能和稳定性也不错,适合初学者学习和使用。 ... [详细]
  • 本文介绍了RxJava在Android开发中的广泛应用以及其在事件总线(Event Bus)实现中的使用方法。RxJava是一种基于观察者模式的异步java库,可以提高开发效率、降低维护成本。通过RxJava,开发者可以实现事件的异步处理和链式操作。对于已经具备RxJava基础的开发者来说,本文将详细介绍如何利用RxJava实现事件总线,并提供了使用建议。 ... [详细]
  • Java和JavaScript是什么关系?java跟javaScript都是编程语言,只是java跟javaScript没有什么太大关系,一个是脚本语言(前端语言),一个是面向对象 ... [详细]
  • 从零基础到精通的前台学习路线
    随着互联网的发展,前台开发工程师成为市场上非常抢手的人才。本文介绍了从零基础到精通前台开发的学习路线,包括学习HTML、CSS、JavaScript等基础知识和常用工具的使用。通过循序渐进的学习,可以掌握前台开发的基本技能,并有能力找到一份月薪8000以上的工作。 ... [详细]
  • 恶意软件分析的最佳编程语言及其应用
    本文介绍了学习恶意软件分析和逆向工程领域时最适合的编程语言,并重点讨论了Python的优点。Python是一种解释型、多用途的语言,具有可读性高、可快速开发、易于学习的特点。作者分享了在本地恶意软件分析中使用Python的经验,包括快速复制恶意软件组件以更好地理解其工作。此外,作者还提到了Python的跨平台优势,使得在不同操作系统上运行代码变得更加方便。 ... [详细]
  • 本文介绍了JavaScript进化到TypeScript的历史和背景,解释了TypeScript相对于JavaScript的优势和特点。作者分享了自己对TypeScript的观察和认识,并提到了在项目开发中使用TypeScript的好处。最后,作者表示对TypeScript进行尝试和探索的态度。 ... [详细]
  • Vue基础一、什么是Vue1.1概念Vue(读音vjuː,类似于view)是一套用于构建用户界面的渐进式JavaScript框架,与其它大型框架不 ... [详细]
  • 腾讯T3大牛亲自教你!2021大厂Android面试经验,经典好文
    本篇将由环境搭建、实现原理、编程开发、插件开发、编译运行、性能稳定、发展未来等七个方面,对当前的ReactNative和Flutter进行全面的分析对比, ... [详细]
  • Android中高级面试必知必会,积累总结
    本文介绍了Android中高级面试的必知必会内容,并总结了相关经验。文章指出,如今的Android市场对开发人员的要求更高,需要更专业的人才。同时,文章还给出了针对Android岗位的职责和要求,并提供了简历突出的建议。 ... [详细]
  • 本文介绍了Python爬虫技术基础篇面向对象高级编程(中)中的多重继承概念。通过继承,子类可以扩展父类的功能。文章以动物类层次的设计为例,讨论了按照不同分类方式设计类层次的复杂性和多重继承的优势。最后给出了哺乳动物和鸟类的设计示例,以及能跑、能飞、宠物类和非宠物类的增加对类数量的影响。 ... [详细]
  • React基础篇一 - JSX语法扩展与使用
    本文介绍了React基础篇一中的JSX语法扩展与使用。JSX是一种JavaScript的语法扩展,用于描述React中的用户界面。文章详细介绍了在JSX中使用表达式的方法,并给出了一个示例代码。最后,提到了JSX在编译后会被转化为普通的JavaScript对象。 ... [详细]
  • 随着前端技术的发展,越来越多的开发者开始使用react、vue等web框架,但很少有人深入理解这些框架的源码。然而,这些框架底层都是由原生的javascript构建而成。对于初学前端的人来说,可能会认为javascript很容易上手,但实际上只是因为它被高度封装了。与能够使用封装类的人相比,能够理解框架原理的人则处于另一个层面。本文将深入剖析jquery源码,探寻框架底层的原理,帮助读者更好地理解web框架的运行机制。 ... [详细]
  • v8对象机制1.概述v8中每一个API对象都对应一个内部实现对象(堆对象)2.对象创建过程(1)v8::internal::Factory类: ... [详细]
author-avatar
我才是陈墨_773
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有