使用wxs优化拖动效果实战总结

下面是一个真实的项目场景:需要选中一张图中的某个图案或文本,对其进行放大缩小并将它移动个位置。

                        拖动前                                                  选中状态                                         拖动后                                  

                                                              

最终效果

做这个事,有几个JS事件可以帮到我们 

  • touchstart: 拖动前的点击选中事件,这个事件可能需要和tap事件和进行下区别 ,经实际测试如果在一个view中同时捕获tap和touchstart事件,如:<view catchtap='tap' catchtouchstart='touchatart'>  </view>,则只会触发touchart事件
  • touchmove:  选中后鼠标不松开会触发此事件
  • touchend:选中移动并松开后会触发此事件
 
在处理过程中,比如在拖动过程中会产生大量touchmove事件导致页面不断渲染,会有明显的卡顿现象出现,

所以这里我们需要用到WMS这个技术来处理移动事件。
 

个人感觉用WXS的时候注意以下几点:

   1. 不要让WXS过多参与业务,发挥它的优势,只要它解决渲染性能问题

   2. 如何向WMS传送参数

   3. 如何让WMS和JS 进行交互

下面是解决拖动效果的WMS代码,文件名为move.wxs

var startX = 0
var startY = 0
var lastLeft = lastTop = 0
var flag 
var target_id ,target_top,target_left,target_width,target_height; 
var canvas_width = 200, canvas_height = 350 ;
var hRatioH ;
var stop = false 

function touchstart(event, ins) {
   
  // stop = false;
  var touch = event.touches[0] || event.changedTouches[0]
  startX = touch.pageX
  startY = touch.pageY

  var flag = false ;
  if( event.target.dataset.targetid != target_id){
     flag = true; 
  }
  
  target_id = event.target.dataset.targetid; 
  target_top = event.target.dataset.targettop; 
  target_left = event.target.dataset.targetleft;
  target_width = event.target.dataset.targetwidth ;
  target_height = event.target.dataset.targetheight;
  hRatioH = event.target.dataset.hratioh ;
  canvas_width = event.target.dataset.canvasw;
  canvas_height = event.target.dataset.canvash; 
  if(flag){
    lastLeft = target_left
    lastTop = target_top
  }

}



function touchmove(event, ins) {
  var touch = event.touches[0] || event.changedTouches[0]
  var pageX = touch.pageX
  var pageY = touch.pageY

  var left = pageX - startX + lastLeft
  var top = pageY - startY + lastTop
  startX = pageX
  startY = pageY
  lastLeft = left
  lastTop = top
  
  
  if(target_id ){ 
    ins.selectComponent('.selectBox').setStyle({
        left:  left + 'px',
        top: top + 'px'
      })
      
    ins.selectComponent('#'+ target_id).setStyle({  //使用选择器获取组件的引用
        left:  left + 'px',
        top: top + 'px'
      })
      
  }
  

}
module.exports = {
  touchstart: touchstart,
  touchmove: touchmove 
}

使用时,在WXML文件中进行声明和引用,如:<wxs module="move" src="./move.wxs"></wxs>

然后在需要进行拖动控制的组件上绑定WXS事件,并可以通过 data-xxx 机制向wxs 脚本传入page中的data中的数据,如 data-targetid="{{selectbox.targetid}}" ,这样脚本内部可以通过

event.target.dataset.xxx 这样的方式获取到传入的值
 <view class="selectBox" catchtouchstart="{{move.touchstart}}" 
                              catchtouchmove="{{move.touchmove}}" 
                              catch:touchend="{{move.touchend}}" 
                              data-targetid="{{selectbox.targetid}}" 
                              data-targettop="{{selectbox.top}}"
                              data-targetleft="{{selectbox.left}}"
                              data-targetwidth="{{selectbox.width}}"
                              data-targetheight="{{selectbox.height}}"
                              data-hRatioH="{{hRatioH}}"
                              data-canvasW="{{windowWidth}}"
                              data-canvasH="{{windowHeight}}">

另外wxs脚本可通过callMethod方式调js脚本可以向JS传递数据,但是callMethod机制无法获取JS的返回值

在使用WXS时,还需要注意一点,如果在 wxs 中对组件进行样式设置后,它的优先级比JS中要高,就是说如果wxs 和 js 中同样对某个样式操作,可能JS中的操作会无效。要解决这个问题,我们可利用wxs 提供的数据监听机制,当page中的data里某个数据发生变化后,会触发wxs中的事件,这样就可以利用WXS去设置和改变样式

  (1)  wxml中设置事件:如 <view change:prop="{{move.listenupdate}}" prop="{{box_left_top}}"></view>

              move.listenupdate是wxs中的响应事件的函数,box_left_top 是page中data的数据名称

  (2) wxs 中添加监听事件的响应函数

listenupdate: function(newValue, oldValue, ownerInstance, ins) {
    if(newValue){
      console.log(newValue)
      var arr = newValue.split(":")
      var l = arr[0] ;
      var t = arr[1] ;
      ownerInstance.selectComponent('.selectBox').setStyle(
        {
          left: l + 'px',
          top: t + 'px'
        }
      )
    }
    console.log('----------------prop observer------------------')
  }

  (3)在js中更新data数据

this.setData({
      box_left_top: (left*this.data.hRatioH-2) + ":" + (top*this.data.hRatioH-2)
    })
原文地址:https://www.cnblogs.com/hzhuxin/p/15122678.html