微信小程序(wepy)

1.連接: blog.csdn.net/qq_26585943…vue

www.jianshu.com/p/0078507e1…web

微信小程序開發(wepy框架)

佈局: rpx 設計稿750px, 設計稿多大就寫多大的

1、生命週期(app.js)

  • onLaunch 用戶首次打開小程序,觸發 onLaunch(全局只觸發一次)這裏作第三方開發平臺自定義配置項 注意: ext.json也能夠覆蓋本地的配置項目,例如小程序跳轉小程序就是在ext.json能夠進行配置,手機掃碼會進行讀取ext.json進行覆蓋本地的配置
  • wx.getExtConfigSync() 動態讀取ext 字段自定義的數據字段

  • onLoad[(options)] 加載小程序,options參數攔截,模塊只能觸發一次,tabbar菜單, 頁面模塊進行切換不進行調用了, 頁面是每次都會調用的

涉及到模塊頁面是不是是及時更新,若是及時更新放到onShow裏面vuex

  • onHide 進入後臺,進程沒有殺死
  • onError 錯誤監聽函數 當小程序發生腳本錯誤,或者 api 調用失敗時,會觸發 onError 並帶上錯誤信息
  • 順序 onLuach => onLoad => onHide

頁面生命週期(page.js):

  • onLoad --監聽頁面加載
  • onShow --監聽頁面顯示
  • onReady --監聽頁面初次渲染完成
  • onHide --監聽頁面隱藏
  • onUnload ---監聽頁面卸載
    • 其中,打開小程序後會依次執行onLoad => onShow => onReadyjson

    • 先後臺切換會分別執行onHide和onShow方法,redux

    • 當小程序頁面銷燬時會執行 onUnload方法canvas

    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() {
      ....
    }
    
    
    複製代碼

2、配置文件. 小程序配置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 全局方法 , 全部頁面均可以共用的,通常外鏈文件

3、頁面配置信息 conifig (重點)

app.json配置若是和頁面配置衝突了,那麼會採用頁面配置的微信小程序

  • navigationBarTitleText title
  • navigationBarTextStyle 字體顏色 ["white" /"blank"]
  • enablePullDownRefresh 是否下拉屬性
  • disableScroll 是否能夠滾動
  • disableSwipeBack 是否能夠IOS左滑返回上一級,或着關閉小程序

4、一個wpy文件的組成

  • template模板,結構
  • script腳本
    1. data頁面數據 this.xxx = xxx; 進行修改
    2. methods 頁面方法 @綁定的 內置的方法
    3. events 是子組件傳遞的方法 $emit子元素傳父元素事件 .sync props對象進行接收設置twoWay: true父元素下發的數據更新子元素跟着改變
    4. watchs 監聽數據 數據發生改變進行處理

5、 微信受權登陸流程

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

<script>
import 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();
    }
}

複製代碼

6、項目問題總結:

  • 獲取公共數據
    • 頁面內採用: this.$parent ==> [ app = getApp() ]
    • 組件內部: this.parent.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 的切換)api

  • 自定義底部導航和內置tabBar導航promise

  • 自定義組件

  • 解析 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;
複製代碼

7、經常使用方法封裝

  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;
},
複製代碼
相關文章
相關標籤/搜索