在小程序中使用base64展示图片
背景
- 项目使用
taro
进行开发 - 需求是通过
api
请求, 获取图片的base64
字符串, 并且将图片展示出来 - 小程序中单次调用
setData
数据不能超过1024kb
分析
根据setData
的限制, 图片的大小不能超过1024kb
, 否则setData
的时候会超过限制而报错。
因此, 可以考虑使用数组来存储数据, 并且将数据分批写入。
const arr = []
const baseStr = '....' // > 1024kb
const step = 1024 * 1024
for (let i = 0, j = 0; i < baseStr.length; i = i + step, j++) {
arr[j] = baseStr.subStr(i, step)
}
然而, 对于taro
而言, 数据的修改通过this.setState
来完成, 不能像原生小程序那样只修改部分数据。 比如:
// taro
this.setState({
a: {
...this.state.a,
b: 1
},
c: [{ b: 1 }, ...this.state.c.slice(1)]
})
// 小程序
this.setData({
'a.b': 1,
'c[0].b': 1
})
因此, taro
每次的setState
都会把整个数据带上. 不符合setData
限制。
倘若taro
能像setData
一样可以支持单独修改某一部分数据, 是否可以?
答案也是否定的
在taro
中, 在render
方法用到的数据, 最终都会被挂在this.__state
上, 而this.__state
最终也会反应到data
上, 所以也是不可取。
class C extends Taro.Component {
render() {
const a = 1
return <View>{a}</View>
}
}
// 编译后
// ...
var a = 1
Object.assign(this.__state, {
aa: aa
})
// ...
最终还是只能用原生的方法来实现。
解决
对于数据处理, 则像上面一样, 分次写入数据。
Page({
data: {
arr: []
},
setImg() {
const arr = []
const baseStr = '....' // > 1024kb
const step = 1024 * 1024
for (let i = 0, j = 0; i < baseStr.length; i = i + step, j++) {
const key = `arr[${i}]`
this.setData({
[key]: baseStr.subStr(i, step)
})
}
}
})
数据处理完毕后, 需要将数据拼接成原字符串, 并且赋值给src
, 而小程序wxml
不支持嵌入复杂表达式。
但是小程序中的wxs
却可以进行复杂运算, 并且在wxml
中使用, 请参考。 那么便可以将拼接字符串的操作放在wxs
中, 然后在wxml
中调用即可
<wxs module="m1">
function join(arr) { return arr.join('') } module.exports.join = join;
</wxs>
<image src="{{m1.join(arr)}}" mode="aspectFill" lazy-load></image>
这样便能使用base64
来展示图片。