解决vue的 v-for 循环中图片加载路径问题


Posted in Javascript onSeptember 03, 2018

先看一下产品需求,如下图所示,

解决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() {}
 }
};

整个页面显示如下,我以为没有问题了。

解决vue的 v-for 循环中图片加载路径问题

现在再来写后台代码, 用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;
  }
 })
 }
 }
};

我以为成功了,点击按钮发送请求,但是看到的如下画面,没有图片

解决vue的 v-for 循环中图片加载路径问题

当时想不通,img 的src 绑定的是变量,它和defaultImg 不应该是一样吗?打开浏览器控制台,看到如下内容,img 的src 已经是一个字符串,它不是我们想要的变量了。

我想这里可能是它对item.EnName进行了一次解析变成了字符串,就完事了,绑定变量,就是解析一次。而对于defalutImg 来说,它本来就是变量,无法再进行分割解析,所以它会去data 里面去找,如果找不到,才报错。

解决vue的 v-for 循环中图片加载路径问题

那么我们现在要做的就是把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);

刷新浏览器,在控制台上可以看到如下输出

解决vue的 v-for 循环中图片加载路径问题

正好是图片的路径,也正是我们想要的内容,刚才也说了,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 引入图片,获得图片路径
   }
  })
  }
 })
 }

这时刷新浏览器,点击按钮发送请求,可以看到图片了并且一一对应, 成功了。

解决vue的 v-for 循环中图片加载路径问题

这时又一想,既然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 循环中图片加载路径问题就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
document.all与WEB标准
May 13 Javascript
jQuery温习篇 强大的JQuery选择器
Apr 24 Javascript
Jquery AJAX 用于计算点击率(统计)
Jun 30 Javascript
JS中for循序中延迟加载动态效果的具体实现
Aug 18 Javascript
jquery xMarquee实现文字水平无缝滚动效果
Apr 29 Javascript
简介JavaScript中的push()方法的使用
Jun 09 Javascript
jquery+ajax实现省市区三级联动效果简单示例
Jan 04 Javascript
Javascript 链式作用域详细介绍
Feb 23 Javascript
使用jQuery动态设置单选框的选中效果
Dec 06 jQuery
vue v-for循环重复数据无法添加问题解决方法【加track-by='索引'】
Mar 15 Javascript
Vue.js标签页组件使用方法详解
Oct 19 Javascript
JavaScript实现点击图片换背景
Nov 20 Javascript
Vue实现底部侧边工具栏的实例代码
Sep 03 #Javascript
Angular动态绑定样式及改变UI框架样式的方法小结
Sep 03 #Javascript
node.js使用免费的阿里云ip查询获取ip所在地【推荐】
Sep 03 #Javascript
react在安卓中输入框被手机键盘遮挡问题的解决方法
Sep 03 #Javascript
Vue 中对图片地址进行拼接的方法
Sep 03 #Javascript
VUE预渲染及遇到的坑
Sep 03 #Javascript
详解vue通过NGINX部署在子目录或者二级目录实践
Sep 03 #Javascript
You might like
SONY ICF-SW07收音机电路分析
2021/03/02 无线电
PHP 编写的 25个游戏脚本
2009/05/11 PHP
深入HTTP响应状态码速查表的详解
2013/06/07 PHP
jquery 可排列的表实现代码
2009/11/13 Javascript
基于JQuery的一句话搞定手风琴菜单
2012/09/14 Javascript
子窗体与父窗体传值示例js代码
2013/08/01 Javascript
动态加载脚本提升javascript性能
2014/02/24 Javascript
JS的encodeURI和java的URLDecoder.decode使用介绍
2014/05/08 Javascript
javascript根据时间生成m位随机数最大13位
2014/10/30 Javascript
javascript使用正则表达式实现去掉空格之后的字符
2015/02/15 Javascript
浅谈javascript事件取消和阻止冒泡
2015/05/26 Javascript
理解Javascript的动态语言特性
2015/06/17 Javascript
AngularJs中route的使用方法和配置
2016/02/04 Javascript
JavaScript知识点总结(十一)之js中的Object类详解
2016/05/31 Javascript
jQuery EasyUI之验证框validatebox实例详解
2017/04/10 jQuery
Angularjs的启动过程分析
2017/07/18 Javascript
微信小程序实现鼠标拖动效果示例
2017/12/01 Javascript
简单的vuex 的使用案例笔记
2018/04/13 Javascript
layui获取选中行数据的实例讲解
2018/08/19 Javascript
vue配置接口域名方法总结
2019/05/12 Javascript
js滚轮事件 js自定义滚动条的实现
2020/01/18 Javascript
python发送邮件示例(支持中文邮件标题)
2014/02/16 Python
Python的内存泄漏及gc模块的使用分析
2014/07/16 Python
Python while 循环使用的简单实例
2016/06/08 Python
使用python实现http及ftp服务进行数据传输的方法
2018/10/26 Python
详解python中的线程与线程池
2019/05/10 Python
Python协程操作之gevent(yield阻塞,greenlet),协程实现多任务(有规律的交替协作执行)用法详解
2019/10/14 Python
python提取xml里面的链接源码详解
2019/10/15 Python
浅谈three.js中的needsUpdate的应用
2012/11/12 HTML / CSS
html5通过postMessage进行跨域通信的方法
2017/12/04 HTML / CSS
天网面试题
2013/04/07 面试题
总经理职责范文
2013/11/08 职场文书
人力资源部经理助理岗位职责
2014/03/04 职场文书
毕业证委托书范文
2014/09/26 职场文书
监察建议书
2015/02/04 职场文书
中国合伙人观后感
2015/06/02 职场文书