Scene:

When making the effect of a ball moving with fingers, setData is frequently called in the Touchmove event to change the displacement of the ball, which is smooth in the development tools and IOS platform, but extremely slow interaction appears in the mobile phone preview under Android, which is simply unnoticeable.

Can open WeChat web developer tools segment code https://developers.weixin.qq.com/s/B9UHyvmo7t6t

Root cause:

SetData calls up to 50 or so per second. To quote the official:

A. Throw touchMove event from Webview layer to Logic layer (App Service)

B. The logic layer (App Service) processes the TouchMove event and changes the position of the component through setData

The response of a Touchmove needs to go through two communications between the logic layer and the rendering layer and one rendering, which takes a lot of time. In addition, setData rendering blocks other script execution, resulting in a delay in the animation process of the entire user interaction.

How to optimize?

1. Use the movable – view

The movable-view + movable-area effect is smooth, but it also has limitations and cannot meet complex requirements. For example, the current requirement is that two balls can control the movement of the balls with two fingers at the same time, which cannot be achieved, and it needs to be realized with setData. The use of setData is bound to stall

2. Recommended solution: Discard setData and use WXS to write interactions

From base library 2.4.4 to support WXS response to events directly on the code, I am a newcomer, code writing is very chaotic:

index.js

const app = getApp()

Page({
  data: {
    balls: [1, 2, 3, 4, 5, 5, 6, 7]
  }
})

Copy the code

index.wxml

// Import WXS file < WXS module="index" src="./index.wxs"></wxs>
<view class='wrap' catchtouchstart='{{index.touchstart}}' catchtouchmove='{{index.touchmove}}' catchtouchend='{{index.touchend}}'>
  <view class="demo hide" wx:for="{{ balls }}"></view>
</view>

Copy the code

index.wxs

var allTouchs = [], len = 0, instances = [], instanceLen, isMoveEnd = false


functionReset (ownerInstance) {// Resetfor (var i = 0; i < instanceLen; i++) {
    instances[i].setStyle({
      'transform': ' '.'display': 'none'}}})function touchstart(event, ownerInstance) {
  if (isMoveEnd) returnBoundsLen = boundsLen = event.touches, len = event.touches.length instances = ownerInstance.selectAllComponents('.demo'), instanceLen = instances.length

  for (var i = 0; i < instanceLen; i++) {
    var instance = instances[i], bound = bounds[i]

    if(I < boundsLen) {// Update instance.disabled =false
      instance.identifier = bound.identifier
      instance.setStyle({
        'transform': 'translateX(' + bound.pageX + 'px) translateY(' + bound.pageY + 'px)'.'display': 'block'})}else {
      instance.setStyle({
        'transform': ' '.'display': 'none'
      })
      instance.disabled = true
      instance.identifier = ' '}}}functionTouchmove (event, ownerInstance) {var bounds = event. ChangedTouches, boundsLen = bounds.length, bound = null, instance = null, allTouch = nullfor (var i = 0; i < instanceLen; i++) {
    instance = instances[i]
    for (var j = 0; j < boundsLen; j++) {
      bound = bounds[j]
      if(instance.identifier === bound.identifier) {// Update instance.setstyle ({instance.identifier === bound.identifier) {'transform': 'translateX(' + bound.pageX + 'px) translateY(' + bound.pageY + 'px)'.'display': 'block'})}}}}function touchend(event, ownerInstance) {
  isMoveEnd = trueBoundsLen = bounds. Length, bound = null, instance = null, allTouch = nullfor (var i = 0; i < instanceLen; i++) {
    instance = instances[i]
    for (var j = 0; j < boundsLen; j++) {
      bound = bounds[j]
      if(instance.identifier === bound.identifier) {// Update instance.setstyle ({instance.identifier === bound.identifier) {'transform': ' '.'display': 'none'}) // Remove instances[I]. Disabled =true
        instances[i].identifier = ' '
      }
    }
  }

  var tmp = instances.filter(function (item) {
    return! item.disabled })if(tmp.length < 1) {// reset reset(ownerInstance)} isMoveEnd =false
}
module.exports = {
  touchmove: touchmove,
  touchend: touchend,
  touchstart: touchstart
}
Copy the code

WeChat web developer tools to open the small program code snippets at https://developers.weixin.qq.com/s/wLxQuwm1786m

The instance object supports the following methods:

The official documentation

After the real machine test, there is no stuck effect

Matters needing attention

Official bug:

1. WXS cannot use ES6+ syntax, otherwise an error will be reported.

2. Console.log () cannot print objects directly, requires json.stringify

3. Of course, methods and wx.xxxx methods in app Service environment cannot be called