微信小程序技术总结

2,034 阅读21分钟

运行环境

微信小程序是运行在微信环境中的,小程序的逻辑层和渲染层是分开的,逻辑层运行在 JSCore 中。所以是无法调用DOM和BOM中的API。不过小程序自己提供了各种API,但是有的需要开通权限,真烦人,想骂人。

小程序注册

客户不知道小程序如何注册的情况下,需要大概告知操作界面在哪。

企业微信截图_16966603902735.png 微信图片_20231011092049.png

进入公众号找的小程序管理,选择快速注册小程序即可进行注册。

微信图片_20231011092340.png

根据提示进行账号注册。

微信图片_20231011092419.png 成功之后让客户填写小程序信息,小程序类目,添加开发权限。

微信图片_20231011092525.png

微信图片_20231011092541.png

添加完成之后即可开发小程序了。

客户如果遇见这种情况,直接让客户登录小程序就行。 微信图片_20231011092750.png

基础目录结构

pages 用来存放所有小程序页面。

utils 用来存放工具性质的模块。

api 统一管理api接口。

其余的文件根据项目需要进行划分, 如components文件 就是存放公共组件模块。

image.png

json文件配置

app.json 是小程序的全局配置,包括了小程序的所有页面路径,窗口外观,底部tab等。当中的style字段这是样式版本,加上style和删除style,这样会使用小程序组件样式是不一样。

image.png

project.config.json 是项目配置文件,记录小程序开发工具所做的个性化配置,如项目名称,小程序账号ID等

sitemap.json 小程序内搜索,类似于网页的SEO,配置是否允许微信索引。

页面中的json 小程序每个页面中的json,配置本页面的窗口外观,会覆盖app.json的window中相同配置项。

页面渲染过程

1.加载解析页面的json文件配置。

2.加载页面wxml和wxss样式。

3.执行页面js文件,调用Page()创建页面实例。

4.页面渲染完成。

小程序单向数据流

单向数据流就是从逻辑层到视图层,vue也是单向数据流Model - view,但是实现了双向数据绑定。而小程序没有做劫持代理,所以不能进行双向数据绑定。但现在小程序是有双向数据绑定这个概念的,叫简易的双向数据绑定。

胶囊按钮

需求:logo需要同右边的胶囊按钮顶部对齐。

解决方法:使用 wx.getMenuButtonBoundingClientRect()

image.png


输出下 wx.getMenuButtonBoundingClientRect(),可以看见胶囊按钮的信息,需要注意的是单位为px。

image.png

wx.getMenuButtonBoundingClientRect().top就能获取到胶囊按钮距离信息栏的距离,然后将px转为rpx。

//视图层
<view style="height:{{logHeight}}rpx"></view>

//逻辑层
  data: {
      //logo图片高度,加入默认高度,防止页面渲染时图片闪动。
      logHeight:60,
  },

  attached:function(){
    let height=wx.getMenuButtonBoundingClientRect().top//获取顶部距离,单位是px  
    let deviceWidth = wx.getSystemInfoSync().windowWidth; //获取设备屏幕宽度
    let capsuleTop = (750 / deviceWidth) * height //得到rpx的值
    this.setData({
      capsuleTop
    })
  },

获取一个元素信息

需求:获取一个图片的高度,自适应图片宽度变化,高度也会变化。

解决办法:wx.createSelectorQuery()

注意两点:

1.要在ready函数中执行

2.在组件中使用wx.createSelectorQuery()之后,要用in()来指定范围。(将选择器的选取范围更改为自定义组件 component 内)或者在自定义组件或包含自定义组件的页面中,应使用 this.createSelectorQuery() 来代替

   视图层
   
   <image id="logoImg"  src="xxx.jpg" mode="widthFix"/>
   
   逻辑层
   
  //在组件在视图层布局完成后执行
  ready:function(){
    //加入定时器防止渲染时慢,无法获取节点。
    setTimeout(()=>{
      //创建节点选择器 ,in(this)传入组件实例防止获取为null,或者let query =this.createSelectorQuery()
      let query=wx.createSelectorQuery().in(this)
      //选择需要获取的元素
      query.select('#logoImg').boundingClientRect()
      //获取元素信息  
      query.exec(function(res){
        //获取元素高度(px)
        let clientHeight = res[0].height 
      })
    },120)

  },

输出下 query.exec(function(res){console.log(res)}) 会看见这个图片的信息,单位同样是px,需要转化成rpx。

image.png

this.setData修改对象、数组

直接在this.setData中直接修改,编译器会显示波浪线报错。

image.png

修改对象

data: { 
    list: { 
        deleted: false, 
        name: "设计模块" 
    } 
}

//对象.属性名:修改的值
this.setData({
    'list.deleted': true
})

修改数组

data: { 
    list: [ 
        {id: 1, deleted: false}, 
        {id: 2, deleted: false},
        {id: 3, deleted: false}
    ] 
}

this.setData({ 
    'list[0].deleted': true 
})

或者加入变量使用,用字符串拼接起来。

 data:[
      {"id":0,"name":'zs'},
      {"id":1,"name":'ddds'}
 ]
  
  let  newData="data["+0+"].name"
  
  this.setData({
    [newData]:"张三"
  })

 console.log(this.data.data) 

注:修改对象和数组都要用''包括起来

但下标总不能写死了,所以循环下就行了,主要就是赋值给新的变量,在新变量中进行修改数据,再进行this.setData。

data: {
    listData:[
      [
        { "id"0,"deleted"false},
        { "id"1,"deleted"false},

      ],
      [  { "id"3,"deleted"false}]
    ]
}



//先循环外成数组
for(let h=0;h<this.data.listData.length;h++){
  //在循环数组中的对象
  for(let k=0;k<this.data.listData[h].length;k++){
    //id进行比对,比如判断id是否等于0
    if(this.data.listData[h][k].id==0){
      //将赋值给新的变量
      let  temp = this.data.listData
      //如果这个对象中的deleted为false,就修改成true.
     if(this.data.listData[h][k].deleted==false){
      temp[h][k].deleted=true
     }else{
      temp[h][k].deleted=false
     }
     //更新数据
      this.setData({
        listData:temp
      })
    }
  }
}

//id为0的deleted变成true
console.log(this.data.listData)


  

image.png

小程序设计稿

为了方便开发,需要跟设计师沟通好设计稿以宽度750px,高度1334px。这样1px就会一比一换算1rpx,不需要进行转换。

使用px根据项目要求设置,将rpx和px结合使用。

小程序eCharts使用

第一步:进入eCharts官网点击下载选择下载,进入在线制定。按需要下载,减少体积

image.png

第二步:点击在线制定

image.png

第三步:选择需要的图形

image.png

第四步:下载

image.png

第五步:选择文档下的应用篇,选择跨平台方案,选择微信小程序

image.png

第六步:下载echarts-for-weixinecharts-for-weixin

image.png

用ec-canvas文件就行

image.png

第七步:将ec-canvas文件放入项目中

我这里是在组件中创建了echarts文件夹,就把ec-canvas文件中的文件全部放进去。注意如果是按需制定的echarts,将echarts.js替换成在线制定生成的echarts.min.js。

同时修改ec-canvas.js 中的 import * as echarts from './echarts'的引用文件。

image.png

第八步使用

配置组件使用

  "usingComponents": {
    "ec-canvas": "../echarts/ec-canvas"
  }

视图层

 <ec-canvas  id="mychart-dom-mapr" canvas-id="mychartBar"  ec="{{ ec }}"></ec-canvas>

逻辑层

//引入eCharts
import * as eCharts from '../../components/echarts/echarts'

  data: {
    ec: {
      onInit: initChart
    },
   }
   
   function initChart(canvas, width, height) {
         //绘制宽高
          let chart = echarts.init(canvas, null, {
            width: width,
            height: height
          });
          
           canvas.setChart(chart); //容器初始化
           echarts.registerMap('china', geoJson); //地图数据注册
           let option = {}
          
           chart.setOption(option); //返回初始化结果
           return chart;
   }

另外一种封装成组件

逻辑层

     /**
   * 组件的初始数据
   */
  data: {
    ec: {
      onInit: null
    },
  },
   
   //在组件实例进入页面节点树时执行
   attached:function(){
    this.setData({
      ec: {
        onInit: this.initChart
      }
    })
  },
   
   /**
   * 组件的方法列表
   */
  methods: {
    // eCharts 可视化地图
    initChart:function(e,width,height){
      //绘制宽高 地图模糊时候使用devicePixelRatio 调整清晰度
      const chart = eCharts.init(e,null,{
        width:width,
        height:height,
        devicePixelRatio: 2.5
      });

  //容器初始化
  e.setChart(chart); 
  //地图数据注册
  eCharts.registerMap('china', geoJson); 
  
  //初始化数据
  let option = {
      
  }
  chart.setOption(option); //返回初始化结果
  return chart;
},

大致效果:

image.png

navigateTo超出10个页面,粗糙解决办法

wx.navigateTo打开页面最多只能打开10个,超过10个之后就没反应,无法继续跳转。这是微信小程序的页面栈机制每次调用 wx.navigateTo 会向页面栈新增一层页面,页面栈最大深度为10 层。

生命周期触发

原页面:触发 onHide(页面隐藏),但未销毁。 目标页面:触发 onLoad(首次加载)、onShow(页面显示)

// 导航列表跳转对应页面
handleNavigate:function(e){
  //获取全局变量
  const app=getApp()
  //获取全局变量中adCenterPitchOn的值
  let adCenterPitchOn=app.globalData.adCenterPitchOn

  //判断如果当前选中的id与全局变量中adCenterPitchOn不相等进行跳转,相等就不进入跳转程序,减少重复跳转。
  if(e.currentTarget.dataset.id!=adCenterPitchOn){
    this.setData({
      pitchOn:e.currentTarget.dataset.id
    })
    
    
    //navigateTo跳转不能打开10个页面,需要进行判断超过10个页面就关闭所有页面,重新进行页面栈个数统计
    let pages=getCurrentPages()//获取当前打开的页面
    let pagesLength=pages.length//获取当前打开页面的数量
    
    //打开页面数量大于等于10 使用reLaunch关闭所有页面,重新进行页面栈个数统计。
    if(pagesLength>=10){
      
      wx.reLaunch({
        url:e.currentTarget.dataset.path,
      })
    }else{
      //小于10 就使用navigateTo
      wx.navigateTo({
        url: e.currentTarget.dataset.path,
      })
    }
  }
}

这里不直接使用reLaunch是因为会重新渲染,会关闭所有页面,打开新页面,跳转一次屏幕就会有闪动。所以进行粗糙的处理到了10个页面,使用reLaunch,十次之后才会闪动一次。

其他方法

1.redirectTo代替

描述:关闭当前页面,跳转到应用内的某个页面,不能跳转tabbar页面。不会增加页面栈,但这样就不能返回上一页。

参数传递:路径?参数名=参数值 多个参数传递:路径?参数名=参数值&参数名=参数值&参数名=参数值

动态路由策略:判断页面栈深度,自动切换redirectTo

smartNavigate(url) {
  const pagesList = getCurrentPages();
  if (pagesList.length >= 9) { // 预留一层空间
    wx.redirectTo({ url:'地址' });
  } else {
    wx.navigateTo({ url:'地址' });
  }
}

自定义tabBar

第一步:开启tabBar自定义

在app.json中找的tabBar加入custom:true

image.png

同时官方文档建议还是将list内容写上,用来兼容低版本。

image.png

第二步:创建目录

创建custom-tab-bar与pages同级。

image.png

第三步:custom-tab-bar中wxml编写

  <view 
  wx:key="index" 
  wx:for="{{list}}" 
  data-pagePath="{{item.pagePath}}" 
  data-index="{{index}}" 
  bindtap="getTabBarIndex"
  >
    <image  
    src="{{ selected===index? item.selectedIconPath : item.iconPath}}" 
    mode="widthFix>
    </image>
  </view>

第三步:tab-service工具类

创建一个工具类,用来处理custom-tab-bar切换

 //获取静态资源地址
 import config from '../config/config'

 //写好数据   
 let tabData = {
  selected:"",//当前选中tabBar
  list:[
    {
      "pagePath": "/pages/home/home",
      "iconPath": config.staticHost+"tabBar_home_def.png",
      "selectedIconPath": config.staticHost+"tabBar_home_active.png"
    },
    {
      "pagePath": "/pages/adCenter/adCenter",
      "iconPath": config.staticHost+"tabBar_advertising_def.png",
      "selectedIconPath": config.staticHost+"tabBar_advertising_active.png"
    },
    {
      "pagePath": "/pages/processing/processing",
      "iconPath": config.staticHost+"tabBar_data_def.png",
      "selectedIconPath": config.staticHost+"tabBar_data_active.png"
    },
    {
      "pagePath": "/pages/finance/finance",
      "iconPath": config.staticHost+"tabBar_money_def.png",
      "selectedIconPath": config.staticHost+"tabBar_money_active.png"
    },
    {
      "pagePath": "/pages/me/me",
      "iconPath": config.staticHost+"tabBar_me_def.png",
      "selectedIconPath": config.staticHost+"tabBar_me_active.png"
    }
  ]
}



// 更新底部高亮 获取下标,进行替换
const updateIndex = (that, index) => {
  tabData.selected = index
  updateTab(that, index)
}

// 更新Tab状态  点选选中效果不改变或者点击两次才改变解决办法
const updateTab = (that,index) => {
  if (typeof that.getTabBar === 'function' && that.getTabBar()) {
      //将值改为当前页面的下标
      that.getTabBar().setData(tabData);
  }
}

// 将可调用的方法抛出让外面调用
module.exports = {
   updateTab, updateIndex
}

第四步:custom-tab-bar中js逻辑层编写

点击时触发,进行跳转

 getTabBarIndex:function(e){
  //获取当前点击的下标及位置
  const tabBarData=e.currentTarget.dataset
  const presentPath=tabBarData.pagepath
  //跳转到对应页面,并关闭其他所有非 tabBar 页面
  wx.switchTab({
    url:presentPath,
  })
}

第五步:调用及高亮不变处理

在tab页引入const tabService = require("../../utils/tab-service");

const tabService = require("../../utils/tab-service");

Page({

  /**
   * 页面的初始数据
   */
  data: {
  },

  //将当前所在页的下标传入,解决选中没有高亮问题;
  onShow:function(){
    tabService.updateIndex(this, 4);
  },

})

image.png

获取机型

ios和android显示的效果会有差异,这就需要通过识别机型进行适配。

在app.js中使用 wx.getSystemInfoSync().platform获取手机型号

onLaunch() {
//获取机型
const res = wx.getSystemInfoSync().platform
//将机型放进缓存
if(res=='ios'){
    wx.setStorageSync('facility', "ios")
  }else{
    wx.setStorageSync('facility', "android")
 }
},

真机测试才行,模拟测试值是devtools

简单封装下wx.request

 //导入服务器配置信息
import config from '../config/config'

 export default (url,data,method='GET')=>{
  //初始化Promise实例
  return new Promise((resolve,reject)=>{
    wx.request({
      url:config.host+url,
      data,
      method,
      success:(res)=>{
        //成功之后修改Promise状态
        resolve(res)
      },
      fail:(err)=>{
        //失败之后修改Promise状态
        reject(err)
      }
    })
  })
 }
 
     

使用方法:

import req from '../../utils/request' //引入封装的地址
onLoad:async function(){
//获取数据
let pageImgData = await req('/cas/query')
},

关于传值的方法

全局变量使用

在app.js中使用globalData定义全局变量。

  // 定义全局变量
  globalData: {
    userInfo: null,
    tabBarIndex:0,
  }

app.globalData.变量名获取定义的变量值

 //获取全局变量
const app=getApp()
console.log(app.globalData.tabBarIndex)

//直接修改变量,不需要setData
app.globalData.tabBarInde=1

父组件传值给子组件

父组件使用子组件,传入父组件定义的值:tableHeaderData和tableList

     <DataList 
         tableHeader="{{tableHeaderData}}" 
         tableList="{{tableList}}" >
     </DataList>

子组件通过properties接收父组件传来的值

   /**
   * 组件的属性列表
   */
  properties: {
    //列表表头数据
    tableHeader:{
      type:Array,
      value:[],
    },
    //列表数据
    tableList:{
      type:Array,
      value:[]
    },
  },

父组件没有传值,子组件也不会报错。所以父组件可以按需传入相应得值。

    //父组件
   <DataList></DataList>
   
  //子组件接收值
  properties: {
    //列表表头数据
    tableHeader:{
      type:Array,
      value:[],
    },
  },

子组件传值给父组件

子组件通过triggerEvent给父组件传值

  //将值传给父组件
  this.triggerEvent("getLogHeight",62)      

父组件接收子组件传入的值

   //父组件使用子组进行件接收
   <NavLog bind:getLogHeight="getLogHeight"></NavLog>


  //父组件逻辑层进行获取
  getLogHeight:function(e){
    console.log(e.detail)
  }  
  

image.png

缓存

//设置缓存,传入数据
 wx.setStorageSync('facility', 2)
 
//获取缓存下的值
wx.getStorageSync('facility')

页面跳转传值

wx.navigateTo({
    url: 'xxx?data='+this.data.job,
 }) 

接收参数:

  onLoad(options) {
       console.log(options.cutState)
  }

保留小数点后两位数

这样的写法报错,是因为wxml中不能直接使用较高级的js语法。
{{(item[secondArguments]/item[thirdArguments]).toFixed(2)}}


image.png

解决方案:引入wxs模块实现

根据开发场景使用,这里就单独创建一个wxs,放入工具文件夹中。

image.png

wxs中写入方法

 function ftoFixed(num) {
    return num.toFixed(2);
 }
 module.exports.ftoFixed = ftoFixed;

wxml中使用wxs

//引入wxs
<wxs module="utilsWxs" src="../../utils/utils.wxs"></wxs>

<text>
   {{utilsWxs.ftoFixed(item[secondArguments]/item[thirdArguments])}} 
</text>

注:wxs模块中不能使用let,只能使用var

保留小数点稍微完善版:

  //保留小数点后两位
  function ftoFixedTwo(num) {
    var data=""
    //如果值为空使用-占位显示,提高界面友好度
    if(num == ""){
      data="-"
    }else{
      //不为空的情况下,
      var newNum=num.toString().split('.')
      //长度为1表示没有小数点,不进行处理,直接赋值
      if(newNum.length==1){
        data=newNum
      }else{
        //否则进行小数点处理
        data=Number(num).toFixed(2)
      }
    }
    return data
  }

image.png

千分符处理

  //千分符分割
  function thousandSeparator(num) {
    var num=num+''//转成字符串
    var intPart=''//存放整数
    var pointPart=""//存放小数点
    var data=''//返回最终数据
    //判断是否有小数点
    var point =num.indexOf('.')
    //-1没有小数点
    if(point===-1){
      //直接调用千分符方法,不进行处理
      data = thousandSeparatorReduce(num)
    }else{
       //千分符方法,对小数点前面数据进行处理
      intPart=thousandSeparatorReduce(num.slice(0,point))
     //获取数点
      pointPart=num.slice(point+1)
      //进行拼接
      data= intPart+'.'+pointPart
    }  
    return data
  }


  //千分符处理函数  
  function thousandSeparatorReduce(num){
   return  num.split('').reverse().reduce(function(prev,next,index){
      return ((index%3)?next:(next+','))+prev
   })
   
  }

image.png

视频播放video

 <video   id="myVideo" src="{{pathUrl}}" object-fit="contain" loop autoplay></video>

注:路径不能有中文。src="xxxxxx.com/xxx/大美女.mp4" 这个路径在模拟器中正常播放,但是真机调试时候视频是打不开,所以要确保后端给的的路径不能存在中文。

字符串显示成html

接收后端传入的数据,将字符串显示成html格式内容。

image.png

可是使用rich-text

  <rich-text nodes="{{htmlSnip}}"></rich-text>

使用链接:developers.weixin.qq.com/miniprogram… image.png 需要注意的是如果返回的数据是一个页面,rich-text就失效了。

image.png

解决办法:使用wxPars

先下载需要的文件,下载地址:gitcode.net/mirrors/ici…

只需要下载wxParse文件就行 image.png

image.png

将下载好的文件放入小程序中,放的位置看你心情。

在需要的功能模块下引入js文件。

image.png

js中进行数据绑定

/* 1.bindName绑定的数据名(必填)
* 2.type可以为html或者md(必填)
* 3.data为传入的具体数据(必填)
* 4.target为Page对象,一般为this(必填)
* 5.imagePadding为当图片自适应是左右的单一padding(默认为0,可选)
*/ 

WxParse.wxParse(bindName , type, data, target,imagePadding)
let that = this
wx.request({
  url: '',
  header: {
    'Content-Type': 'application/json',
  },
  success:res=>{
    let article=res.data.obj
   WxParse.wxParse('article', 'html', article, that,0);
  }
})

引入WxParse.css,可以在app.wxss引入,建议在需要模块的wxss样式文件中单独引用,不要全局使用,减少样式冲突。

image.png

在wxml文件中引入模板

image.png

使用模板,.nodes不要去掉。

image.png

如果head标签里有样式,这里会直接显示样式代码。

image.png

image.png

按照以往风格,简单粗暴的解决: 在wxss文本中加入下面代码

.card_service_ul > .WxEmojiView.wxParse-inline {
  display: none;
}
.wxParse-head{
  display: none;
} 

模拟器数据正常显示,真机测试获取不到数据

这个问题有可能是后端同学限制了接口访问IP,造成真机测试时接口调用失败。

使用md5加密

有些小程序有登录功能,通过账号密码进行登录,所以为了安全需要对密码进行加密处理发送给后端。

获取md5js源文件,源文件百度可以找到,因为审核不通过这里就不放了。

将md5源文件放入工具文件夹中

image.png

在登录模块的js文件中调用。

const md5 = require('../../utils/md5')
  

可以直接使用md5加密,也可以拼接之后再加密,这里看后端是怎么要求的。

后端会给一些字段,直接存入数组中

data: {
    //里面存放后端需要的字段
    mdValue: [x,x,x,x,x,x,x,x,x,x,x,x,x]
  },
  

进行拼接,将密码和数组中的字段拼接一起。注意这里的拼接方式后端规定,前端按照格式进行拼接即可。

 let userPwdStr = this.data.mdValue[4] + this.data.mdValue[5] + this.data.userPwd + this.data.mdValue[3] + this.data.mdValue[6]

最后使用md5加密

md5(userPwdStr)

base-64加密

js放入工具文件夹中,源文件百度可以找到,因为审核不通过这里就不放了。

image.png

引入js

const base64 = require('../../utils/base64')

直接使用

base64.base64_encode('xxxxx ')   

如果后端有加密要求根据后端的规则进行加密。

关于小程序图片大小问题

image.png

image.png

底部图标大小不要超过30kb,如果超过小程序就会报错,15kb其实差不多就可以了。

复用小程序时注意appid

当复用小程序整体代码,只是替换图片时,另起一个项目注意替换原来的appid。

将需要复用的项目导入,其实跟开始创建新的项目一样步骤,只不过目录结构里已经有内容了。 填入新客户的APPid即可创建。 image.png

进入项目发现上传不能点击,无法上传。还要写着测试号,但是appid是正确的,这就需要改一个地方就行。 image.png

找的project.config.json image.png

修改下原来的APPid,解决问题 image.png

小程序自定义导航栏

在需要的页面中的json文件中简单配置下即可,app.json设置无效。

{ 
    "usingComponents": {}, 
    "navigationStyle":"custom" 
 }
 

image.png

分享时带有参数

业务场景:A销售员通过分享小程序给客户,客户填写信息之后,此客户就属于A销售员。

简单的实现逻辑就是A销售员登录小程序,分享出去时带有他的手机号信息。 客户打开分享的小程序带有A销售员的手机号信息,获取到并传给后台进行比对判断。

从缓存中获取到登录时存放的手机号,在分享是带着参数就行。

sharePhone字段自己定义就行。

   onShareAppMessage:function(res){
      return { 
          title: '分享XXXX', path: 'XXXXX?sharePhone='+wx.getStorageSync('phoneNumber'), 
      } 
    }

在首页中获取分享时传过来的参数。

    onLoad(e) { 
        //获取分享的参数,将参数存入缓存中 
        wx.setStorageSync('sharePhone',e.sharePhone) 
     }
     

使用腾讯官方的视频播放插件

小程序设置里 —— 第三方设置 —— 插件管理 —— 添加插件 —— 搜索腾讯视频添加即可

image.png

进行添加 image.png

代码中也需要进行配置:

在需要播放的页面中找到json文件,配置下视频插件。

"usingComponents": {
    "txv-video": "plugin://tencentVideo/video"
  }
  

在wxml文件中加入代码:

 <view class="content-video">
      <txv-video vid="{{videoUrl}}" playerid="txv1" objectFit="fill"></txv-video>
 </view>

vid是用了获取视频的,playerid确保唯一即可。

关于视频需要申请一个企业账号,进行主体认证等操作。然后上传视频到腾讯视频,审核通过就行。

获取视频链接,右键视频点击视频信息

image.png

找到视频ID,斜杠前面的一串数字就是ID image.png

或者通过分享找到代码查看,点击嵌入代码

image.png

嵌入代码打开里面的vid就是o33401kc9b1跟上面的一样。

<iframe frameborder="0" src="https://v.qq.com/txp/iframe/player.html?vid=o33401kc9b1" allowFullScreen="true"></iframe>

细心一点会发现链接:v.qq.com/x/page/o334… 也有视频ID

加入腾讯视频插件,视频播放前会有广告,这里就需要付费去除广告,另外小程序包的大小也会变大。

在线客服

小程序有自带的人工客服,组件button加上open-type=“contact”属性,客服人员在小程序后台添加就行。

<button open-type="contact">咨询</button>

如果想使用第三方在线,直接找第三方在线让他们关联下小程序就行,关联上后台会显出结果。 image.png

for循环修改别名

wx:for="{{book}}" 默认是item

进行修改方法: wx:for-item="dataLiet" 就可以使用dataLiet。

下标index 也是wx:for自带的,可以进行修改 wx:for-index="idx" 就可使用idx

注意使用wx:for记得加上wx:key="index" 可以换成后端传入的id。

rpx 和 px 简单转换

基于iPhone 6/7/8 等标准机型上,1rpx = 0.5px。因此,设计图是基于 iPhone 6 尺寸比例(通常是 375px 或 750rpx),可以直接进行简单的换直接算乘以2

375px 乘以 2 等于 750rpx

小程序特殊字体引用

1.使用外部链接进行引用(动态加载网络字体)

代码放在app.js中或者需要使用到的模块js中

  wx.loadFontFace({
    global:true, // 版本 2.10.0 后 全局app.js 使用
    family: 'PingFang',
    source: 'url("https://www.xxxxxx.com/PingFangRegular.ttf")',//字体资源的地址。建议格式为 TTF 和 WOFF,WOFF2 在低版本的iOS上会不兼容。
    success: (res) => {
      //成功返回结果
      console.log(res)
  
    },
    fail: function (res) {
     //失败返回结果
      console.log(res)
    },
    complete: function (res) {
      console.log(res)
    }
  });

在wxss文件中进行使用。

 font-family: "PingFang"!important;
 

需要注意一点就是ios系统可以正常获取到字体,但是在安卓手机中会失败。这就需要进行配置,进入服务器找nginx 配置,站点配置文件加入以下代码,开启cros支持,然后重启下nginx。

	location ~ \.(eot|otf|ttf|woff|woff2|svg)$ {
   add_header  Access-Control-Allow-Origin *;
   add_header Content-Type font/ttf|font/woff|font/woff2;
}

image.png

这里造成安卓手机失败的原因是字体链接访问需满足浏览器同源策略,字体文件资源设置CORS的Access-Control-Allow-Origin为小程序域名:servicewechat.com或者*

该行代码的含义为在HTTP响应中添加一个名为"Access-Control-Allow-Origin"的头部字段,这个头部字段的作用是指定允许访问资源的源,即哪些域名可以与服务器进行跨域请求;

如果是使用的宝塔的配置如下

<FilesMatch "\.(ttf|otf|eot|woff|woff2)$">

      <IfModule mod_headers.c>

      Header set Access-Control-Allow-Origin "*"

      </IfModule>

</FilesMatch>

   location ~ .(eot|otf|ttf|woff|woff2|svg)$ {
   add_header Access-Control-Allow-Origin *;
   add_header Content-Type font/ttf|font/woff|font/woff2;
   }

根据配置文件来设置。

解决安卓特殊字体失败问题还有一种方法就是字体文件转base64。

字体文件转换网站:transfonter.org/

1.点击按钮Add fonts(添加字体)

2.将Base64 encode按钮打开,下面的Formats按钮按需要选择。

3.转换好后点击Download下载

image.png

下载成功之后的压缩包。

image.png

解压后:

image.png

把stylesheet.css文件里的内容整个复制到微信小程序的wxss页面中。

image.png

我大概看了一下大小比原来字体的还要大一些,所以个人觉得没必要安卓和IOS两套写法,直接在服务器配置文件就好了。

服务类目

服务类目可以有多个,具体还是需要跟小程序功能业务来添加的,审核时小程序也会提醒你加入对应的服务类目。 image.png

比如工具服务类目就是,获取地理位置权限。 image.png

wx.getLocation获取位置

本地开发wx.getLocation不会正常使用,如果没有开通权限,审核时会被拒绝。 记得开通下,避免上线时出现问题。 image.png

//获取坐标信息
      wx.getLocation({
        success:(res)=>{
            //成功获取之后
            wx.request({
              //传入经纬度参数
              url:"xxxx?longitudeLatitude="+res.latitude+','+res.longitude,     
              success:(res)=>{

              }   
            })
        }
        
        

登录操作及获取手机号

在button组件中设置open-type="getPhoneNumber"

<button  open-type="getPhoneNumber" bindgetphonenumber="getPhoneNumber"></button>

点击按钮时触发方法

    getPhoneNumber(e){

    //结构赋值 手机号解密 这是时小程序传入的值,直接用
    let {encryptedData,iv} = e.detail

       //登录获取code
        wx.login({
            success:(res)=>{
                //获取code 并将code传给后端,用来获取session_ke
                let code=res.code
                wx.request({
                    url:api.useCode+code,
                    success:(res)=>{

                        //手机号解码
                        wx.request({
                            url:api.phoneDecode,
                            method: "post",
                            header: { 'Content-Type': 'application/x-www-form-urlencoded'},
                            data:{
                              'encryptedData':encryptedData,
                              'sessionKey':res.data.data.session_key,
                              'iv':iv
                            },
                            success:(res)=>{
                                if(res.data.code==200){
                                  //改变登录状态
                                  wx.setStorageSync('loggingStatus', true)
                                  //获取解码成功后的手机号
                                  let phoneNumber=res.data.data.purePhoneNumber
                              }
                            }
                          }
                        )
                    }
                })
            }
        })

  },

简易的双向绑定

 <input model:value="{{value}}"/>
 <view>{{value}}</view>
 

错误集

一.首次编译大概率出现invoke loadComponents fail错误

[渲染层错误] [jsbridge] invoke remoteDebugInfo fail: too eayly.

image.png

解决方法:删除掉app.json里面的

"lazyCodeLoading": "requiredComponents",

或者降低基础库的版本。

二.手机号获取不到,失败状态。

代码层级没有问题,却无法获取到手机信息

e.detail 里提示失败信息,请查看下小程序是否认证。 image.png

如果小程序后台微信认证是未认证,那么是无法成功获取手机号相关信息的。需要完成微信认证才行。 image.png

三.ERR_SSL_PROTOCOL_ERROR,配置合法域名不生效。

合法已经域名配置了,但小程序报错ERR_SSL_PROTOCOL_ERROR,直接找后端解决,代理啥的配置绝对有问题。

小细节

bindinput获取值为[object promise]

出现这个问题的原因就是,定义的方法使用了async。

bindInputVal(e) 正常获取数据

bindInputVal:async function(e) 获取的是[object promise]

自定义内容,结构解析方便提取

<view data-usrName="张嘎嘎" data-usrAge="23" bindtap="onClickName">你的名字</view>

onClickName(event){
    //对象中有自定义data-usrName内容,通过currentTarget中的dataset找的usrname
    console.log(event)
    console.log(event.currentTarget.dataset.usrname)
    
    //event.currentTarget.dataset是个对象,如果自定义有多个可以通过结构解析,方便提取值
    let {name,age} = event.currentTarget.dataset
    console.log(name) //张嘎嘎
    
    
}

小程序管理修改

面对管理员离职,没有交接且离职后无法联系此人可以通过下面方式进行修改管理员。

一般都习惯使用二维码方式进行登录,所以会忘了还有账号登录,所以通过账号登录可以找回账号和密码。

image.png

image.png

image.png

方法二: 打开链接:mp.weixin.qq.com/acct/findac…

image.png

本文用于学习记录,如有错误地方请多指正,谢谢。