vue的 v-for 循环中图片加载路径问题
先看一下产品需求,如下图所示,
产品要求图片和它的名称一一对应,本来是非常简单的需求,后台直接返回图片路径和名称,前台直接读取就可以了,但是我们没有存储图片的服务器,再加上是一个实验性的需求,图片需要存放到前台。当时我想,vue 中的img 的src 可以动态绑定到一个变量上, 很简单吗,就没有考虑太多,直接开始做了。
首先和后台商量一下数据结构,因为图片要和名称一一对应,所以后台要返回中英文的名称的映射,我把前台的图片名称直接设置给后台给的英文名称,从而读取图片,图片和中文名称就一一对应了。数据结构如下:映射关系用对象表示,多个图片,所以放到一个数组中
- [
- {
- CnName:'荷花',
- EnName: 'lotus'
- },
- {
- CnName:'康乃馨',
- EnName: 'carnations'
- },
- {
- CnName:'牡丹',
- EnName: 'peony'
- }
- ]
现在前台用vue-cli, 后台用express 来模拟一下当时的开发场景,也可以还原一下错误和业务的迭代过程。新建一个文件夹,就叫vue-img吧,然后再在该文件夹中新建两个文件夹,client, server, client 表示客户端代码,server 表示服务端代码。 在client 文件夹中,打开命令窗口,执行 vue init webpack-simple . 命令,后面的点表示当前文件夹,为了简单,这里使用了simple 模版. server 文件夹,打开命令窗口,先执行npm init 初始化为node 项目,然后npm install express cors --save, 安装依赖,cors 是解决跨域的。
先来写前端代码,把app.vue 中的template和script中的内容清空,保留它的css 样式内容,我们就不用写样式了。前端页面,有两个部分,一个是button, 点击按钮来发送请求,一个是图片展示区域,它用的就是v-for 循环, template 内容如下
- <div id="app">
- <button @click='getFlower'>点击加载请求</button>
- <!-- 由于当时想当然地以为,src 就是绑定一个变量,所以就设置了一个默认变量,这是出错的过程 -->
- <ul>
- <li v-for ="item in flowers" :key="item">
- <img :src="defaultImg" alt="flowers">
- <p>{{item}}</p>
- </li>
- </ul>
- </div>
- </template>
由于template中用到了方法 getFlower, 变量defaultImg 和 flowers, 所以要在script中进行声明。defaultImg 是一个图片,所以还要引入进来, 在src 目录中新建一个img文件夹,放几张图片。flowers是一个数组,我先预写了一个['荷花', '康乃馨'],getFlower,因为没有后台,所以先没有写, 注意如果数据量大的,交互复杂,是要写mock 数据的,这里比较简单就没有写。这也是出错的原因。代码如下
- import defaultImg from './img/lotus.jpg'; // import 引入图片
- export default {
- data() {
- return {
- flowers: ['荷花', '康乃馨'],
- defaultImg: defaultImg
- };
- },
- methods: {
- getFlower() {}
- }
- };
整个页面显示如下,我以为没有问题了。
现在再来写后台代码, 用express 写一个后台接口,还是非常简单的。在server 文件夹中,建一个文件server.js 来写后台代码
- var express = require('express');
- var cors = require('cors'); // 引入cors 中间件,解决跨域
- var app = express();
- app.use(cors());
- // 前端发送的是get请求,接口是flowers. 返回的数据code 表示成功或失败,obj 表示数据
- // 数据中Cn 表示中文名称,En表示中文名称
- app.get('/flowers', (req, res) => {
- res.json({
- code: 0,
- obj: [
- {
- CnName:'荷花',
- EnName: 'lotus'
- },
- {
- CnName:'康乃馨',
- EnName: 'carnations'
- },
- {
- CnName:'牡丹',
- EnName: 'peony'
- }
- ]
- })
- })
- app.listen(3000, () => {
- console.log('server start at 3000');
- })
现在用nodemon server.js 启动服务,在浏览器地址输入http://localhost:3000/flowers, 可以看到返回的数据表示接口ok.
现在再重新写一下前端代码,进行前后端联调。由于要发送请求,还要安装axios 依赖。首先要根据后台接口改一下template 内容的li
- <ul>
- <li v-for ="item in flowers" :key="item.EnName">
- <img :src="item.EnName" alt="flowers">
- <p>{{item.CnName}}</p>
- </li>
- </ul>
然后,在script中引入 axios, flowers 数组清空,default img 删除 , 引入后台数据所需要的三张图片, 同时getFlower 方法发送请求
- // 引入axios,用于发送请求,defaults 设置后台请求地址
- import axios from 'axios';
- axios.defaults.baseURL = "http://localhost:3000"
- // 引入相关的图片, 命名要和后台保持一致
- import lotus from './img/lotus.jpg';
- import carnations from './img/carnations.jpg';
- import peony from './img/peony.jpg';
- export default {
- data() {
- return {
- flowers: [],
- lotus,
- carnations,
- peony
- };
- },
- methods: {
- getFlower() {
- axios.get('/flowers')
- .then(res => {
- if(res.status === 200 && res.data.code === 0) {
- this.flowers = res.data.obj;
- }
- })
- }
- }
- };
我以为成功了,点击按钮发送请求,但是看到的如下画面,没有图片
当时想不通,img 的src 绑定的是变量,它和defaultImg 不应该是一样吗?打开浏览器控制台,看到如下内容,img 的src 已经是一个字符串,它不是我们想要的变量了。
我想这里可能是它对item.EnName进行了一次解析变成了字符串,就完事了,绑定变量,就是解析一次。而对于defalutImg 来说,它本来就是变量,无法再进行分割解析,所以它会去data 里面去找,如果找不到,才报错。
那么我们现在要做的就是把item.EnName 变成图片的地址,这样进行一次解析的时候,直接去读取图片。要怎么做到呢?当时 我也不是很清楚,就百度了一下,有人提到了require 方法, require 一个图片路径,我想require 什么,以前没有听说过require 这个关键字啊。想了一段时间,突然就明白了,require 是一个commonJs 规范的关键字,当我们在写node 代码的时候,都是有require 去读取资源的。在前端js 中,一直使用import,直接忘记了,不知道怎么用了。webpack 把img 当做一种资源,所以使用时要先引进。引进方式有两种,一种是import , 一种是require, 因为webpack 同时支持ES6 module 和 commonJs 规范. import 是个语句,只能在js 代码顶部使用, 而require 不一样,它是一个表达式,可以进行赋值操作。我们试一下,用require 引入图片是怎么样的效果,在 script 标签时,写下
- var img = require('./img/lotus.jpg');
- console.log(img);
刷新浏览器,在控制台上可以看到如下输出
正好是图片的路径,也正是我们想要的内容,刚才也说了,require是一个表达式,它可以用到任何js 表达式能用到的地方。我这时就想,把后台返回的代码进行重新组装,EnName 直接是图片路径。getFlower 方法修改如下
- getFlower() {
- axios.get('/flowers')
- .then(res => {
- if(res.status === 200 && res.data.code === 0) {
- this.flowers = res.data.obj.map(item => {
- return {
- CnName: item.CnName,
- EnName: require(`./img/${item.EnName}.jpg`) // 利用require 引入图片,获得图片路径
- }
- })
- }
- })
- }
这时刷新浏览器,点击按钮发送请求,可以看到图片了并且一一对应, 成功了。
这时又一想,既然require 是一个表达式,在template模版中是直接可以解析js 表达式,那么直接把img 的src 绑定到require 表达式就可以了,把getFlower 方法,回退到上一次代码,然后template 代码如下
- <ul>
- <li v-for ="item in flowers" :key="item.EnName">
- <img :src="require(`./img/${item.EnName}.jpg`)" alt="flowers">
- <p>{{item.CnName}}</p>
- </li>
- </ul>
同样也成功了。
最后写代码的时候发现,如果读取的图片不存在,上面的方法就会报错,并且没有办法处理。这时还要回到js 的代码处理。我又把html代码回到以前,然后在getFlower方法中进行错误处理,既然读取报错,我们读取的代码就放到try中, 如果有报错,就在catch 看处理,提供一个默认图片,try catch 处理读取异常。 try catch 的逻辑
- try {
- img = require(`./img/${item.EnName}.jpg`);
- } catch (err) {
- img = require('./img/lotus.jpg');
- }
整 个app.vue
- <template>
- <div id="app">
- <button @click='getFlower'>点击加载请求</button>
- <ul>
- <li v-for ="item in flowers" :key="item.EnName">
- <img :src="item.EnName" alt="flowers">
- <p>{{item.CnName}}</p>
- </li>
- </ul>
- </div>
- </template>
- <script>
- // 引入axios,用于发送请求,defaults 设置后台请求地址
- import axios from 'axios';
- axios.defaults.baseURL = "http://localhost:3000";
- export default {
- data() {
- return {
- flowers: []
- };
- },
- methods: {
- getFlower() {
- axios.get('/flowers')
- .then(res => {
- if(res.status === 200 && res.data.code === 0) {
- this.flowers = res.data.obj.map(item => {
- var img = null;
- try {
- img = require(`./img/${item.EnName}.jpg`);
- } catch (err) {
- img = require('./img/lotus.jpg');
- }
- return {
- CnName: item.CnName,
- EnName: img
- }
- })
- }
- })
- }
- }
- };
- </script>
vue的 v-for 循环中图片加载路径问题的更多相关文章
- Vue 动态图片加载路径问题和解决方法
最近在做一个树形结构的组件,使用了Vue和element UI中el-tree组件.因为树中每个节点都需要显示一个图标图片,并且需要根据后台传入的数据类型动态地显示,所以图片的路径需要动态地加载.下面 ...
- iOS 解决LaunchScreen中图片加载黑屏问题
iOS 解决LaunchScreen中图片加载黑屏问题 原文: http://blog.csdn.net/chengkaizone/article/details/50478045 iOS 解决Lau ...
- vue+webpack项目打包后背景图片加载不出来问题解决
在做VUE +的WebPack脚手架项目打包完成后,在IIS服务器上运行发现项目中的背景图片加载不出来检查项目代码发现是因为CSS文件中,背景图片引用的路径问题;后来通过修改配置文件,问题终于解决了, ...
- volley中图片加载
volley图片加载有三种方式: 记得:Volley中已经实现了磁盘缓存了,查看源码得知通过 context.getCacheDir()获取到了 /data/data/<application ...
- IOS中图片加载的一些注意点
图片的加载: [UIImage imageNamed:@"home"] //加载 png图片 在ios中获取一张图片只需要写图片名即可 不需要写后缀 默认都是加载.png的图片 但 ...
- 当h5页面图片加载失败后,给定一个默认图
本文主要讨论页面中图片加载失败后替换默认图片的几种方式 重点来了:一定要记住error事件不冒泡. 相关的知识点:jquery的ready方法.$("img").error().i ...
- vue中img图片加载中以及加载失败显示默认图片问题
加载中默认图片:主要是onload事件监听,data中定义变量 imgSrc :require('./default.png'): <div class="per-pic" ...
- vue中动态加载组件+开发者模式+JS参数值传递和引用传递
今天写vue里面通过接口反参动态加载组件时候 跟着同学...学习到了 一.先说说vue 内置组件 component 的用法 component组件可以来专门用来进行组件的切换,使用is来绑定你的组件 ...
- vue 首页背景图片加载完成前增加 loading 效果 -- 使用 new Image() 实现
1. 创建 loading 公用组件 <template> <div class="load-container"> <div class=" ...
随机推荐
- SkylineGlobe TerraExplorer Pro 遇到模型显示有锯齿怎么办?
SkylineGlobe TerraExplorer Pro 遇到模型显示有锯齿怎么办? 这个问题跟软件的版本无关,跟机器的显卡有关,看下面的截图: 试试看,祝你好运!
- linux驱动之中断处理过程C程序部分
当发生中断之后,linux系统在汇编阶段经过一系列跳转,最终跳转到asm_do_IRQ()函数,开始C程序阶段的处理.在汇编阶段,程序已经计算出发生中断的中断号irq,这个关键参数最终传递给asm_d ...
- Luogu P3165 [CQOI2014]排序机械臂
先讲一下和这题一起四倍经验的题: Luogu P4402 [Cerc2007]robotic sort 机械排序 SP2059 CERC07S - Robotic Sort UVA1402 Robot ...
- Feign性能优化注意事项
一.FeignClient注解 FeignClient注解被@Target(ElementType.TYPE)修饰,表示FeignClient注解的作用目标在接口上 @FeignClient(name ...
- 【C#复习总结】探究各类数据结构(Array、List、Queue、Stack)及线程安全问题和yeild关键字
前言 先普及一下线程安全和类型安全 线程安全: 如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码.如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的 ...
- 【C#复习总结】dynamic
介绍 C# 4 引入了一个新类型 dynamic. 该类型是一种静态类型,但类型为 dynamic 的对象会跳过静态类型检查. 大多数情况下,该对象就像具有类型 object 一样. 在编译时,将假定 ...
- Taro开发微信小程序的初体验
了解Taro 听说Taro是从几个星期前开始的,在一次饭桌上,一个小伙伴说:"Hey, 你听说了Taro么,听说只需要写一套程序就可以生成H5,小程序以及RN的代码模板,并且类似于React ...
- 二十二:制作app的时候超出部分不能滑动
给需要滑动的区域写以下样式(父级是浏览器) position: absolute; left: 0; right: 0; bottom: 0; top: 0; overflow-x: hidden; ...
- C#中委托,匿名函数,lamda表达式复习
一.委托 1.就给类比较,类用class声明,委托用delegate声明. 2.委托要指向一个真正的方法. 3.委托的签名,要和指向的方法一样. //1.声明一个委托 public delegate ...
- 设计模式——MVC MVP MVVM
了解到Vue是MVVM前端框架, 中午就研究了一下MVVM,但要从MVC开始说起: M(Model):模型,提供数据: V(View):视图,负责显示: C(Controller):控制器,负责逻辑处 ...