首先,我们先来重现一下问题,如果直接通过路径的形式引入一个图片,例如:

<template>
  <div id="app">
    <img src="./assets/demo.jpg">
    <!--<img :src="demo">-->
    <HelloWorld/>
  </div>
</template>
假设在src的asstes目录下有一个叫demo的图片(且假设这个图片比较大,不会被base64压缩),在这种情况下,图片是可以正常显示的。但是有些时候,我们需要以js变量的形式引入一个图片的路径,此时,问题就来了。
<template>
  <div id="app">
    <img src="./assets/demo.jpg">
    {{demo}}
    <img :src="demo" alt="暂时无法显示图片">
    <HelloWorld/>
  </div>
</template>

<script>
  export default {
    name: 'App',
    data: () => ({
      src: './assets/demo.jpg'
    })
  }
</script>

程序运行的效果如下图所示:


可以看到,明明路径是一样的,可是就是显示不出图片,我通过Segmentfault查阅资料,得知,此时经过JS变量引入的图片是没有经过webpack打包压缩的,我们通过npm run build来证明我们的结论。


假如我们把代码还原成以<img  src="./assets/demo.jpg" />的形式,先rm -rf dist删除打包出来的目录,然后重新打包,

结果为:


因此,证明了文件没有经过webpack打包。

解决方法很简单:

<template>
  <div id="app">
    {{src}}
    <img :src="src" alt="暂时无法显示图片">
    <HelloWorld/>
  </div>
</template>

<script>
  const src = require('./assets/demo.jpg');
  export default {
    name: 'App',
    data: () => ({
      src
    })
  }
</script>

这就是所谓的CommonJS风格,还有一种解决方案,使用ES6的import函数,同样可以解决这个问题。

<template>
  <div id="app">
    {{src}}
    <img :src="src" alt="暂时无法显示图片">
  </div>
</template>

<script>
  let srcLoad = () => import('./assets/demo.jpg');
  export default {
    name: 'App',
    data: () => ({
      src: ''
    }),
    created () {
      console.log(srcLoad)
//      ƒ srcLoad() {
//        return __webpack_require__.e/* import() */(1).then(__webpack_require__.bind(null, "./src/assets/demo.jpg"));
//      }
      srcLoad().then( i => {
        this.src = i
      })
    }
  }
</script>

ES6的Import不仅可以进行模块的导入导出,还可以引入一个资源,该函数返回的是一个Promise对象,在then方法中可以获得资源的路径。另外一个就是import只能引入静态资源,不能进行JS字符串的拼接。我们基于require的语法继续扩展一下,大家可以尝试配置一个json-loader,把所以需要JS变量引入的图片路径全部配置到里面去,然后通过require()动态的获取。

补充:webpack采用的是CommonJS语法,从这个console打印的内容确实可以看出。


Logo

前往低代码交流专区

更多推荐