宝哥软件园

如何在微信小程序中用自定义组件打包原生图像组件

编辑:宝哥软件园 来源:互联网 时间:2021-12-07

零、问题的由来

在前端显示图片时,一般满足这两个常见要求:

图片未加载时,先显示位图,加载后再显示实际图片。如果图片链接有问题(例如,404),位图仍会显示。你甚至可以添加点击图片并重新加载的功能。(比如知乎)但是,applet的原生组件image并不提供这些常见的功能。

微信小程序之如何使用自定义组件封装原生 image  组件(图1)

注意:这里增加了2s的延迟。

一、常规操作

小程序还没有启动自定义组件功能的时候,只能通过改变Page中的数据来显示底部位图,所以当时的处理方法非常痛苦。

1.1.相同默认图

因为我们需要知道这张图片的数据路径,所以我们必须给每张图片添加类似data-img-path的内容。

view wx : for=' { { obj . arr } } ' wx : key=' IMgsrc ' wx : for-item=' item ' wx : for-index=' ItemIdx ' image src=' { { item . IMgsrc } } Binderror=' on imageerror ' data-IMg-path=' obj . arr[{ { ItemIdx } }]。img src '/view/copy code const DEFAULT _ IMG='/assets/your _ DEFAULT _ img ' page({ data : { obj : { arr :[{ IMGsrc : ' your _ img 1 ' },{ imgSrc: 'your_img2' },],},},Magerror({ target 3: { dataset 3: { img path } }){ this。setdata({[img path]: default _ img,}}})复制代码

1.2.不同默认图

如果默认图片不一样怎么办?比如玩家、队伍、feed的默认图片一般都不一样。

通常,我们必须添加另一个属性,如data-img-type来标识默认图的类型。

!-团队地图-图像.data-img-type=' team'/!-玩家地图-图像.data-img-type=' player '/copy code const default _ img _ map={ feed 3360 '/assets/default _ feed ',team3360'/assets/default _ team ',player : '/assets/default _ player ',} Page({ data : { obj : { arr :[{ imgsrc 3: ' your _ img 1 ' },],}}setdata({[img path]: default _ img _ map[img type],})},})复制代码

g-4">1.3.图片在模板中

页面层级浅倒还好,如果跨模板了,那么模板就可能要用一个类似于pathPrefix的属性来传递模板数据的路径前缀。

<!--    球员排行模板    pathPrefix: String    playerList: Array    ...--><template name="srPlayerRank">    <view        wx:for="{{ playerList }}"        wx:key="imgSrc"        wx:for-item="item"        wx:for-index="itemIdx"    >        <image            src="{{ item.imgSrc }}"            binderror="onImageError"            data-img-type="player"            data-img-path="{{ pathPrefix }}.playerList[{{ itemIdx }}].imgSrc"        />    </view></template>复制代码

最后在失败回调里调用setData({ [path]: DEFAULT_IMG })重新设置图片地址。

就问你蛋不蛋疼?这一坨data-img-path="{{ pathPrefix }}.playerList[{{ itemIdx }}].imgSrc"代码真让人无发可脱...

微信小程序之如何使用自定义组件封装原生 image 组件(图2)

二、自定义组件

有了自定义组件后,用领袖【窃·格瓦拉】的话来说的话就是:“感觉好 door 了~”

微信小程序之如何使用自定义组件封装原生 image 组件(图3)2.1.原生自定义组件

原生写法一般要写4个文件:.json/.wxml/.js/.wxss

  • TuaImage.json
{%20%20%20%20"component":%20true}复制代码
  • TuaImage.wxml
<!--%20加载中的图片%20--><image%20%20%20%20hidden="{{%20!isLoading%20}}"%20%20%20%20src="{{%20errSrc%20}}"%20%20%20%20style="width:%20{{%20width%20}};%20height:%20{{%20height%20}};%20{{%20styleStr%20}}"%20%20%20%20mode="{{%20imgMode%20}}"/><!--%20实际加载的图片%20--><image%20%20%20%20hidden="{{%20isLoading%20}}"%20%20%20%20src="{{%20imgSrc%20||%20src%20}}"%20%20%20%20mode="{{%20imgMode%20}}"%20%20%20%20style="width:%20{{%20width%20}};%20height:%20{{%20height%20}};%20{{%20styleStr%20}}"%20%20%20%20bindload="_onImageLoad"%20%20%20%20binderror="_onImageError"%20%20%20%20lazy-load="{{%20true%20}}"/>复制代码
  • TuaImage.js
const%20DEFAULT_IMG%20=%20'/assets/your_default_img'Component({%20%20%20%20properties:%20{%20%20%20%20%20%20%20%20//%20图片地址%20%20%20%20%20%20%20%20src:%20String,%20%20%20%20%20%20%20%20//%20图片加载中,以及加载失败后的默认地址%20%20%20%20%20%20%20%20errSrc:%20{%20%20%20%20%20%20%20%20%20%20%20%20type:%20String,%20%20%20%20%20%20%20%20%20%20%20%20//%20默认是球队图标%20%20%20%20%20%20%20%20%20%20%20%20value:%20DEFAULT_IMG,%20%20%20%20%20%20%20%20},%20%20%20%20%20%20%20%20width:%20{%20%20%20%20%20%20%20%20%20%20%20%20type:%20String,%20%20%20%20%20%20%20%20%20%20%20%20value:%20'48rpx',%20%20%20%20%20%20%20%20},%20%20%20%20%20%20%20%20height:%20{%20%20%20%20%20%20%20%20%20%20%20%20type:%20String,%20%20%20%20%20%20%20%20%20%20%20%20value:%20'48rpx',%20%20%20%20%20%20%20%20},%20%20%20%20%20%20%20%20//%20样式字符串%20%20%20%20%20%20%20%20styleStr:%20{%20%20%20%20%20%20%20%20%20%20%20%20type:%20String,%20%20%20%20%20%20%20%20%20%20%20%20value:%20'',%20%20%20%20%20%20%20%20},%20%20%20%20%20%20%20%20//%20图片裁剪、缩放的模式(详见文档)%20%20%20%20%20%20%20%20imgMode:%20{%20%20%20%20%20%20%20%20%20%20%20%20type:%20String,%20%20%20%20%20%20%20%20%20%20%20%20value:%20'scaleToFill',%20%20%20%20%20%20%20%20},%20%20%20%20},%20%20%20%20data:%20{%20%20%20%20%20%20%20%20imgSrc:%20'',%20%20%20%20%20%20%20%20isLoading:%20true,%20%20%20%20},%20%20%20%20methods:%20{%20%20%20%20%20%20%20%20//%20加载图片出错%20%20%20%20%20%20%20%20_onImageError%20(e)%20{%20%20%20%20%20%20%20%20%20%20%20%20this.setData({%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20imgSrc:%20this.data.errSrc,%20%20%20%20%20%20%20%20%20%20%20%20})%20%20%20%20%20%20%20%20%20%20%20%20this.triggerEvent('onImageError',%20e)%20%20%20%20%20%20%20%20},%20%20%20%20%20%20%20%20//%20加载图片完毕%20%20%20%20%20%20%20%20_onImageLoad%20(e)%20{%20%20%20%20%20%20%20%20%20%20%20%20this.setData({%20isLoading:%20false%20})%20%20%20%20%20%20%20%20%20%20%20%20this.triggerEvent('onImageLoad',%20e)%20%20%20%20%20%20%20%20},%20%20%20%20},})复制代码

布吉岛大家使用原生写法时有木有一些感觉不方便的地方:

  • 4个文件:.json/.wxml/.js/.wxss,这样老需要切来切去的降低效率
  • properties是什么鬼?大家(React/Vue)一般不都用props么?
  • style="width:%20{{%20width%20}};%20height:%20{{%20height%20}};%20{{%20styleStr%20}}"样式字符串怎么辣么长...
2.2.TuaImage.vue

所以以下是一个使用单文件组件封装原生%20image%20组件的例子。

  • 使用单文件组件将配置、模板、脚本、样式写在一个文件中,方便维护。
  • 使用计算属性computed将样式字符串写在%20js%20中。
  • 使用this.imgSrc%20=%20this.errSrc而不是this.setData来改变data。
<config>{%20%20%20%20"component":%20true}</config><template%20lang="wxml">%20%20%20%20<!--%20加载中的图片%20-->%20%20%20%20<image%20%20%20%20%20%20%20%20hidden="{{%20!isLoading%20}}"%20%20%20%20%20%20%20%20src="{{%20errSrc%20}}"%20%20%20%20%20%20%20%20style="{{%20imgStyleStr%20}}"%20%20%20%20%20%20%20%20mode="{{%20imgMode%20}}"%20%20%20%20/>%20%20%20%20<!--%20实际加载的图片%20-->%20%20%20%20<image%20%20%20%20%20%20%20%20hidden="{{%20isLoading%20}}"%20%20%20%20%20%20%20%20src="{{%20imgSrc%20||%20src%20}}"%20%20%20%20%20%20%20%20mode="{{%20imgMode%20}}"%20%20%20%20%20%20%20%20style="{{%20imgStyleStr%20}}"%20%20%20%20%20%20%20%20bindload="_onImageLoad"%20%20%20%20%20%20%20%20binderror="_onImageError"%20%20%20%20%20%20%20%20lazy-load="{{%20true%20}}"%20%20%20%20/></template><script>/**%20*%20图片组件,能够传递备用图片以防图片失效%20*%20https://developers.weixin.qq.com/miniprogram/dev/component/image.html%20*///%20也可以设置为网络图片如:%20https://foo/bar.pngconst DEFAULT_IMG = '/assets/your_default_img'export default {    props: {        // 图片地址        src: String,        // 图片加载中,以及加载失败后的默认地址        errSrc: {            type: String,            // 默认是球队图标            default: DEFAULT_IMG,        },        width: {            type: String,            default: '48rpx',        },        height: {            type: String,            default: '48rpx',        },        // 样式字符串        styleStr: {            type: String,            default: '',        },        // 图片裁剪、缩放的模式(详见文档)        imgMode: {            type: String,            default: 'scaleToFill',        },    },    data () {        return {            imgSrc: '',            isLoading: true,        }    },    computed: {        // 样式字符串        imgStyleStr () {            return `width: ${this.width}; height: ${this.height}; ${this.styleStr}`        },    },    methods: {        // 加载图片出错        _onImageError (e) {            this.imgSrc = this.errSrc            this.$emit('onImageError', e)        },        // 加载图片完毕        _onImageLoad (e) {            this.isLoading = false            this.$emit('onImageLoad', e)        },    },}</script><style lang="scss"></style>
更多资讯
游戏推荐
更多+