*是的,在这个框架满天飞的年代,我既然有有幸应用了原生小程序开发我的项目,除了麻烦些,倒也不是满载而归,耕耘总有收货嘛,写博客自身不是为了炫技还是什么,单纯的是忘性不好,有些知识点 本人是花了工夫去查找的,工夫久了,下次会忘,所以仅做记录的成份高一些,前言不搭后语莫怪。而后早上看到一句诗也不错:追风赶月莫停留,平芜止境是春山。
回正题吧:*

上传头像

changeAvatar() {    var that = this;    wx.chooseImage({      count: 1, // 最多能够抉择的图片张数,默认9      sizeType: ['original', 'compressed'], // original 原图,compressed 压缩图,默认二者都有      sourceType: ['album', 'camera'], // album 从相册选图,camera 应用相机,默认二者都有      success: async function (res) {        var avatar = res.tempFilePaths;        await that.filebBatchDeletes()        let resImage = await uploadImage(avatar[0])        if (resImage.data.code == 200) {          that.setData({            avatar: avatar[0],            picId: resImage.data.result          })        }      },      fail: function () {        // console.log("上传图片没有胜利");      },      complete: function () {        // complete      }    })  },export const uploadImage = (uploadFile: string) => {  return new Promise((resolve, reject) => {    wx.uploadFile({      url: config.otherBaseUrl + 'load/file-upload',      filePath: uploadFile,      header: {        "Content-Type": "multipart/form-data",        'token': wx.getStorageSync('accessToken'),      },      formData: {        'caseNum': wx.getStorageSync('userId'),        "caseType": 'image',      },      name: 'file',      success: (res) => {        const data = JSON.parse(res.data)        resolve({ data })      },      fail: (err) => {        reject(err)      }    })  })}

前端小程序拿到图片流解决成Base64async

 readImageByDataIds(id: string) {    let res = await getPicStream(`/readImageByDataId/${id}`)    this.setData({      processPic: res    })  },export const getPicStream = (url:string) => {  return new Promise((resolve,reject) => {    wx.request({      url: config.baseUrl + url,      header: {        'X-Access-Token': wx.getStorageSync('token'),        'X-TIMESTAMP': getDateTimeToString(),      },      responseType: 'arraybuffer',      success: res => {        let url ='data:image/png;base64,'+ wx.arrayBufferToBase64(res.data)        resolve(url)      },      fail: err => {        reject(err)      }    })  })}

返回上一个页面并触发上一个页面的办法因为小程序不像浏览器会主动刷新,所以须要手动刷新

var pages = getCurrentPages();      var beforePage = pages[pages.length - 2];      wx.navigateBack({        delta: 1,         success: function () {          beforePage.getInfo(); // 执行前一个页面的getInfo办法        }      })

Base64模式的文件做预览

preClick(event: any) {    if (event.detail.type == 'file') {      const fileSystemManager = wx.getFileSystemManager()      try {        let strPath = event.detail.url.substring(event.detail.url.indexOf(',') + 1)        fileSystemManager.writeFileSync(wx.env.USER_DATA_PATH + `/${event.detail.materialName}`, strPath, "base64");        wx.openDocument({          filePath: wx.env.USER_DATA_PATH + `/${event.detail.materialName}`        })      } catch (err) {        console.log("调用失败", err);      }    }    return true  }

v-button自定义通明用于绑定或获取用户信息

<button bind:getuserinfo="onGetUserInfo" open-type='{{openType}}'  plain='{{true}}' class="container">  <slot name="img"></slot></button>Component({  /**   * 组件的属性列表   */  options: {    multipleSlots: true // 在组件定义时的选项中启用多slot反对  },  // externalClasses: ['ex-btn-class'],  properties: {    openType: {      type: String    },    imageSrc: {      type: String    },    bindgetuserinfo: {      type: String    }  },  /**   * 组件的初始数据   */  data: {  },    /**   * 组件的办法列表   */  methods: {    onGetUserInfo(event) {      this.triggerEvent('getuserinfo', event.detail, {})    },  }}).container{  padding: 0 !important;  border:none !important;}

一个小程序跳转到另一个小程序

async getPayInfos(item:any) {    const { buildId, id, estateId } = item    let params = {      buildId,      estateId,      houseId: id,    }    let infos = await getPayInfo(params)    let that = this    wx.navigateToMiniProgram({      appId: 'wxe7550',  //appid      path: `pages/index/index?token=${infos.data.payData}`,//path      success(res) {        that.data.isPay = true    that.data.mchOrderNo = infos.data.mchOrderNo      }    })  },

wxs

wxs是小程序的一套脚本语言 ,联合WXML,能够构建出页面的构造  wxs不依赖于运行时的根底库版本  能够在所有版本的小程序中运行wxs与javascript是不同的语言  有本人的语法 并不和javascript统一wxs的运行环境和其余javascript代码是隔离的  wxs不能调用其余JavaScript文件中定义的函数  也不能调用小程序提供的APIwxs函数不能作为组件的事件回调与es5类似,不能用es6的语法这里作为独自文件应用


也可间接写在wxml文件中

<block wx:for="{{util.limit(comments,15)}}">        <tag-cmp class="tag" text="{{item.content}}">          <text class="num" slot="after">{{'+' + item.nums}}</text>        </tag-cmp>  </block><wxs module="util">  var limit = function(array, length) {    return array.slice(0, length)  }  var format = function(text){    if(!text){      return    }    var reg = getRegExp('\\\\n','g')    var text = text.replace(reg,'\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;')    return text  }  module.exports = {    limit: limit,    format:format  }</wxs>

属于wxs的正则

点击事件

  • bind事件 catch事件
  • bind事件绑定不会阻止事件冒泡   
  • catch事件能够阻止事件向上冒泡

    <view bind:tab="handleClick"></view>   <view catch:tab="handleClick"></view>wx:for遍历 <block wx:for="{{data}}">  <v-item item="{{item}}"></v-item> </block>

    表单校验要本人写表单,所以也要本人写校验

    应用的是WxValidate.jsWxValidate的验证规定: 
    (1)required:true/false,是否为必填字段。
    (2)email:true/false,是否恪守电子邮件格局。
    (3)tel:true/false,是否恪守11位手机号码。
    (4)url:true/false,是否恪守域名格局。
    (5)idcarad:true/false,是否恪守18位身份证号格局。
    (6)digits: true/false,只能输出数字。
    (7)min:数值,指定最小值。
    (8)max:数值,指定最大值。
    (9)range:[min,max],指定范畴。
    (10)minlength:数值,指定起码输出的字符个数。
    (11)maxlength:数值,指定最多输出的字符个数。
    (12)rangelength:[minlength,maxlength],指定输出字符个数的范畴。
    (13)dateISO:true/false,压服恪守日期格局(yyyy-mm-dd、yyyy/mm/dd)。
    (14)equalTo:字符串,指定必须输出完全相同的内容。
    (15)contains:字符串,指定必须输出蕴含指定字符串的内容。 

  • 办法就不说了,简略且繁琐,为什么只写规定,规定不好找*

    小程序的跳转

    小程序的跳转分为两种:页面跳转   保留以后页面,跳转到利用内的某个页面

    wx.navigateTo({ url: "/pages/login/login" })

    敞开以后页面,跳转到利用内的某个页面
    `wx.redirectTo({
    url: ''
    }`
    敞开所有页面,关上到利用内的某个页面

    wx.reLaunch 办法则会清空以后的堆栈 通过wx.navigateBack没有可返回的页面了

    底部tab跳转跳转到 tabBar 页面,并敞开其余所有非 tabBar 页面
    `wx.switchTab({
    url: '/index'
    })`

    小程序的事件传参

    data- 自定义属性传参,其中  代表的是参数的名字例子:

    <view class="homeItem" bindtap="goList" data-showType="add">

    事件内可通过e.currentTarget.dataset.showtype拿到值

    goList(e: any) {cosole.log(e.currentTarget.dataset.showtype) //留神这里showtype 可不是写错,而是小程序会把小驼峰大写转成小写}

    onPullDownRefresh onReachBottom  下拉刷新 上拉加载

    Page({ freshList(){    let myList = this.selectComponent("#yg-list")    myList.pullList()  },  onReachBottom: function() {    let myList = this.selectComponent("#yg-list")    myList.getList()  },  onPullDownRefresh:function(){    this.freshList()  },

    可在app.json配置在间隔什么地位触发

    "window": {    "backgroundTextStyle": "light",    "navigationBarBackgroundColor": "#fff",    "navigationBarTitleText": "",    "navigationBarTextStyle": "black",    "enablePullDownRefresh": true,//开启下拉刷新    "onReachBottomDistance":100,//可在app.json配置在间隔什么地位触发  },

    原本认为这个没有什么难的,然而还是踩坑了

  • 若页面不小心写了两个onReachBottom, 这个事件是不会触发的
  • 上拉加载,下拉刷新只能用在page页面组件中,在Component组件外面不触发的所以在page页面监听到达到页面的底部,如何告诉列表组件的加载更多,引出上面的小程序中触发子组件的形式

    小程序中触发子组件的办法

    那这里用上上个例子的代码

    <yg-list applyStatus="1" id="yg-list"/>onReachBottom: function() {//滚动到底部告诉子组件加载新的数据    let myList = this.selectComponent("#yg-list")   myList.getList()  }

    小程序组件中子组件触发父组件的的办法,

    在这里触发indexFunction函数

     <button bindTap="clickTap">点击</button>    clickTap:function(){      this.triggerEvent('indexFunction',{value:this.properties.count})    }

在父组件中

<yg-list bind:indexFunction="indexFunction"/>       Page({      indexFunction:function(e){        console.log('父容器中的办法被调用了',e);      }    })

wx:if 与 hidden

*wx:if 与hidden都能够管制微信小程序中元素的显示与否。
wx:if不满足条件是不渲染,hidden是暗藏对于性能这一块,
hidden页面的暗藏代替页面跳转,不会从新触发ready  或者created生命周期。
所以具体用法与vue的v-if和v-show类似*

小程序组件

如果写小程序每个页面纯手写反复的列表,表单,太臃肿,
所以必定要写组件,组件的应用形式:
外层创立components文件夹,在外面写组件,
如果其中一个页面须要应用这个组件,可在以后页面的json中配置

{  "usingComponents": {    "yg-list":"/components/yg-list/yg-list"  }}

组件传值 properties 相似于vue的props

//在properties外面定义咱们要的属性 properties: {    btText: {      value: '默认值',//value示意默认值      type: String   //type是咱们定义的类型,这里是String字符串类型    }  },

组件本身的办法定义在methods,同vue一样

methods: {   showLog:function(){   } }组件应用插槽 Comment({      options:{        muitipleSlots:true  //开启插槽}   })<view class="container">    <slot name="before"></slot><text>{{text}}</text>   <slot name="after"></slot> </view>应用<v-tag> <text text="哈哈" slot="after">{{text}}</text></v-tag>

组件的内部款式externalClasses的应用

*子组件定义一个内部款式名字 
子组件的元素用上这个类名*

Comment({     externalClasses:['my-class']    })<view class="my-class">{{text}}</view>

在父组件应用这个组件的时候 是在父组件中定义的款式

<yg-list my-class="yg-class"></yg-list>.yg-class{color:red;}

*留神:若是以后子组件的元素上还有别的款式,那组件内的款式会笼罩内部款式,
所以在父容器编写款式的时候,前面可加上impotant,晋升等级关系。*

组件的behaviorbehaviors

  • 是小程序中,用于实现组件间代码共享的个性,
  • 相似于 Vue.js 中的 “mixins”
  • 每个 behaviors 能够蕴含一组属性、数据、生命周期函数和办法。
  • 组件援用它时,它的属性、数据和办法会被合并到组件中,每个组件能够援用多个behaviors,- - behavior也能够援用其它behavior。
  • 在外层创立一个文件夹behavior,外面可放各个用处的behavior js文件,
    创立一个behavior文件

    let classicBeh = Behavior({      properties:{          img:String,          content:String        },        data:{},      methods:{}    })    export {classicBeh}在组件中应用 import { classicBeh } from '../behaviors/classicBeh.js'    Comment({      behaviors: [classicBeh]    })

    behavior与组件的优先级若遇到重名的状况,组件会笼罩behavior,
    然而如果是生命周期,会先执行behavior内的,再执行组件内的

    小程序中引入lodash

    在utils文件夹下新建lodash.js
    文件把压缩过的lodash.min.js文件内容放进去间接引入会报错
    再创立一个lodash-fix.js文件

    /** * 修复 微信小程序中lodash 的运行环境 */global.Object = Object;global.Array = Array;// global.Buffer = Bufferglobal.DataView = DataView;global.Date = Date;global.Error = Error;global.Float32Array = Float32Array;global.Float64Array = Float64Array;global.Function = Function;global.Int8Array = Int8Array;global.Int16Array = Int16Array;global.Int32Array = Int32Array;global.Map = Map;global.Math = Math;global.Promise = Promise;global.RegExp = RegExp;global.Set = Set;global.String = String;global.Symbol = Symbol;global.TypeError = TypeError;global.Uint8Array = Uint8Array;global.Uint8ClampedArray = Uint8ClampedArray;global.Uint16Array = Uint16Array;global.Uint32Array = Uint32Array;global.WeakMap = WeakMap;global.clearTimeout = clearTimeout;global.isFinite = isFinite;global.parseInt = parseInt;global.setTimeout = setTimeout;应用import "../../utils/lodash-fix.js"import _ from "../../utils/lodash"

    应用

     getBuildList: _.throttle(function (str: any) {    const { cellId, searchCell } = this.data    lifePayModels.getBuild({ estateId: cellId, buildName: searchCell }, (res => {      let arr = res.map(item => {      return {          label: item.buildName,        value: item.id        }      })      this.setData({      columns: arr    })    }))  }, 3000),

    第三方库

    Vant  Weappvan-dialog
    van-field model:value反对双向绑定
    van-dialog给外面的输入框做校验的时候,它会敞开,所以这里用上beforeClose阻止默认敞开事件

    <van-dialog use-slot   data-showType="rejectShow"   show="{{rejectShow}}"  show-cancel-button  confirm-button-open-type="toReject"   beforeClose="beforeClose"  bind:close="closeDialog">    <van-field    model:value="{{rejectComment}}"   label=""    type="textarea"      placeholder="驳回起因"    autosize      required/></van-dialog>Page({      data: {          beforeClose (action) {            return new Promise(resolve => {              setTimeout(() => {                if (action === 'confirm') {                // 拦挡确认操作                  resolve(false)                } else {                  resolve(true)                }              }, 0)            })          }    },     toReject(){      if(!this.data.comment){        tips('请填写起因')                return      }          this.setData({        show:false      })        }    })

    微信领取


    具体的做法:

  • 关上某小程序,点击间接下单 wx.login获取用户长期登录凭证code,发送到后端服务器换取
  • openId 在下单时,小程序须要将购买的商品Id,商品数量,以及用户的openId传送到服务器
  • 在下单时,小程序须要将购买的商品Id,商品数量,以及用户的openId传送到服务器
  • 服务器在接管到商品Id、商品数量、openId后,生成服务期订单数据,同时通过肯定的签名算法,向微信领取发送申请,获取预付单信息(prepay_id),同时将获取的数据再次进行相应规定的签名,向小程序端响应必要的信息 
  • 小程序端在获取对应的参数后,调用wx.requestPayment()发动微信领取,唤醒领取工作台,进行领取  
    6 接下来的一些列操作都是由用户来操作的包含了微信领取明码,指纹等验证,确认领取之后执行鉴权调起领取
    7鉴权调起领取:在微信后盾进行鉴权,微信后盾间接返回给前端领取的后果,前端收到返回数据后对领取后果进行展现
    8 推送领取后果:微信后盾在给前端返回领取的后果后,也会向后盾也返回一个领取后果,后盾通过这个领取后果来更新订单的状态
    9 其中后端响应数据必要的信息则是wx.requestPayment办法所须要的参数,大抵如下:``wx.requestPayment({
    // 工夫戳
    timeStamp: '',
    // 随机字符串
    nonceStr: '',
    // 对立下单接口返回的 prepay_id 参数值
    package: '',
    // 签名类型
    signType: '',
    // 签名
    paySign: '',
    // 调用胜利回调
    success () {},
    // 失败回调
    fail () {},
    // 接口调用完结回调
    complete () {}
    })``
    留神:以上信息中timeStamp、nonceStr、prepay_id、signType、paySign各参数均倡议必须都由服务端返回(这样会尽最大可能性保障签名数据一致性),小程序端不做任何解决
    官网领取文档地址https://pay.weixin.qq.com/wik...
    后端的操作 https://juejin.cn/post/706331...

    引入离线iconfont字体图标

https://blog.csdn.net/qq_1506...

域名不非法的解决

小程序刚开始开发的时候测试环境个别都是关上
不测验非法域名然而当咱们发测试版本或者发生产环境的时候,
发的小程序是不申请接口的,这是因为咱们没有设置非法域名,
在这里设置,留神域名必须是https的

扫二维码调到小程序指定页面首先微信平台设置

设置地位: 开发治理 开发设置(最初生成连贯公布的时候要确定 代码曾经在线上)


而后能够拿着这个url去生成二维码

而后在以后页面承受参数,判断是否已绑定手机号,登录

onLoad(options: any) {    if (options.q) {      let url = decodeURIComponent(options.q)      let obj = this.getUrlParam(url)      this.initPhone()      this.setData({        cellName: obj.estateName,        cellId: obj.estateId,        isRead: true      })    }},  getUrlParam(url) {    let params = url.split("?")[1].split("&");    let obj = {};    params.map(v => (obj[v.split("=")[0]] = v.split("=")[1]));    return obj  }

wx.nextTick

提早一部分操作到下一个工夫片再执行
应用办法同vue的this.$nextTick

 getUrlParam(url) {    let params = url.split("?")[1].split("&");    let obj = {};    params.map(v => (obj[v.split("=")[0]] = v.split("=")[1]));    return obj  },onLoad(options: any) {    this.initPhone()    if (options.q) {      let url = decodeURIComponent(options.q)      console.log("url", url);      let obj = this.getUrlParam(url)      if (Reflect.ownKeys(obj).length > 0) {        wx.nextTick(() => {          this.setData({            cellName: obj.estateName,            cellId: obj.estateId,            isRead: true,          })        })      }    }  },

最初如果以后文章给了你提醒和帮忙,还心愿点赞和关注,激励,谢谢啦