Heim  >  Artikel  >  Web-Frontend  >  So erhalten Sie verschiedene Ressourcen und wechseln Bilder je nach Thema in Vue

So erhalten Sie verschiedene Ressourcen und wechseln Bilder je nach Thema in Vue

青灯夜游
青灯夜游nach vorne
2021-12-02 19:12:011990Durchsuche

Wie erhält man in Vue unterschiedliche Ressourcen und tauscht Bilder je nach Thema aus? Der folgende Artikel stellt Ihnen Vues elegante Methode zur Realisierung von Multi-Image-Skins-Anforderungen vor. Ich hoffe, dass er Ihnen hilfreich sein wird.

So erhalten Sie verschiedene Ressourcen und wechseln Bilder je nach Thema in Vue

[Verwandte Empfehlung: „vue.js Tutorial“]

Kürzlich muss ein kleines Spiel Y des Unternehmens ein lokalisiertes Thema implementieren, das heißt, verschiedene Regionen müssen unterschiedliche Themen und das Spiel anzeigen hat viele Bilder, wie man elegant aussieht. Das schnelle Laden des richtigen Hautbildes wird besonders wichtig.

In der CSS-Style-Switching-Community gibt es bereits viele Lösungen. Der Artikel wurde bereits ausführlich beschrieben, daher werde ich hier nicht näher darauf eingehen, wie man verschiedene Ressourcen erhält um Bilder je nach Thema zu wechseln.

Erster Plan

Bild-Reskinning, basierend auf früheren Erfahrungen, dank der Abhängigkeitsverwaltung von Webpack verwenden wir normalerweise „require“, um Bilder einzuführen. Wenn Sie beispielsweise (require(`@assets/img/${theme}/bg.png`)) schreiben, speichert Webpack alle Dateien in @assets/img code> Alle werden dem Bundle hinzugefügt, sodass die entsprechenden Bilder zur Laufzeit gefunden werden können. Die spezifische Implementierung ist wie folgt: <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>

Der obige Code kann grundsätzlich die meisten Anforderungen an die Änderung der Haut erfüllen. Bei Projekten, die das Vorladen von Bildern erfordern, müssen wir jedoch auch Bilder verschiedener Themen unterscheiden, um die Optimierung und das frühe Laden zu erleichtern. Da der Link zum kompilierten Bild und die Kompilierung Der vorherige Link ist unterschiedlich, sodass wir den Link zum kompilierten Bild erhalten. Bei allgemeinen Projekten, beispielsweise bei Projekten, die mit dem offiziellen Gerüst vue-cli erstellt wurden, werden alle Bilder von url-loader verarbeitet und im selben Ordner image abgelegt, wodurch sie kompiliert werden

Bilder mit demselben Namen in verschiedenen Ordnern

Nach der Kompilierung ist der Hash unterschiedlich, sodass wir Bilder zu unterschiedlichen Themen nicht unterscheiden können.

Also müssen wir zuerst verschiedene Themenbilder in verschiedenen Ordnern ablegen. Das Gleiche gilt für die Verwendung des URL-Loaders.

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

Auf diese Weise werden die Bilder verschiedener Themen nach der Kompilierung in verschiedenen Ordnern abgelegt über? Noch nicht, wir müssen noch den kompilierten Bildlink erhalten, um das Themenbild vorab zu laden, wenn wir die Spielseite betreten. Hier können wir ein Webpack-Plugin schreiben, das uns hilft, die entsprechenden Bilder zu sammeln und JSON-Dateien für jedes Thema zu erstellen. Der Plug-in-Code lautet wie folgt:
rrree

Also erhalten wir die JSON-Bildliste verschiedener Themen, indem wir die Liste über Ajax abrufen und dann die Bilder in die anderen Tabellen laden die Bedürfnisse, es ist zu kompliziert? Gibt es eine einfache Möglichkeit? Natürlich gibt es das.

Optimierungsplan

Nachdem wir den obigen Code sorgfältig analysiert haben, möchten wir letztendlich das kompilierte Ergebnis des Bildes erhalten. Wenn wir also ein Bildobjekt generieren können, ist das picture Der name wird als Schlüssel und das kompilierte Ergebnis des Bildes als Wert verwendet. Dann kann der obige Code wie folgt vereinfacht werden:

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

Auf diese Weise wird der Code prägnant , und es ist nicht erforderlich, den gesamten Artikel zu erfordern und zu versuchen. Wie implementieren wir dann dieses SkinImage-Objekt? Die Antwort besteht darin, den require.context des Webpacks zu verwenden. Rufen Sie einen bestimmten Kontext ab, indem Sie die Funktion require.context ausführen Wird hauptsächlich zum Implementieren automatischer Importmodule verwendet. Wenn Sie viele Module aus einem Ordner importieren, werden die angegebenen Dateien im Ordner durchlaufen und dann automatisch importiert Das Importmodul muss jedes Mal explizit aufgerufen werden. Die spezifische Verwendung wird hier nicht beschrieben.

Bitte überprüfen Sie das offizielle Dokument requirecontext

https://webpack.docschina.org/guides/dependency-management/#requirecontext

🎜Also schreiben wir eine Funktion, die automatisch Bilder importiert und SkinImage-Objekte generiert🎜rrreee🎜Auf diese Weise erhalten wir das schwarze Design-Bildobjekt. Da require.context während des Kompilierungsprozesses und nicht zur Laufzeit ausgeführt wird, können alle Parameter nur statisch sein . Hier müssen wir auch das weiße Themenbild wie folgt erhalten: 🎜rrreee🎜Auf diese Weise erhalten wir die Bildobjekte der beiden Themen. Als nächstes müssen wir nur noch ein bestimmtes Objekt dem SkinImage der Stammkomponente zuweisen , und wir sind fertig. Ist es einfacher und prägnanter als das oben Gesagte? 🎜🎜Weitere Kenntnisse zum Thema Programmierung finden Sie unter: 🎜Einführung in die Programmierung🎜! ! 🎜

Das obige ist der detaillierte Inhalt vonSo erhalten Sie verschiedene Ressourcen und wechseln Bilder je nach Thema in Vue. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:juejin.cn. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen