小程序端之封装思想

最近由于疫情,学校一直没有开学,因此有了比较多的空闲时间。从寒假开始,就在跟着做学校的学工系统,包括pc端和小程序端。主要负责系统的前端开发工作。

与之前开发不同,这次系统的前后端都使用了较新的技术和思想,自己也确实通过开发的过程学到了不少东西,因此在这里记录一下,算是总结的笔记。

1 . 封装思想

我从前端的角度谈一谈自己对封装的理解:

1. 封装是将重复出现的东西简化。

举个例子,如果你想要给一个div标签加一些css的属性(style),因为属性很多,就会让原本简洁的标签变得很长,并且如果另一个div标签恰好也需要相同的属性,那很遗憾,你需要把刚才那些属性复制到这个div。

很明显,上边这种做法,有明显的缺点:1. 代码看起来不整洁,尤其是style写的很多的时候;2. 代码冗余。如果学过css,大家应该知道class类,其实class的出现就很好的解决了这个问题:自定义一个class,把写在div标签中style属性放在class中,在需要的标签中直接使用class即可。

封装的直观理解,是对公用属性、方法的提取和抽象。

其实封装的最常见的形式,就是函数或方法。例如常见的前端js框架,vue和jquery都有自己的语法,jquery中的 $ 其实就可以看作是把原生的js操作封装成了这个符号,如果谈底层的实现,其实本质和原生js是一样的。这些js框架的出现就将原本较为重复、繁琐的js操作,在代码形式上大大的简化了,有助于开发效率的提升。对于目前较为流行的vue、react等框架,封装的程度已经到了刚入门就可以快速搭建简单项目了。

2. 封装可以降低代码的维护成本。

对于自己开发项目来说,除了借助一些流行的框架提高开发效率外,让代码可维护性更高也很重要。比如,在写某个页面时,自己写了一段js代码,后来在开发别的页面时,发现也需要几乎相同的代码,可能改变的就是几个参数的值。

这时,你可以有两种选择:1. 把之前的代码复制过来,简单修改;2. 新建一个通用js文件,在里面编写一个函数,把这段代码放在函数中,并把可能变化的参数值作为函数的参数暴露出来。

当然,如果这段复用的代码比较短,并且复用的次数不多,修改比较容易,完全可以采用第一种方式,复制就完事了。但是,一段代码往往代表着一个功能,当这个功能需要多次使用时,从长远角度来看,第二种方式更具有通用性。学过软件工程都知道,需求不是一成不变的,尤其是一些比较重要的功能,一旦需求有比较大的调整,代码的水平高下立分。好的代码只需简单调整,增加新的功能,差的代码牵一发而动全身,严重时可能因为需求增加需要重构代码。(这里涉及到一些解耦的思想)

因此,对于较大系统的设计和开发,封装的思想应该多多考虑。如果开发初期为了简单省事,对于应该封装的功能方法没有进行设计,如果后期功能调整,需求改变,这时需要花费的时间和精力,往往是巨大的,远大于最初设计封装花费的成本。

2. 小程序中用到的封装

因为之前写过小程序,虽然隔了好长一段时间没写,不过基本的写法还是没有忘。这次学工系统包括了小程序端,我也是主要负责前端的开发。

和之前相比,我有个比较大的感受,就是这次比较明显的用到了封装的思想,也是因为考虑到了系统毕竟是给学校用的,要考虑一些通用性的问题,考虑的更长远一些。

下面说一下用到封装思想的地方:

1. css框架的使用
之前开发小程序都是纯原生的,虽然写起来很练基本功,但是确实是丑,这次用的是colorUI这个小程序框架,不得不说,确实好看。框架中包括了对基本css属性的封装,都统一成了class,并且一些常用的文字对齐方式、大小、颜色等,都有自己的类,直接用就行,这比自己一点点写style属性简洁多了。同时,还有以模板形式封装的顶部栏样式,在需要的地方直接引用。(之后会详细一点介绍这个框架)

2. 对request请求的封装
wx.request() 是小程序官方的方法,用法和功能基本上和ajax是一样的,负责的是页面中数据的异步刷新。由于这个方法使用频率很高,基本上每个页面都会用到。在开发中就要考虑到两个问题:

a. 参数中的 url 一般是 “ 服务器地址(或本地localhost)+ 接口路径” 的格式。

如果作为开发项目,一般至少需要两个环境,一个线上发布,一个线下测试,同样对应于服务器的 url 和 localhost 的url 。这样,对于每一个request方法,就都需要两个url,依据环境不同而定。这样,一个简单的封装思想就产生了,在app.js的globalData中,定义一个全局变量,作为服务器/localhost地址的代称,在每个request中的 url 使用这个变量,究竟是用服务器还是本机,只需修改此变量即可。

接口路径的部分,一般来说,一个接口对应一个request。几个request都请求一个接口的情况较少,如果有,一般是重复功能,可以将这个功能直接封装。在pc端,本次开发将系统中用到的所有接口都统一放在了一个js文件中(看作一个接口列表),在每个fetch请求中,都通过引入这个存放接口的js,实现接口路径的引用。(pc端封装了fetch方法和接口列表)

小程序端也是采用了同样的方式,对接口路径进行了汇总,统一放在了一起。这里的含义,就是将接口们封装在了一个js中,如果一旦接口路径有所改变,如接口名改了,接口的层级改了,都可以直接在这个js中直接修改对应的接口,不用去页面中挨个找了。

b. success回调函数,依据接口返回值情况的不同,往往有不同的表现。

例如,如果接口返回的是一个列表,需要把这个返回的列表渲染在当前页面上,回调函数往往是对当前页的变量的赋值语句;如果接口返回的是一个成功/失败(如提交表单),那么回调函数往往是弹窗提示成功/失败,或界面的跳转等。从这两种情况可以看出,success回调函数一般是要根据实际情况而编写,不太适合把它封装为一个公用的函数。

但是,这次开发中加入了对用户token失效的处理。token失效发生在用户重复登录,或登录时间过长并且没有操作的情况,此时接口请求便会出现401的错误码。之前写小程序其实并没有考虑到token失效的问题,也没有相应的处理,现在来看显然是不合适的。此时,success回调函数中对返回值状态码的判断,是不是就要考虑封装了呢?不然,401的判断后界面的跳转,以及后续可能的404…等等的判断,难道要每个接口都手动去增加吗?

综合以上两个考虑,最终决定要把request方法封装成了一个公用的方法,request中不变的部分写在新方法中,变化的部分作为新方法的参数暴露出来,在需要使用的页面直接引入调用即可。同时,接口统一放在一起,需要的地方通过名称引用。

3. 封装实例

utils/util.js

//封装小程序中所有request请求
function request(url,data,callBack){
  var app = getApp();
  wx.request({
    method: "POST",
    url: app.globalData.url+url,
    data: data,
    header: {
      "Content-Type": "application/json",
      "token":app.globalData.token
    },
    success: function(res) {
      if(res.data.code == 401){  //统一处理401情况
        wx.redirectTo({
          url: '../401/401',
        })
        callBack(null);
      }
      else{
         callBack(res);  //将返回值作为回调参数
      }
    }
  })
}

module.exports = {
  //暴露接口
  request:request
}

utils/urls.js (部分展示)

// 用于存放小程序的接口
const URL = {
  //个人中心相关
  'center':{
    //获取个人信息
    'information':'/assistant/login-user/mini/information',
    //修改密码
    'password':'/assistant/login-user/update/password'
  },
  //登录相关
  'login':{
    //账号密码登录
    'user':'/assistant/login-user/mini/login',
    //code登录
    'code':'/assistant/login-user/mini/login/openId',
    //退出登录
    'logout':'/assistant/login-user/mini/logout',
    //获取菜单
    'menu':'/assistant/user-type-menu/menu/list/mini'
  }
}

module.exports = {
  URL:URL
}
 

调用封装,以登录接口 /assistant/login-user/mini/login 为例

pages/login/login.js

const app = getApp()
const md5 = require('../../utils/md5.js')  //md5转换
const utils =  require('../../utils/util.js')
const urls =  require('../../utils/urls.js')

//登录
  login(){
    let that = this;
    //控制按钮点击,防止连续点击
    that.setData({
      flag:true
    })
    wx.login({
      success: res => {
        app.globalData.code = res.code;   //获取code
        var data = {                      //参数列表
          'code':app.globalData.code,
          'loginId':that.data.userId,
          'passwd':md5(that.data.pwd)
        }
        //调用自定义的封装方法
        utils.request(urls.URL.login.user,data,function(res){
          if(res){
            if(res.data.success){
              app.globalData.userInfo = res.data;
              app.globalData.token = res.data.data.token;
              app.globalData.userName = res.data.data.userName;
              wx.showToast({
                title: '登录成功',
                duration: 1000,
                success: function () {//显示提交成功后跳转到首页
                  setTimeout(function () {         
                    wx.navigateTo({
                      url: '../index/index',  
                    })  
                  }, 500);        
                }
              })
            }else{
              wx.showToast({
                title: res.data.msg,
                icon: 'none'
              })
              that.setData({
                flag:false
              })  
            }
          }
        })
      }
    })
  }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值