最近使用钉钉开发者工具开发小程序,遇到了一些问题,在此汇总方便日后查看。
最近发现上面蓝色的开发工具是旧版,有问题,换了新版本的工具,使用起来差不多,甚至功能更全更好用,如下图
钉钉小程序data赋值取值的问题
Page({
// 数据对象
data: {
activeTab: '',
clickedObj: {}
},
// 自定义的方法
setDataFunction() {
// 对data对象的字段直接赋值
this.setData({
activeTab: 'a'
});
// 对data对象字段的一部分赋值
this.setData({
'clickedObj.key1': 'b'
})
// 获取data对象的字段
console.log(this.data.activeTab) // 结果:'a'
console.log(this.data.clickedObj) // 结果:{key1: 'b'}
}
})
钉钉小程序路由跳转及携带参数的问题
首先要在app.json里注册页面
再通过点击等方法,通过dd.navigateTo跳转
// 需要跳转的页面
Page({
// 数据对象
data: {
},
// 跳转方法的方法
jumpToNewPageFunction() {
dd.navigateTo({
url: `pages/record-book-pages/recording-books/recording-books?bookCode=${'1234'}`,
success: () => {},
fail: () => {},
complete: () => {},
})
},
}
})
在目标页面通过onLoad接收参数
// 目标跳转页面
Page({
// 数据对象
data: {
bookCode: ''
},
// 页面加载的钩子函数
onLoad(query) {
console.log('图书编号:', query) // 结果:图书编号:1234
this.setData({
bookCode: query.bookCode,
});
},
})
钉钉小程序调用接口报错的问题
报错:{“code“:“ERR_UNESCAPED_CHARACTERS“}
遇到这个问题是因为传参传入了中文,请求格式出现问题
解决方法为,将URL用encodeURI()包裹起来
钉钉小程序路由跳转路径正确却报错的问题
可能是路径前面没加斜杠 /
钉钉小程序设置页面标题
Page({
// 数据对象
data :{},
// 页面显示的钩子函数
onShow() {
// 页面显示
dd.setNavigationBar({
title : '页面标题',// 控制标题文本,空字符串表示显示默认文本
});
},
})
钉钉小程序使用dd基础Api报错的问题
告诉你不是一个函数,可以检查下最上方是否有引入钉钉的jsapi,jsapi和基础使用的dd二者不是一个东西,把jsapi注释掉,就不会报上方的错误了
钉钉小程序循环列表渲染a:for
想做一个列表,列表的每一项都是左边为图书封面,右边为作者、ISBN、分类、数量的信息,每项如下图
<!-- axml文件 -->
<view a:for="{{bookList}}" class="book-list-item" data-item="{{item}}">
<view class="book-item-picture"></view>
<view class="book-item-infos">
<view class="book-title">{{item.bookName}}</view>
<view class="book-author gray-text">作者:{{item.bookAuthor}}</view>
<view class="book-isbn gray-text">ISBN:{{item.isbn}}</view>
<view class="book-type gray-text">分类:{{item.bookTypeName}}</view>
<view class="book-nume gray-text">数量:{{item.bookNum}}本({{item.borrowCount}}本在馆)</view>
<view class="borrow-times">被借<view class="red-text">{{item.borrowCountSum}}</view>次</view>
</view>
</view>
// js文件
Page({
data: {
bookList: []
},
})
通过a:for循环列表,下方直接取用item取数据
钉钉小程序循环列表点击事件,获取点击项
<!-- axml文件 -->
<view a:for="{{bookList}}" class="book-list-item" data-item="{{item}}" onTap="clickBookListItem">
<view class="book-item-picture"></view>
<view class="book-item-infos">
<view class="book-title">{{item.bookName}}</view>
<view class="book-author gray-text">作者:{{item.bookAuthor}}</view>
<view class="book-isbn gray-text">ISBN:{{item.isbn}}</view>
<view class="book-type gray-text">分类:{{item.bookTypeName}}</view>
<view class="book-nume gray-text">数量:{{item.bookNum}}本({{item.borrowCount}}本在馆)</view>
<view class="borrow-times">被借<view class="red-text">{{item.borrowCountSum}}</view>次</view>
</view>
</view>
在循环容器上添加点击方法: onTap=“clickBookListItem”,注意不能在调用方法里加(item)参数。
注意,不能漏掉 data-item=“{{item}}”
// js文件
Page({
data: {
bookList: []
},
// 点击图书列表项,获取点击项,并做后续操作
clickBookListItem(event) {
const clickItem = event.target.dataset.item
console.log('bookItem', event, clickItem)
},
})
在方法里添加参数event,通过event.target.dataset.item获取点击项
钉钉小程序循环列表点击事件,获取点击项失败
上面的方法可以看出,点击事件是在整个循环项的整体发生,但我在开发新功能的时候,发现如果我点击循环项的一部分,比如每项都有个“编辑”按钮,我想点击这编辑按钮,打开专属编辑页面,但数据获取失败了,我是这样写的(如下)
<view a:for="{{bookDetailsList}}" class="collect-book-list-item" data-item="{{item}}">
<view class="book-author gray-text">编号:{{item.bookBarcode}}</view>
<view class="book-isbn gray-text">位置:{{item.location}}</view>
<view class="book-type gray-text">状态:{{item.isBorrow}}</view>
<view class="book-nume gray-text">备注:{{item.remark}}</view>
<view class="pre-borrow">预借</view>
<view class="operation-wrapper">
<view class="opr-btn">删除</view>
<view class="opr-btn" onTap="clickEditBtn">编辑</view>
<view class="opr-btn">下架</view>
</view>
</view>
// 点击编辑按钮,跳转至编辑页面,编辑信息
clickEditBtn(event) {
const clickItem = event.target.dataset.item
console.log(clickItem) // 结果:undefined
},
经过思考我发现,只需要在按钮所在的标签,添加data-item="{{item}}"
属性即可,没想到还能这么用
<view a:for="{{bookDetailList}}" data-item="{{item}}">
<view class="book-author gray-text">编号:{{item.bookBarcode}}</view>
<view class="book-isbn gray-text">位置:{{item.location}}</view>
<view class="book-type gray-text">状态:{{item.isBorrow}}</view>
<view class="book-nume gray-text">备注:{{item.remark}}</view>
<view class="pre-borrow">预借</view>
<view class="operation-wrapper">
<view class="opr-btn">删除</view>
<view class="opr-btn" data-item="{{item}}" onTap="clickEditB">编辑</view>
<view class="opr-btn">下架</view>
</view>
</view>
钉钉小程序请求后端接口dd.httpRequest的GET方法
dd.httpRequest({
url: url+'?key1=a&key2=b',
success: (res) => {
const { data, status, headers } = res;
},
fail: () => {},
complete: () => {},
});
上方是GET最简单的请求的请求方式,其中有些参数有默认值(如下表),不需要改动的情况下可以不用填
GET请求传参只需在url后方添加key-value值即可(如上方代码)
钉钉小程序请求后端接口dd.httpRequest的POST方法,及遇到的一些问题
1. dd.httpRequest的POST请求格式问题
POST请求我本来是这样写的(下方的代码),但是报错了
Page({
// 请求方法
requestAPI() {
const params = {
'key1': 'a',
'key2': 'b
}
dd.httpRequest({
url: url,
data: params,
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
timeout: 30000,
dataType: 'json',
success: (res) => {
const { data, status, headers } = res;
},
fail: () => {},
complete: () => {},
});
},
})
原因:请求头格式不对,改成 headers: { 'Content-Type': 'application/json; charset=utf-8' }
即可调通
2. dd.httpRequest的POST请求参数问题
解决了Content-Type的报错问题,点击提交结果,又报了个新错误:JSON parse error: Unrecognized token 'key1': was expecting (JSON String, Number, Array, Object or token 'null', 'true' or 'false'); nested exception is com.fasterxml.jackson.core.JsonParseException: Unrecognized token 'key1': was expecting (JSON String, Number, Array, Object or token 'null', 'true' or 'false')↵ at [Source: (org.springframework.util.StreamUtils$NonClosingInputStream); line: 1, column: 6]
(如下图),说类型不对,检查了字段类型、字段名称也没看出哪里有问题,后端的入参字段也没问题,最后发现被官方文档的data类型唬住了
只需要一个小改动就能成功,将入参的json格式转换成字符串类型即可:data: params
替换为data: JSON.stringify(params)
Page({
// 请求方法
requestAPI() {
const params ={
'key1': 'a',
'key2': 'b
}
dd.httpRequest({
url: url,
data: JSON.stringify(params),
method: 'POST',
headers: { 'Content-Type': 'Content-Type': 'application/json; charset=utf-8' },
success: (res) => {
const { data, status, headers } = res;
},
fail: () => {},
complete: () => {},
});
},
})
钉钉小程序的“全局变量”
在app.js文件中定义变量,如图bookStoreApi,就可以在任何组件的js文件里使用了,通过getApp()获取全局变量,如下方代码
// 某组件的js文件
Page({
// 获取全局变量
getGolalData() {
const global = getApp()
console.log('bookStoreApi:', global.bookStoreApi) // 结果:bookStoreApi:http://....
},
})
钉钉小程序请求后端接口的一些小tip
开发vue框架时,调用后端接口通常通过代理/api
转发,来简化调用地址的编写
// vue.config.js
/api': {
target: process.env.VUE_APP_BASE_API,
changeOrigin: true,
pathRewrite: { '^/api': 'http://192.168.123.123:8888' }
},
// vue调用接口处
return Service({
url: '/api/getBookInfo',
method: 'get',
params
})
在钉钉开发平台里,好像没有代理怎么办呢,那就用到全局变量啦
// app.js
App({
bookStoreApi: 'http://123.123.123.123.90'
});
// 组件的js文件
Page({
// 请求方法
requestAPI() {
const global = getApp() // 取到全局变量
dd.httpRequest({
url: `${global.bookStoreApi}/getBookList`, // 使用全局变量的bookStoreApi字段,拼接到url里
data: {}, // 多个服务就定义多个api的字段,按需使用
success: (res) => {},
fail: () => {},
complete: () => {},
});
},
})