微信小程序> 微信小程序(wepy)

微信小程序(wepy)

浏览量:763 时间: 来源:weixin_34343689

1.链接: blog.csdn.net/qq_26585943…

www.jianshu.com/p/0078507e1…

微信小程序开发(wepy框架)

布局: rpx 设计稿750px, 设计稿多大就写多大的

一、生命周期(app.js)

  • onLaunch 用户首次打开小程序,触发 onLaunch(全局只触发一次)这里做第三方开发平台自定义配置项注意: ext.json也可以覆盖本地的配置项目,例如小程序跳转小程序就是在ext.json可以进行配置,手机扫码会进行读取ext.json进行覆盖本地的配置
  • wx.getExtConfigSync()  动态读取ext 字段自定义的数据字段

  • onLoad[(options)] 加载小程序,options参数拦截,模块只能触发一次,tabbar菜单, 页面模块进行切换不进行调用了, 页面是每次都会调用的

涉及到模块页面是否是是及时更新,如果及时更新放到onShow里面

  • onHide 进入后台,进程没有杀死
  • onError  错误监听函数 当小程序发生脚本错误,或者 api 调用失败时,会触发 onError 并带上错误信息
  • 顺序 onLuach = onLoad  = onHide

页面生命周期(page.js):

  • onLoad --监听页面加载
  • onShow --监听页面显示
  • onReady --监听页面初次渲染完成
  • onHide --监听页面隐藏
  • onUnload ---监听页面卸载
    • 其中,打开小程序后会依次执行onLoad = onShow = onReady

    • 前后台切换会分别执行onHide和onShow方法,

    • 当小程序页面销毁时会执行 onUnload方法

     export default class index extends wepy.page {  config = {};  //配置信息     components = {}; //組件配置  data = {};  //页面数据  methods = {};  //元素绑定事件区域  events = {}; //子组件$emit给父组件发数据,触发父组件方法  watch = {}; //监听数据变化  //== 生命周期  onLoad(options) {  // scene=decodeURIComponent(options.scene);  二维码参数  // 一般参数  {} }onReady() {  // Do something when page ready.}onShow() {  // Do something when page show.}onHide() {  // Do something when page hide.}onUnload() {  // Do something when page close.}//下拉onPullDownRefresh() {  // Do something when pull down.}//上拉onReachBottom() {  // Do something when page reach bottom.}//分享onShareAppMessage() {  // return custom share data when user share.},//页面滚动onPageScroll() {  // Do something when page scroll}onResize() {  // Do something when page resize}//== 自定义方法getQuery(){  ...  }createImage() {  ....}复制代码

二、配置文件. 小程序配置config

app.wpy文件

  • pages: [] 页面,小程序所页面,必要的页面,
  • subPackages:[] 分包配置,将模块页面放入,上面就可以不用配置了

  • window:{} 所有页面配置
    1. backgroundTextStyle
    2. navigationBarBackgroundColor
    3. navigationBarTextStyle
    4. onReachBottomDistance: 240 //实现无感加
    5. navigationStyle:default/custom  微信小程序自定义顶部导航栏 ,顶部导航栏就会消失,保留右上角胶囊状的按钮
  • tabBar:[] 小程序下面切换配置,可以自己写
    1. 最多五个,最少2个,每次修改完要提交微信审核
  • navigateToMiniProgramAppIdList: [] 小程序跳转小程序配置, 目前最多10个
  • globalData全局数据  [类似于vuex redux 数据共享],一般外链文件
  • methods 全局方法 , 所有页面都可以共用的,一般外链文件

三、页面配置信息 conifig (重点)

app.json配置如果和页面配置冲突了,那么会采用页面配置的

  • navigationBarTitleText  title
  • navigationBarTextStyle 字体颜色 ["white" /"blank"]
  • enablePullDownRefresh 是否下拉属性
  • disableScroll 是否可以滚动
  • disableSwipeBack 是否可以IOS左滑返回上一级,或着关闭小程序

四、一个wpy文件的组成

  • template模板,结构
  • script脚本
    1. data页面数据  this.xxx = xxx; 进行修改
    2. methods 页面方法 @绑定的 内置的方法
    3. events 是子组件传递的方法 $emit子元素传父元素事件   .sync    props对象进行接收设置twoWay: true父元素下发的数据更新子元素跟着改变
    4. watchs 监听数据   数据发生改变进行处理

五、 微信授权登录流程

wepy登录流程: blog.csdn.net/weixin_4156…

scriptimport wepy from 'wepy'import 'wepy-async-function'import { setStore } from 'wepy-redux'import configStore from './store'const store = configStore()setStore(store) export default class extends wepy.app {  config = {    pages: [      'pages/index',      'pages/charts',      'pages/test'       ],    window: {      backgroundTextStyle: 'light',      navigationBarBackgroundColor: '#fff',      navigationBarTitleText: 'WeChat',      navigationBarTextStyle: 'black'    }  }   globalData = {    userInfo: null,    ret:null,    config:null,    apiUrl:'后台地址'  }   constructor () {    super()    this.use('requestfix')    this.use('promisify')  }  onLaunch() {    this.testAsync()    this.init();  }  // 初始化获取config  init(){    wepy.request('初始化后台api').then(      (ret)={        this.globalData.config = ret.data.config;        console.log('======初始化成功=======');        //初始化成功判断是否授权        this.checkSettingStatus();      }    )  }  //判断登录状态/是否授权  async checkSettingStatus(){    try {      let auth = await wepy.getSetting();    //调用getSetting Api      let authSetting = auth.authSetting;    //获取authSetting用来判断是否授权      console.log('---开始判断---');          if(authSetting['scope.userInfo']){          console.log('---已经授权---');          //已经授权情况下直接获取userInfor          let userInfo= await wepy.getUserInfo();              this.globalData.ret = userInfo;          //调用登录          this.login();      }else{        //如果没有授权跳转至授权页进行授权(新版只能通过调用按钮来调出授权框)        //授权页面button需要赋予open-type='getUserInfo'属性        //bindgetuserinfo='scope' bind方法用来授权/获取userInfor        console.log('---用户未授权---');        wepy.navigateTo({ url: './test' });      }      } catch (error) {      console.log(error)    }  }  //登录方法 async login(){   try {    console.log('---调用login方法---')    let token = wepy.getStorageSync('token') || '';        let {code:code} = await wepy.login();  //通过调用login获取code 判断是否开始登录     if(code){       console.log('---获取信息发送网络请求---');       let ret = this.globalData.ret       wepy.request({         url: '', //开发者服务器接口地址",         data: {           code : code,           rawData : ret.rawData,           token:token         },          method:'POST',          header:{            'Content-Type':'application/x-www-form-urlencoded'          }       }).then((res)={            console.log('---网络请求返回成功---')           console.log(res)           let response = res.data;           if(response.code == 1){             console.log('---登录正常,返回值1---');             console.log(response);             this.globalData.userInfo = response.data.userInfo;             wepy.setStorageSync('token',response.data.userInfo.token);             console.log(this.globalData.userInfo );           }else{             console.log('---登录异常---');             wepy.setStorageSync('token','');           }       });     }else{       console.log('---login返回异常---')     }   } catch (error) {    console.log(error)    }      }  sleep (s) {    return new Promise((resolve, reject) = {      setTimeout(() = {        resolve('promise resolved')      }, s * 1000)    })  }   async testAsync () {    const data = await this.sleep(3)    console.log(data)  }   getUserInfo(cb) {    const that = this    if (this.globalData.userInfo) {      return this.globalData.userInfo    }  }}/script复制代码
= 进入首页判断用户是否登录(是否有用户信息) = 没有登录 = 进入登录页面1.第一步 进入首页检测 HttpRequest.checkSessionAndLogin(this.$parent); //进行判断是否登录,是否登录过期2. 第二步,进行判断static async checkSessionAndLogin(app) {    let that = this;    if (app.globalData.userInfo) {        let session = await wepy.checkSession(); //是否过期了,        if (!session) {            that.login(app);        }    } else {        that.login(app);  //没有登录,去登录页面    }}//3.登录授权static async login(app) {    let that = this;    let res_login = await wepy.login(); //登录    if (res_login.code) {   // code = 用户登录凭证(有效期五分钟)        app.globalData.code = res_login.code;        let res_setting = await wepy.getSetting();  //= //调用getSetting Api 返回API对象        if (res_setting.authSetting['scope.userInfo']) { ///获取authSetting用来判断是否授权            that.getUserLoginInfo(app, res_login.code);            return true;        } else {   //没有授权, 进入登录页面            wepy.navigateTo({                url: 'login'            });            wepy.hideLoading();        }    }}//4. 已经授权, 取得用户信息进行存储static async getUserLoginInfo(app, code) {    let that = this;    // 已经授权,可以直接调用getUserInfo获取头像昵称,不会弹框    let res_userInfo = await wepy.getUserInfo();    if (res_userInfo) {        app.globalData.userInfo = res_userInfo.userInfo;        let invite_app_user_id = app.globalData.invite_app_user_id; //首页进入URL参数放入数据池的        let step_prize = app.globalData.step_prize; //步数邀请 //首页进入URL参数放入数据池的        let punch_the_clock = app.globalData.punch_the_clock; //打卡邀请        let query = {            code: code,            app_id: app.globalData.configInfo.appid,            raw_data: res_userInfo.rawData,            iv: res_userInfo.iv,        };        if (invite_app_user_id) {  //如果是空则不传            query.invite_app_user_id = invite_app_user_id;        }        if (step_prize) { //步数邀请,该值为1            query.step_prize = step_prize;        }        if (punch_the_clock) { //打卡邀请,该值为1            query.punch_the_clock = punch_the_clock;        }        //调用后台接口        that.request({            query: query,            url: app.globalData.basePath + '/auth',            success: function (backData) {                if (backData.data.status == "1") {                    app.globalData.userInfo = backData.data.data;                    // getUserLoginInfo是网络请求,可能会在Page.onLoad之后才返回,所以此处加入callback以防止这种情况                    if (app.userInfoReadyCallback) {                        app.userInfoReadyCallback(backData.data.data);                    }                    wepy.hideLoading();                } else {                    wepy.hideLoading();                }            }        })    }}微信授权button按鈕 button id="getUserInfo" open-type="getUserInfo"   hidden="true"  bindgetuserinfo="bindGetUserInfo"/button bindGetUserInfo(e) {    //用户单击授权按钮确定,进行返回首页    if (e.detail.errMsg == "getUserInfo:ok") {        wepy.navigateBack();    }}复制代码

六、项目问题总结:

  • 获取公共数据
    • 页面内采用: this.$parent   ==  [ app = getApp() ]
    • 组件内部:  this.parent
  • 小程序跳转小程序配置 在app.json里面配置navigateToMiniProgramAppIdList:[]
  • 弹框出来阻止页面滑动,
  view class="outer_chain_pop" @tap="hidePopModel" catchtouchmove='stopPageScroll'/view  stopPageScroll () {      return false;  },复制代码
  • 弹框单击, 单击弹框区域外隐藏弹框,利用事件冒泡
 view class="share_pop" @tap="hidePopModel" catchtouchmove='stopPageScroll'      view class="share_pop_box {{shareObj.slideUp}}" @tap.stop='preventEvent'/view /view  //单击弹框区域外, 弹框消失 hidePopModel() {      this.shareObj.isShowSharePop = false;      this.isPageNoScroll = '';      this.isShowCanvas = false;      this.isShowChainPop = false;  },  //单击弹框,阻止事件  preventEvent() {      return false;  },复制代码
  • button按钮样式重置
  button {      background: transparent !important;  }  button::after {      border: none;  }复制代码
  • 微信修改了分享机制,导致开发者拿不到任何分享后的回调(成功、失败、完成)
  • 用 scroll-view 如果要横向滚动的话,除了要设置 scroll-x 属性,还要设置 white-space: nowrap; 的样式,子元素设置 display: inline-block
  • 如果你用了一个定时器,在退出页面的时候要记得清除,不然这个定时器还会一直执行
  • 小程序分享图片必须是5:4比例,如果不是,则进行补图, 首先用canvas画图,转为图片,这张图片进行分享图片
  • 回到顶部,安卓会有抖动的效果,动画时间直接设为0, IOS没事
  • IOS下拉会出现白色背景,盖一层,定位到上面,优化
  • IOS在模块内左滑会关闭小程序,在config对象设置disableSwipeBack:true 不关闭小程序
  • 生成专属图片分享,canvas生成图片进行分享
  • 邀请好友,分享一律query参数
  • 参数接受问题:
    • 跳转?后面的参数在onLoad里面用options接受,返回的是一个对象   eg:pages/pagesWpy/index?from='step' {}
    • 小程序二维码扫码跳转进来的,在onLoad里面使用var scene = decodeURIComponent(options.scene)获取,他返回的是一个字符串 ?后面的参数 "",在进行参数格式化返回一个的对象,进行处理

  • wx.navigateTo(导航切换) 和wx.switchTab(控制 tabBar 的切换)

  • 自定义底部导航和内置tabBar导航

  • 自定义组件

  • 解析 HTML 的三种方法(www.qinziheng.com/xiaochengxu…)

    • wxParse 解析富文本   插件处理,引用
    • rich-text 解析富文本  标准HTML都可以解析
    • web-view 解析富文本,公众号文章展示,显示网页内容,组件权限最高
    • juejin.im/post/5bb86a…
  • 使用微信开发者工具–添加项目,项目目录请选择dist目录。

  • 微信开发者工具–项目–关闭ES6转ES5。 重要:漏掉此项会运行报错。

  • 微信开发者工具–项目–关闭上传代码时样式自动补全。 重要:某些情况下漏掉此项也会运行报错。

  • 微信开发者工具–项目–关闭代码压缩上传。 重要:开启后,会导致真机computed, props.sync 等等属性失效。(注:压缩功能可使用WePY提供的build指令代替,详见后文相关介绍以及Demo项目根目录中的wepy.config.js和package.json文件。)

  • WePY中的methods属性只能声明页面wxml标签的bind、catch事件,不能声明自定义方法

  • onload只会在页面加载时候执行,比如用navigateBack回到之前的页面的时候,之前那个页面不会再执行onload,所以我们要触发某些函数的时候,我们可以放在onshow里面,即使是navigateBack回来也会执行

  • 同一个页面想要2个分享?

    • 需要在Page中添加onShareAppMessage方法,否则点右上角菜单不会出现转发选项除了右上角菜单外,可以使用button组件的open-type="share"button组件和右上角的点点点都是调用onShareAppMessage方法通过参数中的from字段区分事件来源是菜单menu还是按钮button(某需求要求两个分享不同)通过onShareAppMessage方法返回的对象来定制转发界面显示的内容
  • 全屏蒙版弹窗遮不住tabBar?

    • tabBar的层级还是很高的,当出现全屏蒙版弹窗时,是无法盖住tabBar的,可以调用微信的hidetabbar,不过需要注意兼容低版本  wx.hideTabBar({}) / wx.hideTabBar({})
  • canvas生成分享图

    • 创建canvas对象,画图,draw()花完,进行canvas转图片, 回调里面, wx.canvasToTempFilePath(options)

图解布局:

小程序优化

juejin.im/post/5b496d…

离开页面

进入页面

打开小程序

项目目录分配 src是源文件夹, dist是打包完的文件夹

HttpRequest.js封装

import wepy from 'wepy'import globalData from '@/infrastructure/globalData/global' //公用数据import dialog from '@/assert/utils/dialog';const params = globalData.parapms; //接口公共参数const basePath = globalData.basePath; //域名class HttpRequest {    static setPromise(url, method, options = {}, type) {        if(type !=='md') { //其他接口            options = Object.assign(options, params);            url = (basePath + url);        }        return wepy.request({            url ,            method,            dataType: 'json',            data: options,            header: {                'content-type':'application/json'            }        });    }    //统一接口拦截,请求是否成功    static validation(res) {        return new Promise((resolve, reject) = {            if (typeof res !=='undefined') {                let code = res.data.status;                if (code == 1) {                    resolve(res.data);                } else if(code == 0) {                    //错误处理                    let timer = null;                    clearInterval(timer);                    if(res.data.error=="活动已关闭,该页面已隐藏"){                            reject(res.data);                    }else{                        wepy.showToast({                            title: res.data.error,                            icon: 'none',                            duration: 2000                        });                        timer = setTimeout(() = {                            dialog.hideLoading();                            reject(res); //返回错误信息                        }, 2000);                    }                                   }            }        });    }    static get(url,  options = {}, type) {        return HttpRequest.setPromise(url, "get",options,type);    }    static post(url, options = {}) {        return HttpRequest.setPromise(url, "post", options);    }    static delete(url, options = {}) {        return HttpRequest.setPromise(url, "delete", options);    }    static put(url, options = {}) {        return HttpRequest.setPromise(url, "put",options);    }}export default HttpRequest;复制代码

七、常用方法封装

  1. 获取URL参数
 function getQuery(key, url) {    url = url || window.location.href + '';    if (url.indexOf('#') !== -1)        url = url.substring(0, url.indexOf('#'));    let rts = [],        rt;    let queryReg = new RegExp('(^|\?|&)' + key + '=([^&]*)(?=&|#|$)', 'g');    while ((rt = queryReg.exec(url)) != null) {        rts.push(decodeURIComponent(rt[2]));    }    if (rts.length == 0) return null;    if (rts.length == 1) return rts[0];    return rts;}复制代码

2.保存图片到手机

```  block wx:if="{{shareObj.scopeFlag}}"    view class="" @tap.stop="saveImg" @tap.stop='preventEvent'      button class="canvas_image_btn_save" @tap.stop='handleSetting1'去授权/button    /view  /block  block wx:if="{{shareObj.settingFlag}}"    button class="canvas_image_btn_save"  open-type="openSetting" bindopensetting='handleSetting'去设置/button  /block//保存图片,判断是否授权,没有授权则进入授权页面进行授权function checkoutSaveImg() {  wx.getSetting({    success: res = {      //进行去授权      if (!res.authSetting['scope.writePhotosAlbum']) {        if(this.shareObj.scope) {  //授权完毕了, 包括失败和成功          this.shareObj.scopeFlag = false;          this.shareObj.settingFlag = true;        } else {          this.shareObj.scopeFlag = true;          this.shareObj.settingFlag = false;        }        this.shareObj.saveImgSettingFlag = false;        this.$apply();      } else {  //授权完毕,进入设置页面进行设置        this.shareObj.saveImgSettingFlag = true;        this.shareObj.settingFlag = false;        this.shareObj.scopeFlag = false;        this.isShowCanvas = true;        this.$apply();      }    }  });}//调取授权弹框进行授权function handleSetting1(e) {    //判断是否开启授权    wx.getSetting({      success: res = {        //进行去授权        if (!res.authSetting['scope.writePhotosAlbum']) {          wx.authorize({            scope: 'scope.writePhotosAlbum',            success: () = {              this.shareObj.saveImgSettingFlag = true;              this.shareObj.scopeFlag = false;              this.shareObj.settingFlag = false;              this.isShowCanvas = true;              this.shareObj.scope = true;              this.$apply();            },            fail: () = {              debugger              this.shareObj.scope = true;              this.shareObj.settingFlag = true;              this.shareObj.saveImgSettingFlag = false;              this.shareObj.scopeFlag = false;              this.$apply();            }          });        } else {  //授权完毕,进入设置页面进行设置          if (!e.detail.authSetting['scope.writePhotosAlbum']) {            Tips.alert('不授权无法保存', 2000);            this.shareObj.saveImgSettingFlag = false;            this.shareObj.settingFlag = true;            this.shareObj.scopeFlag = false;            this.isShowCanvas = true;          } else {            this.shareObj.saveImgSettingFlag = true;            this.shareObj.settingFlag = false;            this.shareObj.scopeFlag = false;            this.isShowCanvas = true;          }          this.$apply();        }      }    });  },```复制代码

3.分享图片

//邀请注册,和页面默认转发功能,进入首页function setShare(options) {    options = options || {};    let imageUrl = options.imageUrl || 'https://xiaomengtong.oss-cn-beijing.aliyuncs.com/statics/xiaomengtong-small-program/share_img_one.png'; //默认当前页面截取    let title = options.title || '阅读新体验,活动玩不停';    let path = options.path || '/pages/pagesWpy/index'; //默认回到首页    return {        title,        imageUrl,        path,    }}复制代码

4.随机生成字符串

function getRandomString() {    let str = "",        range = 30,        arr = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'];    // 随机产生    for (let i = 0; i  range; i++) {        str += arr[Math.round(Math.random() * (arr.length - 1))];    }    return str;},复制代码

版权声明

即速应用倡导尊重与保护知识产权。如发现本站文章存在版权问题,烦请提供版权疑问、身份证明、版权证明、联系方式等发邮件至197452366@qq.com ,我们将及时处理。本站文章仅作分享交流用途,作者观点不等同于即速应用观点。用户与作者的任何交易与本站无关,请知悉。

产品经理

手机 : 13312967497

擅长 : 小程序流量变现

扫码领取礼包

最新资讯

热门模板

  • 头条
  • 搜狐
  • 微博
  • 百家
  • 一点资讯
  • 知乎