持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第4天,点击查看活动详情
前言
微信小程序和 vue 的语法非常像,会写 vue 的朋友上手 vue 基本是易如反掌。但是微信小程序中缺少了很多 vue 中没有的东西,比如计算属性 computed 、监听 watch。这些在平常开发中会经常用到。虽然微信小程序没有直接提供相关的 API 来使用这些,但是我们可以用其他的一些方法来简单的间接的实现这些功能。 这篇文章就是记录一下实现这些功能的过程和一些个人感受。
实现步骤
computed 的实现过程
computed
的实现过程非常简单,我们可以通过微信小程序脚本语言 WXS(WeiXin Script) 来简单实现类似vue中的 计算属性功能(computed)。
- 先理解官方文档的示例 ```html var msg = "hello world";
module.exports.message = msg;
{{m1.message}}
代码语言:javascript复制> 页面输出:hello world
我们可以把 `<wxs></wxs>` 标签当做一对 `<script></script>` 标签一样,我们可以在里面定义变量、函数。
然后在 “Mustache” 语法双括号里使用我们定义的函数和变量。
2. 看完官方示例后我们就来实现一个类似 vue 中的简单的 `computed` 。
```javascript
// page.js
Page({
data: {
order: {
time: '2022-06-27',
status: 1,
amount: 10
}
}
})
代码语言:javascript复制<wxs module="comp">
module.exports = {
handleMatchStatus: function (source) {
switch (source) {
case 1:
return '已支付'
case 2:
return '支付失败'
case 3:
return '退款中'
}
}
}
</wxs>
<view> {{comp.handleMatchStatu(order.status)}} </view>
输出:已支付
在后台拿到的一些数据,比如订单数据里面只有商品单价和数据,页面需要你显示总价,这个时候就可以这种方式来实现;或者是项目中有些数据是状态或者类型数据,比如订单状态、订单类型、商品渠道等,通过后端传过来的都是数字,有字典表的话还好办,没有字典表的话一般都是和后端商量好,定死几个值,这个时候就可以通过这种方式显示数值对应的文字意思。
watch 的实现过程
首先明确实现后的效果:能监听小程序 page 里面 data 的所有属性值实时的变化。
思路:掘友们应该都知道 vue2.x 中的 双向绑定是通过 Object.defineProperty
方法来实现的。所以我们微信小程序可以借鉴这一方法。通过遍历 page 里 data 的属性,使用 Object.defineProperty
逐个的对每个属性进行监听,发现属性值被修改时就在 set
里调用对应的处理函数。
具体实现代码:
代码语言:javascript复制/**
*
* @param {*} data 监听的对象
* @param {*} watch 听的 key 和回调函数组成的类
*/
export const setWatcher = (data, watch, _this) => { // 接收 page 传过来的data对象和watch对象
//监听属性 并执行监听函数
const observe = (obj, key, watchFn) => {
var val = obj[key]; // 为改变之前的属性值
Object.defineProperty(obj, key, {
configurable: true,
enumerable: true,
set: (value) => {
val = value;
watchFn.call(_this, value); // 调用对应函数
},
get: () => {
return val;
}
})
}
Object.keys(watch).forEach(v => { // 将watch对象内的key遍历
observe(data, v, watch[v]); // 监听data内的v属性,传入 watch 内对应函数以调用
})
}
函数有三个入数 data
、watch
、_this
;
data 就是我们监听的对象,在小程序里也就是 page
里的 data
。
watch 就是一个对象,里面装着以键值对的形式储存的被监听的各个属性和对应的函数,key 是被监听属性,key 对应的值是这个属性值改变后的回调函数。
_this 是调用我们封装的这个函数的环境。
封装完后我们就可以在 page 页面导入并且使用了
代码语言:javascript复制import { setWatcher } from '../../utils/util'
Page({
data: {
a: 1,
b: 2
}
async onLoad(options) {
setWatcher(this.data, this.watch, this);
},
// 监听的值
watch: {
a: function (newValue) {
// 值改变后的操作
console.log(newValue)
},
b: function (newValue) {
// 值改变后的操作
console.log(newValue)
}
}
})
注意的地方
WXS
- WXS 函数不能作为组件的事件回调
- 在 WXS 中是不能调用其他js文件的函数和变量的,还有小程序的 API 也不能调用,因为 WXS 的运行环境是和其他 js 代码隔离的。有优点也有缺点吧,速度快,但是不能和其他文件的代码交互。watch
- 封装的时候一定要用传进来的
this
,通过 call 修改this
指向到函数被调用的词法环境。否则就调不了set
中传进来的回调函数.
总结
- 说 iOS 设备上小程序内的 WXS 会比 JavaScript 代码快 2 ~ 20 倍。所以像这种订单流水中的一些数据用 WXS 简单实现的类似
vue
中computed
还是比较有优势,特别是这种要经常渲染到页面上的数据。 - 上面代码中用
Object.defineProperty
这种方式封装实现的类似vue
中watch
的方式还有优化的地方,比如 data 中的深层数据改变时是监听不到的,还需深层次循环遍历。当然也可以借鉴vue3
中用代理proxy
的方式来实现。大家还有什么其他更好的方式可以在评论区留言,一起交流交流
写在最后
我是 AndyHu,目前暂时是一枚前端搬砖工程师。
文中如有错误,欢迎在评论区指正,如果这篇文章帮到了你,欢迎点赞和关注呀