Vue에서 테마에 따라 다양한 리소스를 얻고 이미지를 전환하는 방법은 무엇입니까? 다음 기사에서는 다중 이미지 스키닝 요구 사항을 실현하는 Vue의 우아한 방법을 소개합니다. 이것이 도움이 되기를 바랍니다.
[관련 추천: "vue.js Tutorial"]
최근 회사 Y의 작은 게임은 현지화된 테마를 구현해야 합니다. 즉, 지역마다 다른 테마를 표시해야 하며 게임은 사진이 많으니 어떻게 우아해져야 하는지 정확한 피부 이미지를 빠르게 로딩하는 것이 특히 중요합니다.
CSS 스타일 전환 커뮤니티에는 이미 많은 솔루션이 있으므로 직접 참조할 수 있습니다. 기사에서 이미 자세히 설명했으므로 여기서는 주로 다양한 리소스를 얻는 방법에 대해 설명하지 않겠습니다. 테마에 따라 이미지를 전환합니다.
이미지 리스킨닝, 과거 경험을 바탕으로 웹팩의 종속성 관리 덕분에 우리는 일반적으로 이미지를 도입할 때 require를 사용합니다. 예를 들어 (require(`@assets/img/${theme}/bg.png`))
를 작성하는 방식으로 웹팩은 모든 파일을 @assets/img에 저장합니다. code> 모두 번들에 추가되므로 런타임 중에 해당 이미지를 찾을 수 있습니다. 구체적인 구현은 다음과 같습니다. <code>(require(`@assets/img/${theme}/bg.png`))
,webpack会将@assets/img
中的所有文件都加入到bundle中,从而在运行的时候可以找到对应的图片。具体实现如下:
<template> <!-- 这里需要判断图片是否存在,如果不存在需要指定为auto,不然会引起404,导致系统告警 --> <div class="y-content" :style="{backgroundImage: contentBg ? `url(${contentBg})` : 'auto'}"> <img class="y-content__reward" :src="rewardImg" /> </div> </template> <script> data: () => ({ theme: 'blcak' }), computed: { contentBg() { try { // this.theme是文件夹,将不同的皮肤放到不同的文件夹,用同样的命名 return require(`@assets/img/${this.theme}/contentBg.png`) } catch (err) { return ''; } }, rewardImg() { try { return require(`@assets/img/${this.theme}/rewardImg.png`) } catch (err) { return ''; } } } </script>
以上代码基本上能解决大部分的换肤需求,但是对于图片需要预先加载的项目,我们还需要区分不同主题的图片便于优化提前加载,由于编译后的图片链接跟编译前的链接是不同,因此我们获取编译后的图片链接。一般的项目中比如使用官方脚手架vue-cli
构建的项目,所有的图片都会被url-loader
处理后放到同一个文件夹image当中,这样编译前不同文件夹相同名字的图片编译后之后hash
是不同,因此我们是无法区分不同主题的图片的。
于是,首先我们需要将不同的主题图片放置到不同的文件夹当中,同样适用用url-loader
// vue-cli配置 const imagesRule = config.module.rule('images'); imagesRule.uses.clear() //清除原本的images loader配置 imagesRule .test(/white/.+.(jpg|gif|png|svg)$/) .use('url-loader') .loader('url-loader') .options({ name:"img/white/[name].[hash:8].[ext]", limit: 8192 }) // 加多一个主题的配置 config.module .rule('image2') .test(/black/.+.(jpg|gif|png|svg)$/) .use('url-loader') .loader('url-loader') .options({name:"img/black/[name].[hash:8].[ext]", limit: 8192 }) // 自定义webpack配置 rules: [ { test: /white/.+.(png|svg|jpg|gif)$/, use: [ { loader: 'url-loader', options: { limit: 8192, name: 'img/white/[name].[hash:8].[ext]', } } ], }, { test: /black/.+.(png|svg|jpg|gif)$/, use: [ { loader: 'url-loader', options: { limit: 8192, name: 'img/black/[name].[hash:8].[ext]', } } ], }, ]
这样子编译后不同主题的图片就会被放置到不同的文件夹当中,这样就结束了吗?还没有,我们还需要获取编译后的图片链接,才能在进入游戏页面的时候提前加载主题图片,这里我们可以写一个webpack plugin来帮我们收集相应的图片,生产各自主题的json文件。插件代码如下:
// webpack版本为4.x class WebPackSouceManifest { // 将 `apply` 定义为其原型方法,此方法以 compiler 作为参数 constructor(option = {}) { // 黑色主题的文件名 this.blackManifestName = option.blackManifestName || 'js/blackManifest.json' // 白色主题的文件名 this.whiteManifestName = option.whiteManifestName || 'js/whiteManifest.json' this.blackJsonData = { code: 0, data: [] } this.whiteJsonData = { code: 0, data: [] } this.addFileToSouceManifest.bind(this) } apply(compiler) { // 指定要附加到的事件钩子函数 compiler.hooks.emit.tapAsync( 'HashServiceWorkerStartPlugin', (compilation, callback) => { const allBuildFiles = Object.keys(compilation.assets) allBuildFiles.forEach((file) => { if (file.indexOf('white') !== -1) { this.addFileToSouceManifest('white', file) } else { this.addFileToSouceManifest('black', 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 = 'text' } else if (/.js.map$/.test(file)) { fileItem.type = 'json' } if (type === 'white') { 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})` : 'auto'}"> <img class="y-content__reward" :src="rewardImg" /> </div> </template> <script> data: () => ({ theme: 'middleEast' }), computed: { contentBg() { // skinImage是跟组件下的字段 return this.$root.skinImage['contentBg'] // contentBg为name }, rewardImg() { return this.$root.skinImage['rewardImg'] } } </script>
vue-cli
를 사용하여 빌드한 프로젝트 등 일반 프로젝트에서는 모든 이미지를 url-loader
로 처리한 후 동일한 폴더 이미지에 배치하여 Before를 컴파일합니다. 다른 폴더에 있는 동일한 이름의 사진
편집 후해시
가 다르기 때문에 서로 다른 테마의 사진을 구별할 수 없습니다. 그러므로 먼저 서로 다른 테마 사진을 서로 다른 폴더에 배치해야 합니다. url-loaderconst black = require.context('../black', true, /.(png|jpg|gif)$/); const middleImageObj = {}; black.keys().forEach(path => { // 获取图片的key const key = path.slice(2, -4); blackImageObj[key] = rawSkin(path); });
const black = require.context('../black', true, /.(png|jpg|gif)$/); const middleImageObj = {}; black.keys().forEach(path => { // 获取图片的key const key = path.slice(2, -4); blackImageObj[key] = rawSkin(path); });로그인 후 복사로그인 후 복사그래서 우리는 다양한 테마의 json 이미지 목록을 얻습니다. 페이지에 들어갈 때 ajax를 통해 목록을 얻은 다음 위의 접근 방식을 충족할 수 있지만 이미지를 로드합니다. 요구 사항이 너무 복잡합니까? 쉬운 방법이 있나요? 물론 있습니다.
최적화 계획
위 코드를 주의 깊게 분석한 결과, 우리가 궁극적으로 얻고자 하는 것은 이미지의 컴파일된 결과이므로 그림 객체를 생성할 수 있다면, picture
rrreee이름
이 키로 사용되며, 이미지의 컴파일된 결과가 값으로 사용됩니다. 그러면 위 코드는 다음과 같이 단순화될 수 있습니다.이렇게 하면 코드가 간결해집니다. , 기사 전체에서 require 및 try catch가 필요하지 않습니다. 그러면 이 skinImage 개체를 어떻게 구현합니까?
답은 webpack의 require.context를 사용하는 것입니다
require.context 함수를 실행하여 특정 컨텍스트를 가져옵니다. 주로 자동화된 가져오기 모듈을 구현하는 데 사용됩니다. 폴더에서 많은 모듈을 가져올 때 이 API를 사용할 수 있습니다. 매번 가져오기 모듈을 명시적으로 호출해야 합니다. 자세한 사용법은 여기에서 설명하지 않습니다.
자세한 내용은 공식 문서 requirecontext를 확인하세요🎜🎜https://webpack.docschina.org/guides/dependent-management/#requirecontext 🎜🎜🎜그러면 자동으로 이미지를 가져와서 skinImage 객체를 생성하는 함수를 작성해 보겠습니다🎜rrreee🎜이렇게 하면 검은색 테마 이미지 객체를 얻게 됩니다. require.context는 런타임이 아닌 컴파일 과정에서 실행되므로 모든 매개변수는 정적일 수 있습니다. . 여기서도 다음과 같이 흰색 테마 이미지를 미리 가져와야 합니다. 🎜rrreee🎜이 방법으로 두 테마의 이미지 개체를 얻은 다음 루트 구성 요소의 skinImage에 특정 개체만 할당하면 됩니다. 위의 것보다 더 간단하고 간결합니까? 🎜🎜더 많은 프로그래밍 관련 지식을 보려면 🎜프로그래밍 소개🎜를 방문하세요! ! 🎜위 내용은 Vue에서 테마에 따라 다양한 리소스를 얻고 사진을 전환하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!