ホームページ  >  記事  >  ウェブフロントエンド  >  Vueでさまざまなリソースを取得し、テーマに応じて画像を切り替える方法

Vueでさまざまなリソースを取得し、テーマに応じて画像を切り替える方法

青灯夜游
青灯夜游転載
2021-12-02 19:12:012032ブラウズ

Vue でテーマに応じてさまざまなリソースを取得し、画像を切り替えるにはどうすればよいですか?次の記事では、マルチイメージ スキニングのニーズを実現する Vue のエレガントな方法を紹介します。

Vueでさまざまなリソースを取得し、テーマに応じて画像を切り替える方法

[関連する推奨事項: 「vue.js チュートリアル 」]

最近、会社の Y が実装する必要がある小さなゲームローカライズされたテーマ、つまり、異なる地域では異なるテーマを表示する必要があり、ゲーム内には多くの画像が存在するため、適切なスキン画像をエレガントかつ迅速にロードする方法が特に重要になります。

CSS スタイル切り替えコミュニティにはすでに多くの解決策が存在しており、各自で参照することができます。すでに記事で詳しく説明されているため、ここでは詳しく説明しません。この記事では主にテーマに応じて画像を切り替えるためのリソースの取得方法について説明します。

初期計画

画像のリスキニングは、過去の経験に基づいて、webpack の依存関係管理のおかげで、通常、画像の導入に require を使用します。たとえば、このように (require(`@assets/img/${theme}/bg.png`)) と記述すると、webpack は @assets/img## にすべてのファイルを追加します。 # 実行時に対応するイメージを見つけられるようにバンドルに追加します。具体的な実装は次のとおりです:

<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 に配置されるため、コンパイル前に異なるフォルダーにある同じ名前の画像 コンパイル後の ハッシュ が異なるため、異なるテーマの画像を区別できません。

したがって、まず、異なるテーマの画像を異なるフォルダーに配置する必要があります。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;,
        }
      }
    ],
  },
]

このようにして、コンパイル後、異なるテーマの画像が配置されます。別のフォルダで、これで終わりですか?まだですが、ゲーム ページに入るときに事前にテーマ イメージをロードするためにコンパイルされたイメージ リンクを取得する必要があります。ここで、対応するイメージを収集し、各テーマの json ファイルを生成するのに役立つ Webpack プラグインを作成できます。プラグイン コードは次のとおりです:

// 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>

Inこのようにすると、コードが簡潔になり、記事全体で説明する必要がなくなります。require と try catch、次はこのskinImage オブジェクトをどのように実装しますか?

答えは、webpack の require.context

を使用することです。

require.context 関数を実行して特定のコンテキストを取得する 主に使用されるモジュールの自動インポートの実装 フロントエンド プロジェクトで、フォルダーから多数のモジュールをインポートする状況が発生した場合、この API を使用できます。フォルダー内の指定されたファイルを走査し、自動的にインポートするため、毎回明示的にインポートする必要がなくなります。インポート インポート モジュールを呼び出します。具体的な使用方法はここでは説明しません。

お願いします。詳細については、公式ドキュメント requirecontext

https://webpack.docschina.org/guides/dependency-management/# を確認してください。そして、skinImage オブジェクトを生成します

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);
});

このようにして、require.context の実行はランタイムではなくコンパイル プロセスで行われるため、すべてのパラメーターは静的であることしかできないため、黒のテーマ画像オブジェクトを取得します。白いテーマの画像を事前に取得するには、次のようにします。
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);
});

この方法で 2 つのテーマの画像オブジェクトを取得し、ルート コンポーネントの SkinImage に特定のオブジェクトを割り当てるだけで完了です。上記よりもシンプルで簡潔ですか?

プログラミング関連の知識について詳しくは、

プログラミング入門

をご覧ください。 !

以上がVueでさまざまなリソースを取得し、テーマに応じて画像を切り替える方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はjuejin.cnで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。