マイクロ信ウィジェット開発ピット記録

34191 ワード

最近、彼女のために微信の小さなプログラムを実現する必要があるので、小さなプログラムの開発を理解しました.微信ウィジェットの開発には以前はまったく接触したことがありません(しかし、いくつかの先端の开発経験があります)、完全な初心者として、资料を手に入れるのはきっと微信の小さいプログラムの开発のドキュメントで、ここ数日の开発の过程の経験から见て、先に详しく公式サイトのドキュメントを过ごしたほうがいいです.大部分のピットは详しくドキュメントを読んでいないためで、もう一部のピットはドキュメントが书いていないためです.
注:プロジェクトアーキテクチャは:C/Sアーキテクチャで、前後の端は完全に分離して、フロントエンド:微信の小さいプログラム、バックエンド:springboot
開発過程で遭遇したピットは主に以下の点である.
  • 微信登録実装モジュール開発ドキュメントでは、ログインロジックの記述が明確で、まずウィジェットでwxを呼び出す.login()は、微信が提供する一時登録証明書codeを取得し、codeを開発者サーバ(私たちのバックエンドサーバ)に転送し、バックエンドは申請した専用appidとappsecret、code(さっきフロントエンドから送られてきたcode)を3つのパラメータとして使用し、微信ライセンスurl(https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code(APPID、すなわちappid、SECRET、すなわちappsecret、JCODE、すなわちcode、その他は変わらない))、微信授権センターは2つのフィールドを返す:ユーザーはOpenIDとセッションキーsession_keyを一意に識別する;安全のためにsession_keyをsessionIdとしないのが一般的であり、自分でsessionIdを生成する.私はjwt技術を用いて実現したsessionIdの生成と検証である.javaは世代を実現する.コード:
  • @PostMapping("/wxLogin")
        public Result wxLogin(LoginVo loginVo) {
            log.info("wxLogin request:{}", loginVo);
            String url = "https://api.weixin.qq.com/sns/jscode2session";
            Map<String, String> param = new HashMap<>();
            param.put("appid", Constants.WEIXIN_APPID);
            param.put("secret", Constants.WEIXIN_SECRET);
            param.put("js_code", loginVo.getCode());
            param.put("grant_type", "authorization_code");
    
            String wxResult = HttpClientUtil.doGet(url, param);
            log.info("weixin response:{}", wxResult);
    
            WXSessionVo wxSessionVo = FastJsonUtil.fromJson(wxResult, WXSessionVo.class);
            if (wxSessionVo == null){
                return Result.fail(LOGIN_FAIL.getDesc(), LOGIN_FAIL.getCode());
            }
            UserInfo oldUserInfo = userInfoService.queryByOpenId(wxSessionVo.getOpenid());
            String token = "";
            if (oldUserInfo == null) {
                //     
                UserInfo newUserInfo = new UserInfo();
                newUserInfo.setHeaderUrl(loginVo.getHeaderUrl());
                newUserInfo.setUserName(loginVo.getUserName());
                newUserInfo.setOpenId(wxSessionVo.getOpenid());
                newUserInfo.setGmtDate(System.currentTimeMillis());
                userInfoService.save(newUserInfo);
                log.info("after userInfoService save, userInfo:{}", newUserInfo);
                token = TokenUtil.sign(newUserInfo.getId());
            } else {
                token = TokenUtil.sign(oldUserInfo.getId());
            }
    
            return Result.success(token);
        }
    @Data
    public class LoginVo implements Serializable {
        private String userName;
    
        private String headerUrl;
    
        private String code;
    
        private static final long serialVersionUID = 1L;
    
    
    }
    

    フロントエンドコード実装:
    wx.login({
                success: function(res) {
                    var code = res.code; //    
                    if (code) {
                        //2、          
                        wx.getUserInfo({
                            success: function(res) {
                                app.globalData.userInfo = res.userInfo;
                                //3.        ,
                                var argu = {
                                    code: code,
                                    userName: res.userInfo.nickName,
                                    headerUrl: res.userInfo.avatarUrl,
                                }
                                //      wx.request    http  ,     ,     wx.request  
                                httpClient.login(argu).then((data) => {
                                    console.log("login http", data);
                                    if (data.status == 200) {
                                    //   token      http    header ,         token         
                                        app.globalData.token = data.data;
                                        //        ,         
                                        wx.switchTab({
                                            url: '../index/index'
                                        })
                                    } else {
                                        wx.switchTab({
                                            url: '../auth/auth'
                                        })
                                    }
                                }).catch(e => console.log(e));
                            },
                            fail: function() {
                                console.log('        ')
                            }
                        })
                    } else {
                        console.log('         !' + r.errMsg)
                    }
                },
                fail: function() {
                    console.log('    ')
                }
            });
    

    ここで強調しなければならないのは、このログイン許可ページは単独のページで、トップページではありません.では、どのようにしてウィジェットのロードを実現するときに、まずこのページを起動してログインに成功してからトップページにジャンプしますか?グローバル構成では、配列の最初の項目はウィジェットの初期ページ(トップページ)を表し、この権限ページをpagesの最初の項目に置くだけで最初に実行できます.ログインに成功した後、本当のトップページにジャンプします.
    //app.json
    {
      "pages": ["pages/auth/auth", "pages/index/index"]
    }
    

    注:私は当時、公式ドキュメントをよく読んでいなかったので、githubからダウンロードしたdemoからログイン許可のページがトップページに呼び出されていませんでしたが、トップページより先に実行されたので、疑問に思っていました.長い間調べていたが、page構成の順序の問題だと疑って、ドキュメントを読み直してから答えがそうだったことに気づいた.
  • button以外のボタンはbindtap="clickFunctionName"でクリックして対応するメソッドをトリガした後、特定のパラメータを渡す必要があります.
  • シーン:forループで文章リストを表示するitemデータに対して、あるデータをクリックして、対応する方法をトリガーするが、このデータの一意の表示id
  • を知る必要がある.
  • 実装方式:wxmlでdata-parameterを使用する方式で、実装方法toDiary:function(event)をクリックするとparameterのvalue、すなわちjsでeventを使用することができる.currentTarget.dataset.patameterはバインドされた値を取得できます.複数のパラメータを入力する必要がある場合は、複数のdata-parameterを設定すればいいです.


  • 注意:ここに大きな穴があります.javaの命名パラメータに慣れる方法-アルパカの命名法です.data-parameterがパラメータをバインドするときは、eventオブジェクトではparameterNameが自動的に小文字に変換されるので、wxmlではdata-tranctionId=「1」など、反人間の設定は本物の穴です.そしてjsのe.currentTarget.dataset.tranctionId、これではtranctionIdの値は永遠に取得できませんが、e.currentTarget.dataset.tranctionidはtranctionIdを取得できる値である.したがって、ウィジェットでは、data-tranctionId="1"であるか、data-tranctionid="1"であるかにかかわらず、jsは、e.currentTargetを小文字で命名するしか取得できない.dataset.tranctionidパラメータ値.
     <view class="content"  data-tranctionid="{{item.id}}" data-type="{{item.type}}" bindtap="toDiary">
    
    toDiary: function(e) {
        console.log("toTopicOrDiary click", e)
        if (e.currentTarget.dataset.type == app.globalData.publishTypeEnum.topic) {
    wx.navigateTo({
          url: '../topic/topic?topicId='+e.currentTarget.dataset.tranctionid
        })
        }else{
          wx.navigateTo({
          url: '../diary/diary?diaryId='+e.currentTarget.dataset.tranctionid
        })
        }
      },
    
  • フロントエンドページurlジャンプ、新しいページでurlリンクのパラメータを取得
  • シーン:文章リストから、謀編文章をクリックして文章詳細
  • にジャンプ
  • 実装方式:通常のweb jsがurl上のパラメータを取得する方式とは異なり、微信ウィジェットでは、url中のパラメータを新しいページonload(options)方法のoptionsオブジェクトに配置し、パラメータvalueを取得する方式は、options.parameterName.

  • // url: '../topic/topic?topicId='+e.currentTarget.dataset.tranctionid
    onLoad: function(options) {
        console.log('options', options);
        var diaryId = options.topicId;
     }
    

    ここでurlのパラメータネーミングにはアルパカネーミング法を使用できますが、optionsのparameterNameでは小文字に変換されません.
  • ダイナミックデータバインド後、jsで変数の値をどのように変更するか、ページで変数の新しい値
  • を自動的にレンダリングします.
  • シーン:文章のコメント数表示、クリックして文章の詳細を見ると、まずバックエンドに行って現在のコメント数を手に入れて、それから私は下にコメントを追加したので、コメント数は1を追加します.
  • 実装形態
  • <view class="operation-btn flex-item">
         <text>{{commentNum}}</text>
     </view>
    //js
    data: {
    commentNum: 0
    },
    //  data        :
    1. this.data.commentNum = this.data.commentNum + 1;
    2. this.setData({
       commentNum: this.data.commentNum + 1
    })
    //      ,   ,    js commentNum  ,       commentNum        ,
    //                commentNum      。           ,,,
    
  • uploaderコンポーネントアップロード画像
  • シーン:画像をアップロードするために、微信公式にweUIフレームワークを提供するuploaderコンポーネントを直接使用しました.正直に言うと、小さなプログラム開発の新しいシロのためか、コンポーネントdemoが簡単すぎて、自分のサーバーにアップロードする方法や、マルチマップアップロードの問題をどのように実現するかを感じました.
  • 実現方式:
  • uplaodFile(files) {
        console.log('upload files', files)
        var _this = this;
        //       ,    promise
        return new Promise((resolve, reject) => {
          for (var i = 0; i < files.tempFilePaths.length; i++) {
            wx.uploadFile({ //    wx.uploadFile,   wx.request,          ,     , github      demo     
              url: URL.UPLOAD_DIARY_FILES, //             
              filePath: files.tempFilePaths[i],
              name: 'file', //     ,          
              formData: {},
              header: {
                "Content-Type": "multipart/form-data", //      form-data  
                'Authorization': app.globalData.token
              },
              success: (res) => {
                //        ,              id
                //      ,    wx.request        ,  return     data res.data ,   data jsonString(     ),   json  ,
                //   data.data    ,                      ,     json  JSON.parse,       ,           ,,,,
                var data = JSON.parse(res.data);
                _this.data.picUrlIds.push(data.data);
              },
              fail: (err) => {
                console.log("error", err)
              }
            })
          }
        })
      },
    

    注:ウィジェットに特殊な役割があるため、ウィジェットのすべてのソースコードを共有しません.ご了承ください.もし小さい仲间はどんな问题があるならば、评论して共に学习を探求することができて、结局私もただ1つのちょうど上手な白です.