组件库开发系列 - 记一次图片组件封装 vc-image

130 阅读1分钟

问题

阿里oss上图片带有时间戳,1分钟后图片就失效,前端切换页面通过浏览器缓存也能显示正常,但是无痕模式下就失败了,只有重新请求接口获得新图片

思考

想着前端请求同一个图片,显示还是直接用,并同时做图片缓存blob格式,下次用blob缓存内容来显示

组件 vc-image

vc-image , 封装的vue组件,已发布到 npmjs

安装

npm i @jser6/vc-image

使用

import vcImage from '@jser6/vc-image'

<vc-image src="https://www.baidu.com/img/flexible/logo/pc/peak-result.png" />

原理

缓存 blob 数据

const cacheBlobMap = new Map();

const vueCacheImage = {
  props: {
    src: {
      type: String,
    },
  },
  computed: {
    realSrc() {
      return cacheBlobMap.get(this.src) || this.src;
    },
    attrs() {
      const attrs = this.$attrs;
      delete attrs.src;
      return attrs;
    },
  },
  watch: {
    src: {
      handler(s) {
        if (cacheBlobMap.get(s)) return;
        if (/^(http|https|\/\/):/i.test(s)) {
          const xhr = new XMLHttpRequest();
          xhr.open("GET", s, true);
          xhr.responseType = "blob";
          xhr.onload = function () {
            const file = new Blob([xhr.response]);
            const blob = window.URL.createObjectURL(file);
            cacheBlobMap.set(s, blob);
          };
          xhr.send();
        }
      },
      immediate: true,
    },
  },
  render() {
    return <img src={this.realSrc} {...this.attrs} />;
  },
};

vueCacheImage.install = function (Vue) {
  Vue.component("vc-image", vueCacheImage);
};

export default vueCacheImage;

rollup打包 umd 和 esm

import babel from "rollup-plugin-babel";
import commonjs from "rollup-plugin-commonjs";
import vue from "rollup-plugin-vue";
import { terser } from "rollup-plugin-terser";
import del from "rollup-plugin-delete";

export default [
  {
    input: "./index.js",
    output: [
      {
        file: "./lib/index.umd.js",
        format: "umd",
        name: "vc-image",
      },
      {
        file: "./lib/index.es.js",
        format: "es",
      },
    ],
    plugins: [
      del({ targets: ["lib/*"] }),
      vue(),
      babel({
        exclude: "node_modules/**",
        runtimeHelpers: true,
      }),
      commonjs(),
      terser(),
    ],
  },
];

package.json

{
  "name": "@jser6/vc-image",
  "version": "1.0.5",
  "description": "",
  "main": "lib/index.umd.js",
  "module": "lib/index.es.js",
  "scripts": {
    "build": "rollup -c"
  },
  "homepage": "https://github.com/rootjser/vc-image",
  "keywords": [
    "vue",
    "cache",
    "image",
    "vc-image"
  ],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@babel/core": "^7.18.10",
    "@babel/preset-env": "^7.18.10",
    "@vue/babel-preset-app": "^5.0.8",
    "rollup": "^2.78.0",
    "rollup-plugin-babel": "^4.4.0",
    "rollup-plugin-commonjs": "^10.1.0",
    "rollup-plugin-delete": "^2.0.0",
    "rollup-plugin-terser": "^7.0.2",
    "rollup-plugin-vue": "^5.1.9",
    "vue-template-compiler": "^2.7.8"
  }
}

.babelrc

{
  "presets": [["@vue/babel-preset-app"]]
}