Vue3 + Vite dynamically introduces images

When developing vue3 + vite project, I wanted to dynamically introduce images to display, tried require and found an error require is not defind

The official instructions

import imgUrl from './img.png'
document.getElementById('hero-img').src = imgUrl
Copy the code

File-loader behaves like Webpack. The difference is that imports can use either an absolute public path (based on the project root path during development) or a relative path.

So the question is how do I dynamically get the group of images I want?

Look at the import() method

Webpack implements the import() method for dynamic loading according to the ES2015loader specification.

This feature allows us to load our code on demand and retrieve loaded packages using promise style callbacks.

So start having fun

Scenario: An object stores the address information of each image I want to load dynamically, so:

const imgUrl = reactive<object[]>([])
const getImage = () = > {
  mapElements.map((item) = > {
    const obj: { img: string, select: string} = {
      img: ' '.select: ' '
    }
    import(item.path).then((res) = > {
      obj.img = res.default
    })
    imgUrl.push(obj)
  })
}
Copy the code

Sure enough, it hung up, and the browser said, no, nothing, no fish balls, no noodles.

The browser will report that the path 404item.path is invalid

/image/${item.path}

This time the compiler is reporting an error expecting a string which means it can’t do that either

Start checking the documentation

Webpack needs to package all import() modules separately, so during the engineering packaging phase, WebPack does dependency collection.

At this point, Webpack finds all calls to import(), processes the passed arguments into a re in which all variables are replaced by.*, and then looks for any matching packages and packages them as package. So it’s really going to bring all the big bags in.

Solution: Statically express the address of the package, minimize the variable control area.

const imgUrl = reactive<object[]>([])
const getImage = () = > {
  mapElements.map((item) = > {
    const obj: { img: string, select: string} = {
      img: ' '.select: ' '
    }
    import('./image' + item.path).then((res) = > {
      obj.img = res.default
    })
    imgUrl.push(obj)
  })
}
Copy the code

You can use import(‘./image’ + item.path) to avoid other distractions