微信小程序技术总结
小程序单向数据流
单向数据流就是从逻辑层到视图层,vue也是单向数据流Model - view,但是实现了双向数据绑定。而小程序没有做劫持代理,所以不能进行双向数据绑定。但现在小程序是有双向数据绑定这个概念的,叫简易的双向数据绑定。
胶囊按钮
需求:logo需要同右边的胶囊按钮顶部对齐。
解决方法:使用 wx.getMenuButtonBoundingClientRect()
输出下 wx.getMenuButtonBoundingClientRect(),可以看见胶囊按钮的信息,需要注意的是单位为px。
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。
小程序eCharts使用
第一步:进入eCharts官网点击下载选择下载,进入在线制定。按需要下载,减少体积
第二步:点击在线制定
第三步:选择需要的图形
第四步:下载
第五步:选择文档下的应用篇,选择跨平台方案,选择微信小程序
第六步:下载echarts-for-weixinecharts-for-weixin
用ec-canvas文件就行
第七步:将ec-canvas文件放入项目中
我这里是在组件中创建了echarts文件夹,就把ec-canvas文件中的文件全部放进去。注意如果是按需制定的echarts,将echarts.js替换成在线制定生成的echarts.min.js。
同时修改ec-canvas.js 中的 import * as echarts from './echarts'的引用文件。
第八步使用
配置组件使用
"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;
},
大致效果:
navigateTo超出10个页面,粗糙解决办法
wx.navigateTo打开页面最多只能打开10个,超过10个之后就没反应。
// 导航列表跳转对应页面
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,十次之后才会闪动一次。
自定义tabBar
第一步:开启tabBar自定义
在app.json中找的tabBar加入custom:true
同时官方文档建议还是将list内容写上,用来兼容低版本。
第二步:创建目录
创建custom-tab-bar与pages同级。
第三步: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);
},
})
获取机型
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)
}
缓存
//设置缓存,传入数据
wx.setStorageSync('facility', 2)
//获取缓存下的值
wx.getStorageSync('facility')
页面跳转传值
wx.navigateTo({
url: 'xxx?data='+this.data.job,
})
保留小数点后两位数
这样的写法报错,是因为wxml中不能直接使用较高级的js语法。
{{(item[secondArguments]/item[thirdArguments]).toFixed(2)}}
解决方案:引入wxs模块实现
根据开发场景使用,这里就单独创建一个wxs,放入工具文件夹中。
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>
本文用于学习记录,如有错误地方请多指正,谢谢。