十三、sentry监听小程序的报错信息(需后端搭建服务)
参考资料地址 https://lvan-zhang.blog.youkuaiyun.com/article/details/113448674
1、先安装sdk $ yarn add sentry-miniapp
//下面的代码放在Taro项目的app.js文件里
import * as Sentry from 'sentry-miniapp'
const version = Taro.getAccountInfoSync().miniProgram.version || 'alpha'
// 初始化 Sentry
Sentry.init({
dsn: '后端配置的dsn',
release: version
})
//用于传额外的信息,可以是当前用户姓名,id,手机号等信息,字段都是自定义的,随便写
Sentry.setUser({
id: userInfo.userId,
name: userInfo.name,
phone: userInfo.phone
})
十二、最近使用了taro-hooks开发项目,也换了UI框架,个人感觉还不错,使用上跟antd差不多,部分组件稍微有点区别
组件地址 https://antmjs.github.io/vantui/#/dialog
1、比如第十一条表单卡顿问题,form组件基本上解决了卡顿问题(只适合一个页面单个表单,并且提交的内容不是太多的情况)。
十一、表单卡顿问题
1、多层嵌套,触发原生组件渲染,不再是state更新组件的value值;(层级太深,不太好操作数据)
2、表单的卡顿主要的视觉效果是input的输入卡顿,其他的比如radio,select除了渲染值可能慢了点,其他的都不明显;
我主要讲解input的优化,解决卡顿问题。将input封装成一个组件,代码如下:
input组件
import React, { Component } from 'react'
import {Input} from "@tarojs/components";
class InputBox extends Component{
state={
value:this.props.value
}
shouldComponentUpdate(nextProps, nextState, nextContext) {
//这个是触发input使用原生渲染的关键,必须添加,内容不需要添加任何东西
}
render() {
let {name,placeholder,onValueChange} = this.props
return <Input
name={name}
placeholder={placeholder}
value={this.state.value}
className='form_item'
这个方法是父级传来的方法,用来存储input输入的值,表单提交的时候使用
onInput={(e)=>onValueChange(e.target.value,name)}
/>
}
}
export {InputBox}
///父级页面
//引用input组件
import {InputBox} from "./components/Inputbox";
onValueChange (value,name) {
let inputValueArr = {...this.state.inputValueArr};///浅拷贝数据,存储表单要提交的数据
inputValueArr[name]=value;
this.setState({
inputValueArr
})
}
//表单内使用方式
<Form>
<InputBox
name='nickname'
placeholder={'请输入姓名'}
value={this.state.inputValueArr.nickname}
onValueChange={this.onValueChange.bind(this)}
/>
</Form>
以上代码在使用原生组件的情况下解决表单卡顿问题,其他的组件应该是同样的封装组件,然后父级引用使用(ps:理论上其他的比如说radio,select等,根据上面的代码修改下应该是不卡的,我只使用过input,哈哈,有问题可以私信我)
十、小程序下拉刷新功能
在需要分享的页面对应的config.js里添加 enablePullDownRefresh:true
onPullDownRefresh ()方法和componentDidMount()同级;
onPullDownRefresh = () => {//添加监听下拉事件,刷新页面
//这里调用方法获取最新数据
};
九、分享小程序功能
onShareAppMessage() 方法和componentDidMount()同级;
onShareAppMessage() {分享功能
return {
title: "分享的标题",
path: 'pages/index/index?id=' + id, // 自定义的分享路径,点击分享的卡 片之后会跳转这里定义的路由
imageUrl: '' // 图片路径,如果没有,那么展示的就是分享页面的预览图
};
}
八、echarts图表层级太高问题

在微信开放文档里已经描述了,view已经可以代替cover-view,不被echarts遮住了。但是我们在开发的过程中发现,开发工具中依然是echarts遮住其他组件的状态。<font color=#f73131>**这个其实是微信开发工具的显示bug**</font>,代码在实机上跑,会神奇的发现,echarts图表并没有遮住其他的组件。
一、图片上传
点击上传按钮时
Taro.uploadFile({
url: 'http://xxx/api/common_file/', //仅为示例,非真实的接口地址
filePath: files[0].file.path,//Taro组件返回的图片信息
header: {
'Authorization':'JWT '+ token
},
name: 'file',//修改上传文件的名称
formData: {
'name': 'test'//上传文件的名称
},
success (res){
console.log(result);
},
fail(){
Taro.showToast({
title: '上传失败,请联系管理员',
icon:'none',
duration: 2000
})
}
})
/*组件onchange事件调用*/
onChange (files,operationType,index) {图片上传
let that=this;
console.log(files);
if(operationType==="remove"){///清除图片
//移除事件后需操作的写在这边
}else {//图片上传
UploadFile(files,index,that)
}
}
二、多个input渲染后,修改其中一个,其他的也会跟着变化
input里的name名不能重复,Taro是根据name名修改对象input值的,所以将name名变不同了,相互之间就没有影响了
三、经常有同学想用微信的一些功能,但不知道在Taro中怎么调用。其实Taro都封装过了,参考地址如下,里面有常用的和不常用的功能
用的到的本地存储方法
//使用方法跟h5一样
//存储方法
Taro.setStorageSync({"key","value"})//
//读取方法
Taro.getStorageSync("key") //值为value
经常用的到的跳转方法
//跳转到 tabBar 页面,并关闭其他所有非 tabBar 页面
Taro.switchTab({
url: '/index'
})
//关闭所有页面,打开到应用内的某个页面
Taro.reLaunch({
url: 'test?id=1'
})
//关闭当前页面,跳转到应用内的某个页面。但是不允许跳转到 tabbar 页面。
Taro.redirectTo({
url: 'test?id=1'
})
//保留当前页面,跳转到应用内的某个页面。但是不能跳到 tabbar 页面。使用 Taro.navigateBack 可以返回到原页面。小程序中页面栈最多十层。
Taro.navigateTo({
url: 'test?id=1',
events: {
// 为指定事件添加一个监听器,获取被打开页面传送到当前页面的数据
acceptDataFromOpenedPage: function(data) {
console.log(data)
},
someEvent: function(data) {
console.log(data)
}
...
},
success: function (res) {
// 通过eventChannel向被打开页面传送数据
res.eventChannel.emit('acceptDataFromOpenerPage', { data: 'test' })
}
})
//关闭当前页面,返回上一页面或多级页面。可通过 getCurrentPages 获取当前的页面栈,决定需要返回几层。
//如果跳转层级超出了应有的层级会报错的
// 注意:调用 navigateTo 跳转时,调用该方法的页面会被加入堆栈,而 redirectTo 方法则不会。见下方示例代码
// 此处是A页面
Taro.navigateTo({
url: 'B?id=1'
})
// 此处是B页面
Taro.navigateTo({
url: 'C?id=1'
})
// 在C页面内 navigateBack,将返回A页面
Taro.navigateBack({
delta: 2
})
更多功能查看官网地址示例
https://taro-docs.jd.com/taro/docs/apis/about/desc
四、接口请求全局添加拦截器
import Taro from "@tarojs/taro";
//配置的常量文件
import {BASE_URL} from '../lib/constant';
/**
* http request 拦截器
*/
const interceptor = function (chain) {
const requestParams = chain.requestParams;
let { url } = requestParams;
//console.log(requestParams)
//完整的请求地址
//console.log(requestParams);
将请求地址修改为完整的请求地址
requestParams.url=BASE_URL+url;
//接口添加Authorization
let gToken=Taro.getStorageSync('token');///获取本地存储的token
//添加用户身份验证信息,Authorization
requestParams.header={
'Content-Type':"application/json"
'Authorization':gToken?('JWT '+ gToken.split("&&")[0]):''
};
//小程序不支持patch接口,所以在接口里添加一个'patch/'标记为patch的接口
if(url.match('patch')){
requestParams.url=BASE_URL+url.replace('patch/','');//将接口里标记为patch方法的字符串去掉
requestParams.header={
'Content-Type':"application/json",
'Authorization':gToken?('JWT '+ gToken.split("&&")[0]):'',
//添加请求头,中间件将post方法设置为patch方法,解决小程序不支持patch方法的问题,需与后台商议, 让他做下处理
'X-HTTP-Method-Override':'PATCH'
};
}
return chain.proceed(requestParams)
.then(res => {
return res
}).catch((error) => {
return error
});
};
Taro.addInterceptor(interceptor);///为请求添加拦截器
let Axios={//为了从pc端copy方便,封装成了同样的对象,哈哈
/**
* 封装get方法
* @param url 请求url
* @param params 请求参数
* @returns {Promise}
*/
get(url, params = {}) {
return new Promise((resolve, reject) => {
Taro.request({url,
data: params,
method:'GET'
}).then((response) => {
//console.log(response);
if(response.statusCode < 300){//请求成功
//接口返回的信息
resolve(response.data);
}else
//错误信息未返回,如果有需要返回,可以添加,用于特殊处理
//resolve(response);
msag(response)
}
}).catch((error) => {
reject(error);
});
});
},
/**
* 封装post方法
* @param url 请求url
* @param data 请求参数
* @returns {Promise}
*/
post(url, data) {
return new Promise((resolve, reject) => {
Taro.request({url,
data: data,
method:'POST'
}).then((response) => {
if(response.statusCode < 300){//请求成功
resolve(response.data);
}else {
//错误信息未返回,如果有需要返回,可以添加,用于特殊处理
//resolve(response);
msag(response)
}
}).catch((error) => {
console.log(error);
msag(error);
reject(error);
});
});
},
};
export default Axios
//失败提示
function msag(err) {
// hideLoading ()
if (err ) {
switch (err.statusCode) {
///根据实际情况自己处理接口错误信息提示
case 400:
break;
case 401:
break;
case 403:
break;
case 404:
break;
case 408:
break;
case 500:
break;
case 501:
break;
case 502:
break;
case 503:
break;
case 504:
break;
case 505:
break;
default:
}
}
}
五、echarts图表
先安装插件
$ yarn add echarts-taro3-react
安装完成后,我们开始封装一些基础的图表
创建bar.jsx文件
import React, { Component } from 'react'
import { View } from '@tarojs/components'
import { EChart } from 'echarts-taro3-react'
class Bar extends Component {
componentDidMount() {
if(this.props.data.x.length>0){
this.refresh(this.props.data)
}
}
refresh(data) {
let x=data.x;
let y=data.y;
const option = {
color:'#1e91ff',
xAxis: {
type: "value",
},
grid:{
left:'2%',
right:'6%',
bottom:'4%',
top:'15%',
containLabel:true
},
tooltip: {
trigger: 'item',
formatter: '{b} : {c} ' + '人',
confine:true ///解决tooltip被遮挡问题
},
yAxis: {
type: "category",
data: y,
},
series: [
{
data: x,
type: "bar",
showBackground: true,
// 实现数字展示在柱状图
label: {
show: true,
position: 'inside',
color:'white'
},
itemStyle: {
//这里是重点
color: function(params) {
//注意,如果颜色太少的话,后面颜色不会自动循环,最好多定义几个颜色
var colorList = ['#5470C6','#91CB74', '#FAC858', '#EE6666', '#73C0DE','#3CA272', '#FC8452','#9A60B4'];
return colorList[params.dataIndex%7]
}
}
},
],
};
this.pieChart.refresh(option);
}
refPieChart = (node) => (this.pieChart = node);
render() {
return (
<View className='chart pie-chart'>
{this.props.data.x.length===0?
<View className='noDate'>暂无统计数据</View>: <EChart ref={this.refPieChart} canvasId={this.props.id} />
}
</View>
)
}
}
export default Bar
接下来使用刚封装好的组件
import React, { Component } from 'react'
import { View} from '@tarojs/components'
import './center_echarts.less'
import '../main.less'
import Bar from '../../components/echarts/bar/bar'
import Pie from '../../components/echarts/pie/pie'
import Axios from '../../api/request'
import Taro from "@tarojs/taro";
export default class Center_echarts extends Component {
state={
area:{
x:[],
y:[]
},
areaKey:0,
};
componentWillMount () { }
componentDidMount () {
let _this=this;
Axios.get('/api/v1/report/?type=area').then((res)=>{//柱状图
if(res){
if(res.data){
let result=res.data;
let x=[];
let y=[];
result.map((item)=>{
y.push(item.province__name?item.province__name:'未知');
x.push(item.count);
return item
});
let area={
x,y
};
_this.setState({
area:area,
areaKey:area.x.length
})
}
}
});
}
componentWillUnmount () { }
componentDidShow () { }
componentDidHide () { }
render () {
return (
<View className='center_echarts'>
<View className='echarts_box'>
<View className='title'>各省份人数</View>
//key的作用是用来重新加载组件的,area数据变化后,图表并不会自动刷新
<Bar id='bar' data={this.state.area} key={this.state.areaKey} />
</View>
</View>
)
}
}
更多echarts组件参考Taro物料市场 echarts-taro3-react
提示:自定义echart.js,自行前往echart官网(注意:版本需要选择4.9.0,不要勾选压缩,可下载下来后自行压缩) 按需构建echart.js,然后替换掉echarts-taro3-react/lib/ec-canvas/echart.js,压缩下来大概在600kb左右,比原来体积小了一大半。
六、小程序分享功能
componentDidMount () {}
//位置与componentDidMount同一级 ,添加后右上角可以点击分享了
onShareAppMessage() {分享功能 ,不能改为箭头函数,会失效的,啥?我为啥会知道?
return {
title: "分享小程序",
path: 'pages/index/index', // 自定义的分享路径,点击分享的卡片之后会跳转这里定义的路由
imageUrl: '' // 图片路径
};
}
页面里点击实现分享功能,能够触发分享功能
<Button openType='share'>分享小程序</Button>
七、小程序登录授权手机号
//进入首页时,先调用wx.login方法获取code
Taro.login({
success:function(res){
let code=res.code;
//这边后台根据code去查询用户是否已经登录过, xxx是后台的接口
Axios.post('/api/v1/xxx/', {code:res.code,type:small_progress_type}).then((res)=>{//接口获取openid
if(res){
//这边根据后台返回的数据做些判断,本地存储下用户是否已经授权注册过
}
});
}
})
getPhoneNumber=(e)=>{///获取用户手机号
console.log('获取手机号');
if(e){///授权登录
let iv=e.detail.iv;
let encryptedData=e.detail.encryptedData;
console.log(e);
if(iv&&encryptedData){
Taro.showLoading({
title: '授权中...',
});
//后台根据iv&&encryptedData解密出手机号
toGetPhoneNum(iv,encryptedData);
}else {
///用户拒绝授权
console.log('用户拒绝授权');
callback();
}
}
};
//用户未授权注册过,引导用户点击授权登录按钮,微信已经不让自动弹出获取手机号的界面了,只能用户点击了才能出现,嗯嗯,干的漂亮。
<Button type='primary' openType ="getPhoneNumber" onGetPhoneNumber ={(e)=>getPhoneNumber(e,'',id,name)}>授权登录</Button>