VUE中静态文件引入问题

3,664 阅读3分钟

前言

在VUE的使用过程中肯定会遇到引用静态文件的需求的,一般的情况都是直接在imgvideoaudio标签的src属性中直接使用文件的相对地址或者绝对地址就可以了。但是往往业务中有在js中动态引用静态文件的情况,如果我们仍然直接使用相对地址就会导致静态文件应用失败,就像下面的例子一样会导致图片不显示。

<template>
  <div id="box"></div>
</template>
<script>
export default {
  mounted(){
    const divElment = document.getElementById('box');
    const imgElment = document.createElement('img');
    imgElment.src = '../assets/logo.png';
    divElment.appendChild(imgElment);
  }
}
</script>

解决方法

向上面这种情况在开发中经常遇到,在VUE项目中只要通过js动态引用静态文件就会出现找不到文件的问题。

本质上来说这不是bug,而是打包机制决定的,所以有现成的解决方法。只要通过require()进行引入就可以了。

<template>
  <div id="box"></div>
</template>
<script>
export default {
  mounted(){
    const divElment = document.getElementById('box');
    const imgElment = document.createElement('img');
    imgElment.src = requrie('../assets/logo.png'); // 只需要通过require引入文件路径就可以了
    divElment.appendChild(imgElment);
  }
}
</script>

上面这种方式是大家常用的一种解决静态文件引用的方法,但是其实还有另一种方法也可以解决只是不被大家常用。

<template>
  <div id="box"></div>
</template>
<script>
import src from '../assets/logo.png'  // 可以通过import将静态文件引入
export default {
  mounted(){
    const divElment = document.getElementById('box');
    const imgElment = document.createElement('img');
    imgElment.src = src; 
    divElment.appendChild(imgElment);
  }
}
</script>

疑问

虽然静态文件的动态引用解决了,但是留下了一些问题。

1、 require()import分别是CommonJSES6针对js模块引用的方法(“理解import、export、module.exports、require等”),为什么可以用来引用静态资源文件。

2、 了解VUE模板渲染原理应该知道我们在<template>中写的html标签其实最终都会被js动态生成为真实的html标签,而我们写在标签中的src等属性也不过是VUE模板对象中的一个属性,为何在<template>中直接写<img src="../assets/logo.png">就可以找到静态资源文件而在js中就必须要使用require()或者import引入。

VUE模板编译与file-loader

<template>中的内容会被VUE编译成为模板对象,我们写的所有标签最终也都会变成一个个的模板对象和属性,例如下面的代码片段:

<img src="../assert/logo.png">

// 上面的标签会被编译成下面这种形式
createElement('img', {
  attrs: {
    src: require('../assert/logo.png')
  }
})

具体VUE是如何进行编译的?跟这里要说的东西不相关,单独百度就行了。通过上面的例子可以看到哪怕是用标签的方式引入静态资源文件本质上也是通过require()来引入的。

VUE项目一般会通过打包将很多vue文件打包成一个或多个js文件,最终执行引入文件的代码跟静态资源文件的相对地址已经发生了变化,所以我们在vue文件中使用相对路径找不到对应的静态资源文件。

VUE脚手架中引入了file-loader就是来用来解决这个问题的,file-loader会将文件中require()import引入的文件地址做解析并加入hash进行映射,最终我们在浏览器中可以看到img标签的src属性值并不是我们填写的相对地址,而是由file-loader映射后的地址。

在使用中注意,import()方法引入的资源文件路径是不能被解析的哦,file-loader解析的是import而不是import()