解决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 相关文章推荐
运行Node.js的IIS扩展iisnode安装配置笔记
Mar 02 Javascript
js实现同一页面多个运动效果的方法
Apr 10 Javascript
Vuejs第十三篇之组件——杂项
Sep 09 Javascript
JS简单封装的图片无缝滚动效果示例【测试可用】
Mar 22 Javascript
基于Bootstrap实现城市三级联动
Nov 23 Javascript
React Native 使用Fetch发送网络请求的示例代码
Dec 02 Javascript
Vue-router的使用和出现空白页,路由对象属性详解
Sep 03 Javascript
详解如何用VUE写一个多用模态框组件模版
Sep 27 Javascript
微信小程序功能之全屏滚动效果的实现代码
Nov 22 Javascript
JavaScript怎样在删除前添加确认弹出框?
May 27 Javascript
解决Element中el-date-picker组件不回填的情况
Nov 07 Javascript
Vue + iView实现Excel上传功能的完整代码
Jun 22 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
PHPUnit PHP测试框架安装方法
2011/03/23 PHP
Thinkphp中Create方法深入探究
2014/06/16 PHP
smarty内部日期函数html_select_date()用法实例分析
2015/07/08 PHP
PHP 微信扫码支付源代码(推荐)
2016/11/03 PHP
PHP内部实现打乱字符串顺序函数str_shuffle的方法
2019/02/14 PHP
jquery.validate使用攻略 第二部
2010/07/01 Javascript
禁用JavaScript控制台调试的方法
2014/03/07 Javascript
jQuery实现多按钮单击变色
2014/11/27 Javascript
创建js对象和js类的方法汇总
2014/12/24 Javascript
Javascript中实现trim()函数的两种方法
2015/02/04 Javascript
JavaScript实现九九乘法表的简单实例
2016/06/07 Javascript
JS中的hasOwnProperty()、propertyIsEnumerable()和isPrototypeOf()
2016/08/11 Javascript
jQuery模拟Marquee实现无缝滚动效果完整实例
2016/09/29 Javascript
javascript对浅拷贝和深拷贝的详解
2016/10/14 Javascript
jquery.guide.js新版上线操作向导镂空提示jQuery插件(推荐)
2017/05/20 jQuery
浅析JS中常用类型转换及运算符表达式
2017/07/23 Javascript
vue页面加载闪烁问题的解决方法
2018/03/28 Javascript
karma+webpack搭建vue单元测试环境的方法示例
2018/05/24 Javascript
vue单页应用在页面刷新时保留状态数据的方法
2018/09/21 Javascript
bootstrap-treeview实现多级树形菜单 后台JSON格式如何组织?
2019/07/26 Javascript
JS数组Reduce方法功能与用法实例详解
2020/04/29 Javascript
[00:15]TI9观赛名额抽取
2019/07/10 DOTA
Python中让MySQL查询结果返回字典类型的方法
2014/08/22 Python
Python XML RPC服务器端和客户端实例
2014/11/22 Python
进一步理解Python中的函数编程
2015/04/13 Python
Python作用域用法实例详解
2016/03/15 Python
Python教程之全局变量用法
2016/06/27 Python
python 中文件输入输出及os模块对文件系统的操作方法
2018/08/27 Python
Python面向对象基础入门之编码细节与注意事项
2018/12/11 Python
Python基于datetime或time模块分别获取当前时间戳的方法实例
2019/02/19 Python
python导入不同目录下的自定义模块过程解析
2019/11/18 Python
html5嵌入内容_动力节点Java学院整理
2017/07/07 HTML / CSS
大学生村官典型材料
2014/01/12 职场文书
《逃家小兔》教学反思
2014/02/23 职场文书
个人催款函范文
2015/06/24 职场文书
2019入党申请书格式
2019/06/25 职场文书