乐趣区

关于小程序:微信小程序归结

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

上传头像

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 = Buffer
    global.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,
          })
        })
      }
    }
  },

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

退出移动版