Maison  >  Article  >  interface Web  >  Comment obtenir différentes ressources et changer d'image selon le thème dans Vue

Comment obtenir différentes ressources et changer d'image selon le thème dans Vue

青灯夜游
青灯夜游avant
2021-12-02 19:12:011990parcourir

Comment obtenir différentes ressources et changer d'image selon le thème dans Vue ? L'article suivant vous présentera la méthode élégante de Vue pour implémenter les besoins de skinning multi-images. J'espère qu'il vous sera utile.

Comment obtenir différentes ressources et changer d'image selon le thème dans Vue

[Recommandation associée : "tutoriel vue.js"]

Récemment, un petit jeu Y de l'entreprise doit implémenter un thème localisé, c'est-à-dire que différentes régions doivent afficher différents thèmes, et le jeu a de nombreuses images, comment être élégant Charger l'image de peau correcte devient rapidement particulièrement important.

Il existe déjà de nombreuses solutions dans la communauté de changement de style CSS, vous pouvez vous y référer vous-même. L'article est déjà entré dans les détails, je n'entrerai donc pas dans les détails ici. Cet article parle principalement de la façon d'obtenir différentes ressources. pour changer d'image en fonction du thème.

Plan initial

Reskinning d'images, basé sur l'expérience passée, grâce à la gestion des dépendances de webpack, nous utilisons généralement require pour introduire des images. Par exemple, cette façon d'écrire (require(`@assets/img/${theme}/bg.png`)), webpack stockera tous les fichiers dans @assets/img code> Tous sont ajoutés au bundle, afin que les images correspondantes puissent être trouvées lors de l'exécution. L'implémentation spécifique est la suivante : <code>(require(`@assets/img/${theme}/bg.png`)),webpack会将@assets/img中的所有文件都加入到bundle中,从而在运行的时候可以找到对应的图片。具体实现如下:

<template>
  <!-- 这里需要判断图片是否存在,如果不存在需要指定为auto,不然会引起404,导致系统告警 -->
  <div class="y-content" :style="{backgroundImage: contentBg ? `url(${contentBg})` : &#39;auto&#39;}">
    <img class="y-content__reward" :src="rewardImg" />
  </div>
</template>

<script>
  data: () => ({
    theme: &#39;blcak&#39;
  }),
  computed: {
    contentBg() {
      try {
        // this.theme是文件夹,将不同的皮肤放到不同的文件夹,用同样的命名
        return require(`@assets/img/${this.theme}/contentBg.png`)
      } catch (err) {
        return &#39;&#39;;
      }
    },
    rewardImg() {
      try {
        return require(`@assets/img/${this.theme}/rewardImg.png`)
      } catch (err) {
        return &#39;&#39;;
      }
    }
  }
</script>

以上代码基本上能解决大部分的换肤需求,但是对于图片需要预先加载的项目,我们还需要区分不同主题的图片便于优化提前加载,由于编译后的图片链接跟编译前的链接是不同,因此我们获取编译后的图片链接。一般的项目中比如使用官方脚手架vue-cli构建的项目,所有的图片都会被url-loader处理后放到同一个文件夹image当中,这样编译前不同文件夹相同名字的图片编译后之后hash是不同,因此我们是无法区分不同主题的图片的。

于是,首先我们需要将不同的主题图片放置到不同的文件夹当中,同样适用用url-loader

// vue-cli配置
const imagesRule = config.module.rule(&#39;images&#39;);
imagesRule.uses.clear()        //清除原本的images loader配置
imagesRule
  .test(/white/.+.(jpg|gif|png|svg)$/)
  .use(&#39;url-loader&#39;)
    .loader(&#39;url-loader&#39;)
    .options({ name:"img/white/[name].[hash:8].[ext]", limit: 8192 })

// 加多一个主题的配置
config.module
  .rule(&#39;image2&#39;)
  .test(/black/.+.(jpg|gif|png|svg)$/)
  .use(&#39;url-loader&#39;)
    .loader(&#39;url-loader&#39;)
    .options({name:"img/black/[name].[hash:8].[ext]", limit: 8192 })
    
// 自定义webpack配置
rules: [
  {
    test: /white/.+.(png|svg|jpg|gif)$/,
    use: [
      {
      loader: &#39;url-loader&#39;,
        options: {
          limit: 8192,
          name: &#39;img/white/[name].[hash:8].[ext]&#39;,
        }
      }
    ],
  },
  {
    test: /black/.+.(png|svg|jpg|gif)$/,
    use: [
      {
      loader: &#39;url-loader&#39;,
        options: {
          limit: 8192,
          name: &#39;img/black/[name].[hash:8].[ext]&#39;,
        }
      }
    ],
  },
]

这样子编译后不同主题的图片就会被放置到不同的文件夹当中,这样就结束了吗?还没有,我们还需要获取编译后的图片链接,才能在进入游戏页面的时候提前加载主题图片,这里我们可以写一个webpack plugin来帮我们收集相应的图片,生产各自主题的json文件。插件代码如下:

// webpack版本为4.x
class WebPackSouceManifest {
  // 将 `apply` 定义为其原型方法,此方法以 compiler 作为参数
  constructor(option = {}) {
    // 黑色主题的文件名
    this.blackManifestName = option.blackManifestName || &#39;js/blackManifest.json&#39; 
    // 白色主题的文件名
    this.whiteManifestName = option.whiteManifestName || &#39;js/whiteManifest.json&#39;
    this.blackJsonData = {
      code: 0,
      data: []
    }
    this.whiteJsonData = {
      code: 0,
      data: []
    }
    this.addFileToSouceManifest.bind(this)
  }

  apply(compiler) {
    // 指定要附加到的事件钩子函数
    compiler.hooks.emit.tapAsync(
      &#39;HashServiceWorkerStartPlugin&#39;,
      (compilation, callback) => {
        const allBuildFiles = Object.keys(compilation.assets)
        allBuildFiles.forEach((file) => {
          if (file.indexOf(&#39;white&#39;) !== -1) {
            this.addFileToSouceManifest(&#39;white&#39;, file)
          } else {
            this.addFileToSouceManifest(&#39;black&#39;, file)
          }
        })


        const sourceBlack = JSON.stringify(this.blackJsonData)
        const sourceWhite = JSON.stringify(this.whiteJsonData)
        compilation.assets[this.blackManifestName] = {
          source: () => {
            return sourceBlack;
          },
          size: () => {
            return sourceBlack.length;
          }
        }

        compilation.assets[this.whiteManifestName] = {
          source: () => {
            return sourceWhite;
          },
          size: () => {
            return sourceWhite.length;
          }
        }
        callback()
      }
    );
  }

  addFileToSouceManifest(type, file) {
    let fileItem = {
      src: file,
    }
    if (/.js$/.test(file)) {
      fileItem.type = &#39;text&#39;
    } else if (/.js.map$/.test(file)) {
      fileItem.type = &#39;json&#39;
    }
    if (type === &#39;white&#39;) {
      this.whiteJsonData.data.push(fileItem)
    } else {
      this.blackJsonData.data.push(fileItem)
    }
  }
}

module.exports = WebPackSouceManifest;

因此我们得到不同主题的图片列表json,在进入页面的时候通过ajax获取到列表之后对别表中的图片进行加载,虽然以上的做法可以实现需求,但是实在太过复杂?那还有没有轻松的方式呢?当然是有的。

优化方案

仔细分析上面的代码后她,我们最终要获得的是图片编译后的结果,所以如果我们能够生成一个图片对象,将图片的name

<template>
  <!-- 这里需要判断图片是否存在,如果不存在需要指定为auto,不然会引起404,导致系统告警 -->
  <div class="y-content" :style="{backgroundImage: contentBg ? `url(${contentBg})` : &#39;auto&#39;}">
    <img class="y-content__reward" :src="rewardImg" />
  </div>
</template>

<script>
  data: () => ({
    theme: &#39;middleEast&#39;
  }),
  computed: {
    contentBg() {
      // skinImage是跟组件下的字段
      return this.$root.skinImage[&#39;contentBg&#39;] // contentBg为name
    },
    rewardImg() {
      return this.$root.skinImage[&#39;rewardImg&#39;]
    }
  }
</script>

Le code ci-dessus peut essentiellement résoudre la plupart des besoins de changement de skin, mais pour les projets qui nécessitent un pré-chargement d'images, nous devons également distinguer les images de différents thèmes pour faciliter l'optimisation et le chargement précoce. Depuis le lien de l'image compilée et la compilation Le lien précédent est différent, nous obtenons donc le lien de l'image compilée. Dans les projets généraux, tels que les projets construits à l'aide de l'échafaudage officiel vue-cli, toutes les images seront traitées par url-loader et placées dans le même dossier image, compilant ainsi Avant

images portant le même nom dans des dossiers différents

après compilation, le hash est différent, nous ne pouvons donc pas distinguer les images de thèmes différents.

Donc, nous devons d'abord placer différentes images de thème dans différents dossiers. La même chose s'applique à l'utilisation de url-loader

const black = require.context(&#39;../black&#39;, true, /.(png|jpg|gif)$/);
const middleImageObj = {};
black.keys().forEach(path => {
  // 获取图片的key
  const key = path.slice(2, -4); 
  blackImageObj[key] = rawSkin(path);
});

De cette façon, après la compilation, les images de différents thèmes seront placées dans différents dossiers, de sorte que c'est tout. sur? Pas encore, nous avons encore besoin d'obtenir le lien de l'image compilée pour charger l'image du thème à l'avance lors de l'accès à la page du jeu. Ici, nous pouvons écrire un plugin webpack pour nous aider à collecter les images correspondantes et à produire des fichiers json pour chaque thème. Le code du plug-in est le suivant :
const black = require.context(&#39;../black&#39;, true, /.(png|jpg|gif)$/);
const middleImageObj = {};
black.keys().forEach(path => {
  // 获取图片的key
  const key = path.slice(2, -4); 
  blackImageObj[key] = rawSkin(path);
});

Nous obtenons donc la liste d'images json des différents thèmes. En entrant dans la page, nous obtenons la liste via ajax puis chargeons les images dans les autres tableaux, bien que l'approche ci-dessus puisse se rencontrer. les besoins, c'est trop compliqué ? Existe-t-il un moyen simple ? Bien sûr, il y en a.

Plan d'optimisation

Après avoir soigneusement analysé le code ci-dessus, ce que nous voulons finalement obtenir est le résultat compilé de l'image, donc si nous pouvons générer un objet image, le picture Le nom est utilisé comme clé, et le résultat compilé de l'image est utilisé comme valeur. Ensuite, le code ci-dessus peut être simplifié comme suit :

rrreee

De cette façon, le code devient concis. , et il n'est pas nécessaire d'utiliser require et d'essayer catch tout au long de l'article. , alors comment implémenter cet objet skinImage

La réponse est d'utiliser require.context

Obtenez un contexte spécifique en exécutant la fonction require.context, qui est principalement utilisé pour implémenter des modules d'importation automatique. Dans les projets frontaux, si lors de l'importation de nombreux modules à partir d'un dossier, vous pouvez utiliser cette API pour parcourir les fichiers spécifiés dans le dossier, puis les importer automatiquement, afin que vous ne le fassiez pas. Vous devez appeler explicitement le module d'importation à chaque fois. L'utilisation spécifique ne sera pas décrite ici

Veuillez consulter le document officiel requirecontext pour plus de détails🎜🎜https://webpack.docschina.org/guides/dependency-management/#requirecontext. 🎜🎜🎜Écrivons donc une fonction qui importe automatiquement des images et génère des objets skinImage🎜rrreee🎜De cette façon, nous obtenons ensuite l'objet image du thème noir Puisque require.context est exécuté pendant le processus de compilation plutôt que pendant l'exécution, tous les paramètres ne peuvent être que statiques. . Ici, nous devons également obtenir l'image du thème blanc à l'avance, comme suit 🎜rrreee🎜De cette façon, nous obtenons les objets image des deux thèmes. Ensuite, il nous suffit d'attribuer un certain objet au skinImage du composant racine. , et nous avons terminé. Est-ce plus simple et plus concis que ce qui précède ? 🎜🎜Pour plus de connaissances sur la programmation, veuillez visiter : 🎜Introduction à la programmation🎜 ! ! 🎜

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer