小程序模板网

从AddressPicker实现探讨小程序组件封装方式

作者:u3xyz,来自授权地址

在做最近的小程序项目时,需要使用到省市县联动选择器。浏览了一下小程组件,发现没有直接提供这种组件,比较相近的picker组件也只支持selector|time|date。

当然,我们可以使用view来模拟,但这样开发量会比较大。再往下看,发现了picker-view + picker-view-column这对好基友,这不就是专门用来实现多列滚动选择的吗?既然找到组件了,接下来就是如何实现了?

不急,我们还是先看一下组件最终效果:

 

使用类实现小程序组件

一些小程序组件通常会被设计成一个类。用代码表示,大概是下面的样子:

 

				
  1. //componentXX.js
  2.  
  3. class ComponentXX() {
  4.  
  5. constructor(opts) {
  6. this.$scope = opts.$scope;
  7. },
  8.  
  9. methodA() {
  10. // 使用this.$scope.setData()达到修改ViewModel的能力
  11. }
  12. }
  13.  
  14. export default ComponentXX;

使用时,先引用定义,然后在onLoad时new一个实例,再调用实例相应的方法,如:

 

				
  1. import ComponentXX from 'path/to/conpoentxx/conpoentxx';
  2.  
  3. Page({
  4. data: {
  5.  
  6. },
  7.  
  8. onLoad(opts) {
  9. this.componentXX = new ComponentXX({
  10. $scope: this,
  11. opts: {}
  12. });
  13. },
  14.  
  15. bindTap() {
  16. this.componentXX.doSomething();
  17. }
  18. });

项目里有几个组件,也的确是这样实现的。但这里有几个问题:  1. 使用麻烦。除new之外,每次还得增加一些不必要的方法去调用组件实例相应的方法,比如上面的bindTap方法  2. 因为问题1,所以组件的封装性很差  3. 同页面多组件共存问题,是new多个组件吗?

那么,还有没有更简单,更好的组件封装方式呢?

 

				
  1. page({
  2. onLoad(opts) {},
  3. method() {}
  4. });

其实我们观察小程序页面启动方法会发现:  1. page函数需要传入一个对象参数,这里参数里面的特定函数onXXX(onLoad,onShow)会在页面的特定生命同期被调用  2. 其它挂在对象参数上的方法或属性,可以通过this访问到。在wxml模板中,也可以直接调用  也就是说,我们扩展对象参数,就可以扩展方法在.wxml模板中调用。基于此,有下面的组件封装方式:

 

				
  1. import ComponentXX from 'path/to/conpoentxx/conpoentxx';
  2.  
  3. Page(extend({
  4. data: {
  5.  
  6. },
  7.  
  8. onLoad(opts) {
  9. this.initComponentXXX(opts);
  10. },
  11. }, ComponentXX));

这种组件封装方式,页面注册参数不需要多写额外的方法。看起来更简洁,封装性也更好。

 

实战:使用extend方式实现AddressPicker组件

 

				
  1. import location from 'location.js'; // 数据文件。如果觉得数据文件太大,受小程序1M限制,可以通过cgi返回,然后存于缓存
  2.  
  3. const AddressPicker = {
  4. /**
  5. * 省市县联动初始化个数。注意索引从0开始,例如apNumber = 2,则会有3个联动选择控件
  6. * @param apNumber
  7. */
  8. initAddressPicker(apNumber = 0) {
  9.  
  10. // this 即页面VM,可直接使用this.setData()方法
  11.  
  12. this.curApIndex = 0;
  13. this.conf = [];
  14. this.$address = location;
  15. this.inited = false;
  16.  
  17. // TODO 因为不能控制省份滚动到某个点,所以不能在初始化时指定某个省市县
  18. this.$provinceList = this.getProvinceList();
  19.  
  20. while (apNumber-- >= 0) {
  21. this.conf.push({
  22. index: 0,
  23. show: false,
  24. prePid: 0,
  25. pid: 0,
  26. cid: 0,
  27. tid: 0,
  28. provinceList: this.$provinceList,
  29. cityList: this.$address[0].children,
  30. townyList: this.$address[0].children[0].children
  31. });
  32. }
  33.  
  34. // init ap VM
  35. this.setData({
  36. __ap: this.conf
  37. });
  38.  
  39. setTimeout(() => {
  40. this.inited = true;
  41. }, 200);
  42. },
  43.  
  44. getProvinceList() {
  45. return this.$address.map(item => {
  46. return {
  47. label: item.label,
  48. value: item.value
  49. };
  50. });
  51. },
  52.  
  53. getCityList() {
  54. try {


易优小程序(企业版)+灵活api+前后代码开源 码云仓库:starfork
本文地址:https://www.eyoucms.com/wxmini/doc/course/23465.html 复制链接 如需定制请联系易优客服咨询:800182392 点击咨询
QQ在线咨询