岁寒之松柏:什么!WXS也可以响应事件?
WXS介绍
WXS(WeiXin Script)是小程序的一套脚本语言,结合 WXML
,可以构建出页面的结构。需要特别说明的是WXS是运行在小程序的渲染线程(也就是webview中)的脚本文件,语法和JS很像,但是也有些许不同。
WXS语法简介
因为WXS整体和JS(ES5)实在太过相像,就说一下有什么不同吧(踩过的坑::>_<::)
- WXS中不支持
new Date()
如果想要获取Date对象要使用getDate()
函数函数 - WXS中不支持
new RegExp()
如果想要获取RegExp对象要使用getRegExp()
函数 - 类型判断仅支持利用
构造器进行类型判断
和typeof
进行部分数据判断
// 构造器判断类型
var number = 10;
console.log( "Number" === number.constructor );
var string = "str";
console.log( "String" === string.constructor );
var boolean = true;
console.log( "Boolean" === boolean.constructor );
var object = {};
console.log( "Object" === object.constructor );
var func = function(){};
console.log( "Function" === func.constructor );
var array = [];
console.log( "Array" === array.constructor );
var date = getDate();
console.log( "Date" === date.constructor );
var regexp = getRegExp();
console.log( "RegExp" === regexp.constructor );
// typeof 区分部分数据类型
var number = 10;
var boolean = true;
var object = {};
var func = function(){};
var array = [];
var date = getDate();
var regexp = getRegExp();
console.log( 'number' === typeof number );
console.log( 'boolean' === typeof boolean );
console.log( 'object' === typeof object );
console.log( 'function' === typeof func );
console.log( 'object' === typeof array );
console.log( 'object' === typeof date );
console.log( 'object' === typeof regexp );
console.log( 'undefined' === typeof undefined );
console.log( 'object' === typeof null );
AppService响应事件的问题
一般情况下,小程序响应事件是指在Wxml中绑定事件然后通过JS文件中的函数响应的,也就是webview(渲染层)的事件是要传到AppService线程中处理,这个过程是跨线程的,很显然有很多情况下,Appservice需要频繁响应webview中事件,并且修改data值,就需要进行大量的跨线程通信,性能自然就会降低。比如如下例子,一个跟随view 跟随另一个view水平移动并且x大于250时进行特殊的业务处理:
使用movable-view组件实现该例子代码如下
<!--wxml文件-->
<movable-area class="move-area" >
<movable-view class="move-view" x="{{0}}" y="{{0}}" direction="horizontal" bindchange="handleChange">
1
</movable-view>
<!--需要设置direction属性 否则无法移动-->
<movable-view class="move-view" animation="{{false}}" x="{{x}}" y="{{y}}" direction="all" >
2
</movable-view>
</movable-area>
//js文件
Page({
/**
* 页面的初始数据
*/
data: {
x: 0,
y: 100,
},
handleChange(e) {
if (e.detail.x > 250) {
wx.showToast({
title: "业务逻辑",
icon: "none",
});
return;
}
this.setData({
x: e.detail.x,
});
},
});
该实现方式的底层调用逻辑
可以看到这个过程会进行大量的setData,而执行setData渲染是会阻塞其他脚本执行。进一步思考一下其实很容易发现问题所在,在对view2
设置坐标这个过程中绝大多数的change事件对业务层都是无效,业务层只需要在x大于250
时响应事件即可,再就是滑动这个动作本身就是渲染层的事件,把他放到业务层处理本身就是有问题,正确的方式应该是当在渲染层中独自实现view2
的跟随滑动,当滑动x大于250时
再抛出事件来给到业务层处理。正确的逻辑应该是如下图
要实现如上图所示的逻辑我们就要用到WXS来响应事件。
WXS响应事件
简单使用
先看效果 可以看出来是完全同步的
使用wxs实现代码如下
<!-- wxml 不需要设置moveable-area -->
<view class="container">
<!-- 使用双大括号调用wxs函数 -->
<view
class="move-view-1"
prop={{prop}}
prop:change="{{tool.propObserver}}"
catchtouchstart="{{tool.handleTouchstart}}"
catchtouchmove="{{tool.handleMove}}">
1
</view>
<view class="move-view-2">
2
</view>
</view>
<wxs module="tool">
// WXS 代码
var moveView2
module.exports = {
handleTouchstart:function(event, ownerInstance) {
// `ownerInstance` 表示的是触发事件的组件所在的组件的 实例,
//如果触发事件的组件是在页面内的,`ownerInstance` 表示的是页面实例。
moveView2 = ownerInstance.selectComponent('.move-view-2')
},
handleMove: function(event, ownerInstance) {
var x = event.touches[0].pageX
// 设置move-view-1位置
//`event.instance` 来表示触发事件的组件的实例
event.instance.setStyle({
left: x + "px"
})
if(x>250){
// 第二个参数可以向AppService传值
ownerInstance.callMethod("handleEvent",{isMore250:true})
return
}
// 如过在组件中 可以通过triggerEvent 触发组件事件
// if(x>250){
// ownerInstance.triggerEvent("handleEvent",{isMore250:true})
// return
// }
// 设置move-view-2位置
moveView2.setStyle({
left: x + "px"
})
},
// 当业务层的数据变化可以回调此函数
propObserver: function(newValue, oldValue, ownerInstance, instance) {
console.log('prop observer', newValue, oldValue)
}
}
</wxs>
Page({
/**
* 页面的初始数据
*/
data: {
x: 0,
y: 100,
},
handleEvent(e) {
wx.showToast({
title: "业务逻辑",
icon: "none",
});
},
});
代码的简单实现逻辑
- 在wxml声明两个view 其中一个view使用双大括号使用wxs响应事件
- 在wxs的分别获取到两个view的实例 通过setStyle方法设置view的位置
- 当x大于250是通过callMethod调用页面的handleEvent方法
- 在js的handleEvent方法中实现业务逻辑
WXS 常用API
引用
转载自:https://juejin.cn/post/7212526902773907512