最近在重构小程序,重构的时候发现很多页面都用到了定位与逆地理解析这一功能,于是项目里几乎每个页面都要写一下获取定位的相关逻辑,实在头大。有没有办法抽离这部分逻辑呢?写成Component又太庞大,因为我们只需要js的相关逻辑。把方法抽离到utils中再调用,又需要再声明个响应式data去接收,都不是最优方案。那小程序能不能做到混入呢?答案是:能!
behaviors 是用于组件间代码共享的特性,类似于一些编程语言中的 “mixins” 或 “traits”。
每个 behavior 可以包含一组属性、数据、生命周期函数和方法。组件(注意:基础库 2.9.2 开始在页面中也支持使用 behaviors)引用它时,它的属性、数据和方法会被合并到组件中,生命周期函数也会在对应时机被调用。 每个组件可以引用多个 behavior ,behavior 也可以引用其它 behavior 。
behavior 需要使用 Behavior() 构造器定义。
Behavior(Object object)
注册一个 behavior,接受一个 Object 类型的参数。
定义段 | 类型 | 是否必填 | 描述 |
---|---|---|---|
properties | Object Map | 否 | 同组件的属性 |
data | Object | 否 | 同组件的数据 |
methods | Object | 否 | 同自定义组件的方法 |
behaviors | String Array | 否 | 引入其它的 behavior |
created | Function | 否 | 生命周期函数 |
attached | Function | 否 | 生命周期函数 |
ready | Function | 否 | 生命周期函数 |
moved | Function | 否 | 生命周期函数 |
detached | Function | 否 | 生命周期函数 |
// /behaviors/location.js
let QQMapWX = require('../utils/qqmap-wx-jssdk.min.js');
let qqmapsdk = new QQMapWX({key: '你自己的key'});
module.exports = Behavior({
// 共享数据
data: {
location: {}
},
methods: {
getLocation() {
// 因为我们的业务功能必须在位置信息获取到以后才能正常使用,所以这里封装成Promise,以便链式调用
return new Promise((resolve, reject) => {
wx.authorize({scope: 'scope.userLocation'}).then(() => {
this.handleLocation(resolve, reject)
}).catch(err => {
wx.showModal({
title: '提示',
content: '获取不到您的定位,请允许使用您的定位,以获取准确服务地点',
success: (res) => {
if (res.confirm) {
wx.openSetting().then(() => {this.handleLocation(resolve, reject)})
}
}
})
})
})
},
handleLocation(resolve, reject) {
wx.getLocation({type: 'gcj02'}).then(res => {
const { latitude, longitude } = res
this.setData({ latitude, longitude })
wx.setStorageSync('latitude', latitude);
wx.setStorageSync('longitude', longitude);
this.turnLocationToAddress(resolve, reject);
}).catch(() => {
wx.showToast({
title: '请前往手机设置允许微信使用定位信息',
icon: 'none',
mask: true
})
reject()
})
},
turnLocationToAddress(resolve, reject) {
const { latitude, longitude } = this.data
qqmapsdk.reverseGeocoder({
location: {
latitude: latitude,
longitude: longitude
},
success: (res) => {
if (res.status === 0) {
let {province, city, district} = res.result.address_component;
let adCode = res.result.ad_info.adcode;
let location = {
'longitude': longitude,
'latitude': latitude,
'province': province,
'city': city,
'district': district,
'address': res.result.address,
'districtId': adCode
};
this.setData({ location });
wx.setStorageSync('location', JSON.stringify(location));
resolve(location)
}
},
fail: function (err) {
reject()
console.log('位置解析失败:', err);
}
});
}
}
})
// page中
const LocationBehavior = require('../../behaviors/location');
Page({
behaviors: [LocationBehavior],
data: {},
onLoad: function () {
// getLocation是LocationBehavior中的方法
this.getLocation().then(() => {
this.getDetail()
})
}
})
在page中我们也能通过 this.data.location拿到用户的位置信息。
组件和它引用的 behavior 中可以包含同名的字段,对这些字段的处理方法如下:
如果有同名的属性 (properties) 或方法 (methods):
如果有同名的数据字段 (data):
对于不同的生命周期函数之间,遵循组件生命周期函数的执行顺序;
官方文档是最好的学习资料:微信小程序开发文档-自定义组件Behavior