解决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 相关文章推荐
在textarea中屏蔽js的某个function的javascript代码
Apr 20 Javascript
用js实现输入提示(自动完成)的实例代码
Jun 14 Javascript
触屏中的JavaScript事件分析
Feb 06 Javascript
jQuery插件StickUp实现网页导航置顶
Apr 12 Javascript
详解JavaScript中的blink()方法的使用
Jun 08 Javascript
利用Javascript仿Excel的数据透视分析功能
Sep 07 Javascript
Node.js中常规的文件操作总结
Oct 13 Javascript
微信小程序-详解数据缓存
Nov 24 Javascript
微信小程序之picker日期和时间选择器
Feb 09 Javascript
三分钟教你用Node做一个微信哄女友(基友)神器(面向小白)
Jun 21 Javascript
详解Vue3 Composition API中的提取和重用逻辑
Apr 29 Javascript
Vue+TypeScript中处理computed方式
Apr 02 Vue.js
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
浅谈php自定义错误日志
2015/02/13 PHP
PHP匿名函数(闭包函数)详解
2019/03/22 PHP
PHP cookie与session会话基本用法实例分析
2019/11/18 PHP
在Ajax中使用Flash实现跨域数据读取的实现方法
2010/12/02 Javascript
js hover 定时器(实例代码)
2013/11/12 Javascript
JavaScript实现的图像模糊算法代码分享
2014/04/22 Javascript
jQuery切换网页皮肤并保存到Cookie示例代码
2014/06/16 Javascript
IE浏览器不支持getElementsByClassName的解决方法
2014/08/27 Javascript
javascript 实现 原路返回
2015/01/21 Javascript
JS+CSS实现的经典圆角下拉菜单效果代码
2015/10/21 Javascript
JavaScript用二分法查找数据的实例代码
2017/06/17 Javascript
浅谈webpack打包过程中因为图片的路径导致的问题
2018/02/21 Javascript
基于vue实现移动端圆形旋钮插件效果
2018/11/28 Javascript
JS实现的A*寻路算法详解
2018/12/14 Javascript
实现一个 Vue 吸顶锚点组件方法
2019/07/10 Javascript
layUI实现列表查询功能
2019/07/27 Javascript
uploadify插件实现多个图片上传并预览
2019/09/30 Javascript
Javascript 关于基本类型和引用类型的个人理解
2019/11/01 Javascript
javascript 原型与原型链的理解及应用实例分析
2020/02/10 Javascript
基于javascript实现碰撞检测
2020/03/12 Javascript
关于AngularJS中几种Providers的区别总结
2020/05/17 Javascript
vue 清空input标签 中file的值操作
2020/07/21 Javascript
Python将xml和xsl转换为html的方法
2015/03/10 Python
解决Python 爬虫URL中存在中文或特殊符号无法请求的问题
2018/05/11 Python
Python 函数返回值的示例代码
2019/03/11 Python
pandas 像SQL一样使用WHERE IN查询条件说明
2020/06/05 Python
世界第一冲浪品牌:O’Neill
2016/08/30 全球购物
美国购买体育、音乐会和剧院门票网站:SelectATicket
2019/09/08 全球购物
纺织工程专业个人求职信范文
2014/01/27 职场文书
违反工作纪律检讨书
2014/02/15 职场文书
小学毕业感言300字
2014/02/19 职场文书
财务会计专业自荐书
2014/06/30 职场文书
班主任与学生安全责任书
2014/07/25 职场文书
运动会800米赞词
2015/07/22 职场文书
Python爬虫框架之Scrapy中Spider的用法
2021/06/28 Python
Ajax实现三级联动效果
2021/10/05 Javascript