<p><code></p> <h2 id="articleHeader0">零、问题的由来</h2> <p>一般在前端展示图片时都会碰到这两个常见的需求:</p> <ol> <li>图片未加载完成时先展示占位图,等到图片加载完毕后再展示实际的图片。</li> <li>假如图片链接有问题(比如 404),依然展示占位图。甚至你还可以增加点击图片再次加载的功能。(例如知乎)</li> </ol> <p>然鹅,小程序原生组件 image 并没有提供这些常用功能...</p> <p><span class="img-wrap"><img data-src="https://user-gold-cdn.xitu.io/2018/8/12/1652de20a0bbc809?w=434&amp;h=683&amp;f=gif&amp;s=867184" src="https://static.segmentfault.com/v-5cc2cd8e/global/img/squares.svg" alt="TuaImage" title="TuaImage" style="cursor: pointer;"></span></p> <blockquote><p>注:这里加了 2s 的延迟</p></blockquote> <h2 id="articleHeader1">一、常规操作</h2> <p>在小程序没还没推出自定义组件功能时,只能通过改变 Page 中的 data 来展示兜底的占位图,所以当时的处理方式十分蛋疼...</p> <h3 id="articleHeader2">1.1.相同默认图</h3> <p>由于需要知道这个图片的数据路径,所以不得不在每个 <code>image</code> 上加上类似 <code>data-img-path</code> 的东西。</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="<view wx_for=&quot;{{ obj.arr }}&quot; wx_key=&quot;imgSrc&quot; wx:for-item=&quot;item&quot; wx:for-index=&quot;itemIdx&quot; ><br /> <image src=&quot;{{ item.imgSrc }}&quot; binderror=&quot;onImageError&quot; data-img-path=&quot;obj.arr[{{ itemIdx }}].imgSrc&quot; ></image><br /> </view>" title="" data-original-title="复制"></span> </div> </p></div> <pre class="xml hljs"><code class="html"><span class="hljs-tag">&lt;<span class="hljs-name">view</span> <span class="hljs-attr">wx:for</span>=<span class="hljs-string">"{{ obj.arr }}"</span> <span class="hljs-attr">wx:key</span>=<span class="hljs-string">"imgSrc"</span> <span class="hljs-attr">wx:for-item</span>=<span class="hljs-string">"item"</span> <span class="hljs-attr">wx:for-index</span>=<span class="hljs-string">"itemIdx"</span> &gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">image</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"{{ item.imgSrc }}"</span> <span class="hljs-attr">binderror</span>=<span class="hljs-string">"onImageError"</span> <span class="hljs-attr">data-img-path</span>=<span class="hljs-string">"obj.arr[{{ itemIdx }}].imgSrc"</span> /&gt;</span> <span class="hljs-tag">&lt;/<span class="hljs-name">view</span>&gt;</span></code></pre> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="const DEFAULT_IMG = '/assets/your_default_img' Page({ data: { obj: { arr: [ { imgSrc: 'your_img1' }, { imgSrc: 'your_img2' }, ], }, }, onImageError ({ target: { dataset: { imgPath } }, }) { this.setData({ [imgPath]: DEFAULT_IMG, }) }, })" title="" data-original-title="复制"></span> </div> </p></div> <pre class="javascript hljs"><code class="js"><span class="hljs-keyword"><a href="http://www.js-code.com/tag/const" title="浏览关于“const”的文章" target="_blank" class="tag_link">const</a></span> DEFAULT_IMG = <span class="hljs-string">'/assets/your_default_img'</span> Page({ <span class="hljs-attr">data</span>: { <span class="hljs-attr">obj</span>: { <span class="hljs-attr">arr</span>: [ { <span class="hljs-attr">imgSrc</span>: <span class="hljs-string">'your_img1'</span> }, { <span class="hljs-attr">imgSrc</span>: <span class="hljs-string">'your_img2'</span> }, ], }, }, onImageError ({ <span class="hljs-attr">target</span>: { <span class="hljs-attr">dataset</span>: { imgPath } }, }) { <span class="hljs-keyword"><a href="http://www.js-code.com/tag/this" title="浏览关于“this”的文章" target="_blank" class="tag_link">this</a></span>.setData({ [imgPath]: DEFAULT_IMG, }) }, })</code></pre> <h3 id="articleHeader3">1.2.不同默认图</h3> <p>如果默认图片不同呢?例如球员、球队和 feed 的默认图片一般都是不同的。</p> <p>那么一般只好再增加一个属性例如 <code>data-img-type</code> 来标识默认图的类型。</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="<!-- 球队图 --><br /> <image ... data-img-type=&quot;team&quot; ></image><br /> <!-- 球员图 --><br /> <image ... data-img-type=&quot;player&quot; ></image>" title="" data-original-title="复制"></span> </div> </p></div> <pre class="xml hljs"><code class="html"><span class="hljs-comment">&lt;!-- 球队图 --&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">image</span> <span class="hljs-attr">...</span> <span class="hljs-attr">data-img-type</span>=<span class="hljs-string">"team"</span> /&gt;</span> <span class="hljs-comment">&lt;!-- 球员图 --&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">image</span> <span class="hljs-attr">...</span> <span class="hljs-attr">data-img-type</span>=<span class="hljs-string">"player"</span> /&gt;</span></code></pre> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="const DEFAULT_IMG_MAP = { feed: '/assets/default_feed', team: '/assets/default_team', player: '/assets/default_player', } Page({ data: { obj: { arr: [ { imgSrc: 'your_img1' }, { imgSrc: 'your_img2' }, ], }, }, onImageError ({ target: { dataset: { imgPath, imgType } }, }) { this.setData({ [imgPath]: DEFAULT_IMG_MAP[imgType], }) }, })" title="" data-original-title="复制"></span> </div> </p></div> <pre class="javascript hljs"><code class="js"><span class="hljs-keyword">const</span> DEFAULT_IMG_MAP = { <span class="hljs-attr">feed</span>: <span class="hljs-string">'/assets/default_feed'</span>, <span class="hljs-attr">team</span>: <span class="hljs-string">'/assets/default_team'</span>, <span class="hljs-attr">player</span>: <span class="hljs-string">'/assets/default_player'</span>, } Page({ <span class="hljs-attr">data</span>: { <span class="hljs-attr">obj</span>: { <span class="hljs-attr">arr</span>: [ { <span class="hljs-attr">imgSrc</span>: <span class="hljs-string">'your_img1'</span> }, { <span class="hljs-attr">imgSrc</span>: <span class="hljs-string">'your_img2'</span> }, ], }, }, onImageError ({ <span class="hljs-attr">target</span>: { <span class="hljs-attr">dataset</span>: { imgPath, imgType } }, }) { <span class="hljs-keyword">this</span>.setData({ [imgPath]: DEFAULT_IMG_MAP[imgType], }) }, })</code></pre> <h3 id="articleHeader4">1.3.图片在模板中</h3> <p>页面层级浅倒还好,如果跨模板了,那么模板就可能要用一个类似于 <code>pathPrefix</code> 的属性来传递模板数据的路径前缀。</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="<!-- 球员排行模板 pathPrefix: String playerList: Array ... --><br /> <template name=&quot;srPlayerRank&quot;><br /> <view wx_for=&quot;{{ playerList }}&quot; wx_key=&quot;imgSrc&quot; wx:for-item=&quot;item&quot; wx:for-index=&quot;itemIdx&quot; ><br /> <image src=&quot;{{ item.imgSrc }}&quot; binderror=&quot;onImageError&quot; data-img-type=&quot;player&quot; data-img-path=&quot;{{ pathPrefix }}.playerList[{{ itemIdx }}].imgSrc&quot; ></image><br /> </view><br /> </template>" title="" data-original-title="复制"></span> </div> </p></div> <pre class="xml hljs"><code class="html"><span class="hljs-comment">&lt;!-- 球员排行模板 pathPrefix: String playerList: <a href="http://www.js-code.com/tag/array" title="浏览关于“Array”的文章" target="_blank" class="tag_link">Array</a> ... --&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">template</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"srPlayerRank"</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">view</span> <span class="hljs-attr">wx:for</span>=<span class="hljs-string">"{{ playerList }}"</span> <span class="hljs-attr">wx:key</span>=<span class="hljs-string">"imgSrc"</span> <span class="hljs-attr">wx:for-item</span>=<span class="hljs-string">"item"</span> <span class="hljs-attr">wx:for-index</span>=<span class="hljs-string">"itemIdx"</span> &gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">image</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"{{ item.imgSrc }}"</span> <span class="hljs-attr">binderror</span>=<span class="hljs-string">"onImageError"</span> <span class="hljs-attr">data-img-type</span>=<span class="hljs-string">"player"</span> <span class="hljs-attr">data-img-path</span>=<span class="hljs-string">"{{ pathPrefix }}.playerList[{{ itemIdx }}].imgSrc"</span> /&gt;</span> <span class="hljs-tag">&lt;/<span class="hljs-name">view</span>&gt;</span> <span class="hljs-tag">&lt;/<span class="hljs-name">template</span>&gt;</span></code></pre> <p>最后在失败回调里调用 <code>setData({ [path]: DEFAULT_IMG })</code> 重新设置图片地址。</p> <p>就问你蛋不蛋疼?这一坨 <code>data-img-path="{{ pathPrefix }}.playerList[{{ itemIdx }}].imgSrc"</code> 代码真让人无发可脱...</p> <p><span class="img-wrap"><img data-src="https://buptsteve.github.io/blog/imgs/tua-mp/%E5%95%A5%E5%95%A5%E5%95%A5%E5%86%99%E7%9A%84%E8%BF%99%E6%98%AF%E5%95%A5.jpg" src="https://static.segmentfault.com/v-5cc2cd8e/global/img/squares.svg" alt="啥啥啥写的这是啥" title="啥啥啥写的这是啥" style="cursor: pointer;"></span></p> <h2 id="articleHeader5">二、自定义组件</h2> <p>有了自定义组件后,用领袖【窃·格瓦拉】的话来说的话就是:“感觉好 door 了~”</p> <p><span class="img-wrap"><img data-src="https://camo.githubusercontent.com/f0c9b64e0c302bad63fb7cd9132c08b0e18acde8/68747470733a2f2f6275707473746576652e6769746875622e696f2f626c6f672f696d67732f7475612d6d702fe7a8b32e6a7067" src="https://static.segmentfault.com/v-5cc2cd8e/global/img/squares.svg" alt="" title="" style="cursor: pointer;"></span></p> <h3 id="articleHeader6">2.1.原生自定义组件</h3> <p>原生写法一般要写4个文件:<code>.json</code>/<code>.wxml</code>/<code>.js</code>/<code>.wxss</code></p> <ul> <li>TuaImage.json</li> </ul> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="{ &quot;component&quot;: true }" title="" data-original-title="复制"></span> </div> </p></div> <pre class="json hljs"><code class="json">{ <span class="hljs-attr">"component"</span>: <span class="hljs-literal">true</span> }</code></pre> <ul> <li>TuaImage.wxml</li> </ul> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="<!-- 加载中的图片 --><br /> <image hidden=&quot;{{ !isLoading }}&quot; src=&quot;{{ errSrc }}&quot; style=&quot;width: {{ width }}; height: {{ height }}; {{ styleStr }}&quot; mode=&quot;{{ imgMode }}&quot; ></image></p> <p><!-- 实际加载的图片 --><br /> <image hidden=&quot;{{ isLoading }}&quot; src=&quot;{{ imgSrc || src }}&quot; mode=&quot;{{ imgMode }}&quot; style=&quot;width: {{ width }}; height: {{ height }}; {{ styleStr }}&quot; bindload=&quot;_onImageLoad&quot; binderror=&quot;_onImageError&quot; lazy-load=&quot;{{ true }}&quot; ></image>" title="" data-original-title="复制"></span> </div> </p></div> <pre class="xml hljs"><code class="html"><span class="hljs-comment">&lt;!-- 加载中的图片 --&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">image</span> <span class="hljs-attr">hidden</span>=<span class="hljs-string">"{{ !isLoading }}"</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"{{ errSrc }}"</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"width: {{ width }}; height: {{ height }}; {{ styleStr }}"</span> <span class="hljs-attr">mode</span>=<span class="hljs-string">"{{ imgMode }}"</span> /&gt;</span> <span class="hljs-comment">&lt;!-- 实际加载的图片 --&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">image</span> <span class="hljs-attr">hidden</span>=<span class="hljs-string">"{{ isLoading }}"</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"{{ imgSrc || src }}"</span> <span class="hljs-attr">mode</span>=<span class="hljs-string">"{{ imgMode }}"</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"width: {{ width }}; height: {{ height }}; {{ styleStr }}"</span> <span class="hljs-attr">bindload</span>=<span class="hljs-string">"_onImageLoad"</span> <span class="hljs-attr">binderror</span>=<span class="hljs-string">"_onImageError"</span> <span class="hljs-attr">lazy-load</span>=<span class="hljs-string">"{{ true }}"</span> /&gt;</span></code></pre> <ul> <li>TuaImage.js</li> </ul> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="const DEFAULT_IMG = '/assets/your_default_img' Component({ properties: { // 图片地址 src: String, // 图片加载中,以及加载失败后的默认地址 errSrc: { type: String, // 默认是球队图标 value: DEFAULT_IMG, }, width: { type: String, value: '48rpx', }, height: { type: String, value: '48rpx', }, // 样式字符串 styleStr: { type: String, value: '', }, // 图片裁剪、缩放的模式(详见文档) imgMode: { type: String, value: 'scaleToFill', }, }, data: { imgSrc: '', isLoading: true, }, methods: { // 加载图片出错 _onImageError (e) { this.setData({ imgSrc: this.data.errSrc, }) this.triggerEvent('onImageError', e) }, // 加载图片完毕 _onImageLoad (e) { this.setData({ isLoading: false }) this.triggerEvent('onImageLoad', e) }, }, })" title="" data-original-title="复制"></span> </div> </p></div> <pre class="javascript hljs"><code class="js"><span class="hljs-keyword">const</span> DEFAULT_IMG = <span class="hljs-string">'/assets/your_default_img'</span> Component({ <span class="hljs-attr">properties</span>: { <span class="hljs-comment">// 图片地址</span> src: <span class="hljs-built_in">String</span>, <span class="hljs-comment">// 图片加载中,以及加载失败后的默认地址</span> errSrc: { <span class="hljs-attr">type</span>: <span class="hljs-built_in">String</span>, <span class="hljs-comment">// 默认是球队图标</span> value: DEFAULT_IMG, }, <span class="hljs-attr">width</span>: { <span class="hljs-attr">type</span>: <span class="hljs-built_in">String</span>, <span class="hljs-attr">value</span>: <span class="hljs-string">'48rpx'</span>, }, <span class="hljs-attr">height</span>: { <span class="hljs-attr">type</span>: <span class="hljs-built_in">String</span>, <span class="hljs-attr">value</span>: <span class="hljs-string">'48rpx'</span>, }, <span class="hljs-comment">// 样式字符串</span> styleStr: { <span class="hljs-attr">type</span>: <span class="hljs-built_in">String</span>, <span class="hljs-attr">value</span>: <span class="hljs-string">''</span>, }, <span class="hljs-comment">// 图片裁剪、缩放的模式(详见文档)</span> imgMode: { <span class="hljs-attr">type</span>: <span class="hljs-built_in">String</span>, <span class="hljs-attr">value</span>: <span class="hljs-string">'scaleToFill'</span>, }, }, <span class="hljs-attr">data</span>: { <span class="hljs-attr">imgSrc</span>: <span class="hljs-string">''</span>, <span class="hljs-attr">isLoading</span>: <span class="hljs-literal">true</span>, }, <span class="hljs-attr">methods</span>: { <span class="hljs-comment">// 加载图片出错</span> _onImageError (e) { <span class="hljs-keyword">this</span>.setData({ <span class="hljs-attr">imgSrc</span>: <span class="hljs-keyword">this</span>.data.errSrc, }) <span class="hljs-keyword">this</span>.triggerEvent(<span class="hljs-string">'onImageError'</span>, e) }, <span class="hljs-comment">// 加载图片完毕</span> _onImageLoad (e) { <span class="hljs-keyword">this</span>.setData({ <span class="hljs-attr">isLoading</span>: <span class="hljs-literal">false</span> }) <span class="hljs-keyword">this</span>.triggerEvent(<span class="hljs-string">'onImageLoad'</span>, e) }, }, })</code></pre> <p>布吉岛大家使用原生写法时有木有一些感觉不方便的地方:</p> <ul> <li>4个文件:<code>.json</code>/<code>.wxml</code>/<code>.js</code>/<code>.wxss</code>,这样老需要切来切去的降低效率</li> <li> <code>properties</code> 是什么鬼?大家(<a href="http://www.js-code.com/tag/react" title="React" target="_blank">React</a>/<a href="http://www.js-code.com/tag/vue" title="Vue" target="_blank">Vue</a>)一般不都用 <code>props</code> 么?</li> <li> <code>style="width: {{ width }}; height: {{ height }}; {{ styleStr }}"</code> 样式字符串怎么辣么长...</li> </ul> <h3 id="articleHeader7">2.2.TuaImage.vue</h3> <p>所以以下是一个使用单文件组件封装原生 image 组件的例子。</p> <ul> <li>使用单文件组件将配置、模板、脚本、样式写在一个文件中,方便维护。</li> <li>使用计算属性 <code>computed</code> 将样式字符串写在 js 中。</li> <li>使用 <code><a href="http://www.js-code.com/tag/this" title="this" target="_blank">this</a>.imgSrc = <a href="http://www.js-code.com/tag/this" title="this" target="_blank">this</a>.errSrc</code> 而不是 <code>this.setData</code> 来改变 <code>data</code>。</li> </ul> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="<config><br /> {<br /> &quot;component&quot;: true<br /> }<br /> </config></p> <p><template lang=&quot;wxml&quot;><br /> <!-- 加载中的图片 --><br /> <image hidden=&quot;{{ !isLoading }}&quot; src=&quot;{{ errSrc }}&quot; style=&quot;{{ imgStyleStr }}&quot; mode=&quot;{{ imgMode }}&quot; ></image></p> <p> <!-- 实际加载的图片 --><br /> <image hidden=&quot;{{ isLoading }}&quot; src=&quot;{{ imgSrc || src }}&quot; mode=&quot;{{ imgMode }}&quot; style=&quot;{{ imgStyleStr }}&quot; bindload=&quot;_onImageLoad&quot; binderror=&quot;_onImageError&quot; lazy-load=&quot;{{ true }}&quot; ></image><br /> </template></p> <p><script> /** * 图片组件,能够传递备用图片以防图片失效 * https://developers.<a href="http://www.js-code.com/tag/weixin" title="weixin" target="_blank">weixin</a>.qq.com/miniprogram/dev/component/image.html */</p> <p>// 也可以设置为网络图片如: https://foo/bar.png <a href="http://www.js-code.com/tag/const" title="const" target="_blank">const</a> DEFAULT_IMG = '/assets/your_default_img'</p> <p><a href="http://www.js-code.com/tag/export" title="export" target="_blank">export</a> 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></p> <style lang=&quot;scss&quot;> </style> <p>" title="" data-original-title="复制"></span> </div> </p></div> <pre class="xml hljs"><code class="html"><span class="hljs-tag">&lt;<span class="hljs-name">config</span>&gt;</span> { "component": true } <span class="hljs-tag">&lt;/<span class="hljs-name">config</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">template</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"wxml"</span>&gt;</span> <span class="hljs-comment">&lt;!-- 加载中的图片 --&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">image</span> <span class="hljs-attr">hidden</span>=<span class="hljs-string">"{{ !isLoading }}"</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"{{ errSrc }}"</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"{{ imgStyleStr }}"</span> <span class="hljs-attr">mode</span>=<span class="hljs-string">"{{ imgMode }}"</span> /&gt;</span> <span class="hljs-comment">&lt;!-- 实际加载的图片 --&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">image</span> <span class="hljs-attr">hidden</span>=<span class="hljs-string">"{{ isLoading }}"</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"{{ imgSrc || src }}"</span> <span class="hljs-attr">mode</span>=<span class="hljs-string">"{{ imgMode }}"</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"{{ imgStyleStr }}"</span> <span class="hljs-attr">bindload</span>=<span class="hljs-string">"_onImageLoad"</span> <span class="hljs-attr">binderror</span>=<span class="hljs-string">"_onImageError"</span> <span class="hljs-attr">lazy-load</span>=<span class="hljs-string">"{{ true }}"</span> /&gt;</span> <span class="hljs-tag">&lt;/<span class="hljs-name">template</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript"> <span class="hljs-comment">/** * 图片组件,能够传递备用图片以防图片失效 * https://developers.<a href="http://www.js-code.com/tag/weixin" title="浏览关于“weixin”的文章" target="_blank" class="tag_link">weixin</a>.qq.com/miniprogram/dev/component/image.html */</span> <span class="hljs-comment">// 也可以设置为网络图片如: https://foo/bar.png</span> <span class="hljs-keyword">const</span> DEFAULT_IMG = <span class="hljs-string">'/assets/your_default_img'</span> <span class="hljs-keyword"><a href="http://www.js-code.com/tag/export" title="浏览关于“export”的文章" target="_blank" class="tag_link">export</a></span> <span class="hljs-keyword">default</span> { <span class="hljs-attr">props</span>: { <span class="hljs-comment">// 图片地址</span> src: <span class="hljs-built_in">String</span>, <span class="hljs-comment">// 图片加载中,以及加载失败后的默认地址</span> errSrc: { <span class="hljs-attr">type</span>: <span class="hljs-built_in">String</span>, <span class="hljs-comment">// 默认是球队图标</span> <span class="hljs-keyword">default</span>: DEFAULT_IMG, }, <span class="hljs-attr">width</span>: { <span class="hljs-attr">type</span>: <span class="hljs-built_in">String</span>, <span class="hljs-attr">default</span>: <span class="hljs-string">'48rpx'</span>, }, <span class="hljs-attr">height</span>: { <span class="hljs-attr">type</span>: <span class="hljs-built_in">String</span>, <span class="hljs-attr">default</span>: <span class="hljs-string">'48rpx'</span>, }, <span class="hljs-comment">// 样式字符串</span> styleStr: { <span class="hljs-attr">type</span>: <span class="hljs-built_in">String</span>, <span class="hljs-attr">default</span>: <span class="hljs-string">''</span>, }, <span class="hljs-comment">// 图片裁剪、缩放的模式(详见文档)</span> imgMode: { <span class="hljs-attr">type</span>: <span class="hljs-built_in">String</span>, <span class="hljs-attr">default</span>: <span class="hljs-string">'scaleToFill'</span>, }, }, data () { <span class="hljs-keyword">return</span> { <span class="hljs-attr">imgSrc</span>: <span class="hljs-string">''</span>, <span class="hljs-attr">isLoading</span>: <span class="hljs-literal">true</span>, } }, <span class="hljs-attr">computed</span>: { <span class="hljs-comment">// 样式字符串</span> imgStyleStr () { <span class="hljs-keyword">return</span> <span class="hljs-string">`width: <span class="hljs-subst">${<span class="hljs-keyword">this</span>.width}</span>; height: <span class="hljs-subst">${<span class="hljs-keyword">this</span>.height}</span>; <span class="hljs-subst">${<span class="hljs-keyword">this</span>.styleStr}</span>`</span> }, }, <span class="hljs-attr">methods</span>: { <span class="hljs-comment">// 加载图片出错</span> _onImageError (e) { <span class="hljs-keyword">this</span>.imgSrc = <span class="hljs-keyword">this</span>.errSrc <span class="hljs-keyword">this</span>.$emit(<span class="hljs-string">'onImageError'</span>, e) }, <span class="hljs-comment">// 加载图片完毕</span> _onImageLoad (e) { <span class="hljs-keyword">this</span>.isLoading = <span class="hljs-literal">false</span> <span class="hljs-keyword">this</span>.$emit(<span class="hljs-string">'onImageLoad'</span>, e) }, }, } </span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">style</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"scss"</span>&gt;</span><span class="undefined"> </span><span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span></code></pre> <p>采用框架是 tua-mp:</p> <ul> <li><a href="https://github.com/tuateam/tua-mp" rel="nofollow noreferrer" target="_blank">github 源码地址</a></li> </ul> <p>相关文章:</p> <ul> <li><a href="https://juejin.im/post/5b7016f96fb9a00981655b39" rel="nofollow noreferrer" target="_blank">终极蛇皮上帝视角之微信小程序之告别 setData</a></li> <li><a href="https://juejin.im/post/5b70182bf265da281306deac" rel="nofollow noreferrer" target="_blank">终极蛇皮上帝视角之微信小程序之告别“刀耕火种”</a></li> </ul> <p></code></p>

本文固定链接: http://www.js-code.com/weixin/weixin_46834.html