Vue.js实现动态添加图片的几种方法详解与实践教程

一、问题的根源

    静态引入与动态引入的区别

    • 静态引入:直接在<img>标签的src属性中写入图片路径,这种方式在编译时会被webpack或vite处理,图片路径会被正确解析。
    • 动态引入:通过变量动态绑定src属性,这种方式在编译时无法被webpack或vite处理,导致图片路径无法正确解析。

    编译机制的影响

    • 在webpack或vite中,图片资源被打包后放在特定的文件夹下(如img文件夹),未编译的图片路径无法访问。

二、解决方案

针对上述问题,以下是几种常见的解决方案:

1. 使用require引入图片(Vue2)
<template>
  <img :src="imageSrc" alt="Dynamic Image">
</template>

<script>
export default {
  data() {
    return {
      imageSrc: require('../assets/img/1-2.png')
    };
  }
};
</script>
2. 使用new URL引入图片(Vue3)

在Vue3中,由于是通过vite进行打包编译,不能使用require,而是采用new URL替代。

<template>
  <img :src="imageSrc" alt="Dynamic Image">
</template>

<script>
export default {
  data() {
    return {
      imageSrc: new URL('../assets/img/1-2.png', import.meta.url).href
    };
  }
};
</script>
3. 使用import引入图片
<template>
  <img :src="imageSrc" alt="Dynamic Image">
</template>

<script>
import image from '../assets/img/1-2.png';

export default {
  data() {
    return {
      imageSrc: image
    };
  }
};
</script>
4. 使用public文件夹
<template>
  <img src="/img/1-2.png" alt="Dynamic Image">
</template>

三、动态绑定背景图片

方法一:使用模板语法
<template>
  <div :style="{ backgroundImage: 'url(' + imageUrl + ')' }"></div>
</template>

<script>
export default {
  data() {
    return {
      imageUrl: 'path/to/image.jpg'
    };
  }
};
</script>
方法二:使用三目运算符
<template>
  <div :style="{ backgroundImage: imageUrl ? 'url(' + imageUrl + ')' : 'none' }"></div>
</template>

<script>
export default {
  data() {
    return {
      imageUrl: 'path/to/image.jpg'
    };
  }
};
</script>
方法三:在v-for循环中添加背景图片
<template>
  <div v-for="item in items" :key="item.id" :style="{ backgroundImage: 'url(' + item.imageUrl + ')' }"></div>
</template>

<script>
export default {
  data() {
    return {
      items: [
        { id: 1, imageUrl: 'path/to/image1.jpg' },
        { id: 2, imageUrl: 'path/to/image2.jpg' }
      ]
    };
  }
};
</script>

四、瀑布流布局的实现

1. HTML和CSS结构
<div class="waterfall">
  <div class="column" ref="column1"></div>
  <div class="column" ref="column2"></div>
</div>
.waterfall {
  display: flex;
  justify-content: space-between;
}

.column {
  width: 49%;
}
2. JavaScript逻辑
<template>
  <div class="waterfall">
    <div class="column" ref="column1"></div>
    <div class="column" ref="column2"></div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      images: ['path/to/image1.jpg', 'path/to/image2.jpg', 'path/to/image3.jpg']
    };
  },
  mounted() {
    this.loadImages();
  },
  methods: {
    loadImages() {
      this.images.forEach(image => {
        const img = new Image();
        img.src = image;
        img.onload = () => {
          const column1Height = this.$refs.column1.clientHeight;
          const column2Height = this.$refs.column2.clientHeight;
          if (column1Height <= column2Height) {
            this.$refs.column1.appendChild(img);
          } else {
            this.$refs.column2.appendChild(img);
          }
        };
      });
    }
  }
};
</script>

五、总结