精灵图想必对大家来说都不陌生,就是将多个小图整合到一张图上,以此减少浏览器向服务器请求的次数,从而提高网页的加载速度。
而在 Vue 项目中,我通常会使用 webpack-spritesmith 这个 npm 包来制作需要的精灵图,而这篇文章主要是针对 webpack-spritesmith 的一些高阶使用技巧。
如果你没使用过 webpack-spritesmith ,建议熟悉了解后再阅读本篇文章。
虽然 webpack-spritesmith 已经能帮我减轻很大的工作量了,但在项目中具体使用的时候,还是会遇到一些不大不小的问题,之所以说不大不小,是因为这些问题的解决方案有很多种,而下面我所提供的解决方案,只是单纯从技术角度去思考如何处理。
痛点一:变量名冲突
在配置好各种参数,并且精灵图和对应的 .scss
文件都能生成好后,第一个痛点就来了。
我们先观察一下生成好的 .scss
文件,大致如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 $address-name : 'address' ;$address-x : 0px ;$address-y : 0px ;$address-offset-x : 0px ;$address-offset-y : 0px ;$address-width : 100px ;$address-height : 100px ;$address-total-width : 200px ;$address-total-height : 200px ;$address-image : '~sprites.fe6c69f7e7ec270381e68e2dd4a910c1.png' ;$address : (0px , 0px , 0px , 0px , 100px , 100px , 200px , 200px , '~sprites.fe6c69f7e7ec270381e68e2dd4a910c1.png' , 'address' , );$feedback-name : 'feedback' ;$feedback-x : 100px ;$feedback-y : 0px ;$feedback-offset-x : -100px ;$feedback-offset-y : 0px ;$feedback-width : 100px ;$feedback-height : 100px ;$feedback-total-width : 200px ;$feedback-total-height : 200px ;$feedback-image : '~sprites.fe6c69f7e7ec270381e68e2dd4a910c1.png' ;$feedback : (100px , 0px , -100px , 0px , 100px , 100px , 200px , 200px , '~sprites.fe6c69f7e7ec270381e68e2dd4a910c1.png' , 'feedback' , );$payment-name : 'payment' ;$payment-x : 0px ;$payment-y : 100px ;$payment-offset-x : 0px ;$payment-offset-y : -100px ;$payment-width : 100px ;$payment-height : 100px ;$payment-total-width : 200px ;$payment-total-height : 200px ;$payment-image : '~sprites.fe6c69f7e7ec270381e68e2dd4a910c1.png' ;$payment : (0px , 100px , 0px , -100px , 100px , 100px , 200px , 200px , '~sprites.fe6c69f7e7ec270381e68e2dd4a910c1.png' , 'payment' , );$spritesheet-width : 200px ;$spritesheet-height : 200px ;$spritesheet-image : '~sprites.fe6c69f7e7ec270381e68e2dd4a910c1.png' ;$spritesheet-sprites : ($address , $feedback , $payment , );$spritesheet : (200px , 200px , '~sprites.fe6c69f7e7ec270381e68e2dd4a910c1.png' , $spritesheet-sprites , );@mixin sprite-width($sprite ) { width : nth($sprite , 5 ); } @mixin sprite-height($sprite ) { height : nth($sprite , 6 ); } @mixin sprite-position($sprite ) { $sprite-offset-x : nth($sprite , 3 ); $sprite-offset-y : nth($sprite , 4 ); background-position : $sprite-offset-x $sprite-offset-y ; } @mixin sprite-image($sprite ) { $sprite-image : nth($sprite , 9 ); background-image : url(#{$sprite-image }); } @mixin sprite($sprite ) { @include sprite-image($sprite ); @include sprite-position($sprite ); @include sprite-width($sprite ); @include sprite-height($sprite ); } @mixin sprites($sprites ) { @each $sprite in $sprites { $sprite-name : nth($sprite , 10 ); .#{$sprite-name } { @include sprite($sprite ); } } }
其实生成出来的 .scss
文件很简单,就是包含了一些变量和 @mixin
,这样在 @import
这个 .scss
文件之后就可以很方便的进行使用了。
1 2 3 .example { @include sprite($address ); }
但是也出现了一个问题,就是生成出来的这个变量,在使用的时候如果稍有不注意,可能就会和项目中自定义的一些全局变量重名,导致变量被覆盖。
这个问题其实可以用很简单办法解决,仔细观察就会发现,变量名是依据文件名定义的,所以在给图片文件命名的时候,定义好一个规则就行了,比如全部以 sprite-
开头,这样就极大程度避免了变量的重名的问题,只是在使用的时候会麻烦一点,就需要改成这样。
1 2 3 .example { @include sprite($sprite-address ); }
有没有更好的方法呢?答案当然是有。在查看 webpack-spritesmith 介绍的时候看到了这句话:
Webpack plugin that converts set of images into a spritesheet and SASS/LESS/Stylus mixins, using spritesmith and spritesheet-templates .
说明 .scss
文件其实是通过模版生成的,那只要对模版修改一下,理论上就可以解决这问题了。
首先找到原始的模版,在 spritesheet-templates 这个仓库里搜寻后发现 scss.template.handlebars
这个文件。
接下来先对模版进行精简,因为生成出来的一系列变量中,只用到了这句:
1 $address : (0px , 0px , 0px , 0px , 100px , 100px , 200px , 200px , '~sprites.fe6c69f7e7ec270381e68e2dd4a910c1.png' , 'address' , );
它将所有的值都存放在了一个数组变量中,在 @mixin
中通过 nth()
这个方法去获取数组中其中所需要的值,所以只需要保留这段模版即可:
1 $ {{strings.name }} : ( {{px.x }} , {{px.y }} , {{px.offset_x }} , {{px.offset_y }} , {{px.width }} , {{px.height }} , {{px.total_width }} , {{px.total_height }} , ' {{{escaped_image }}} ', ' {{name }} ', );
剩下生成 @mixin
的模版都是需要用到的,那就原封不动的复制过来,这样就初步定制了一个我的模版。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 { // Default options 'functions': true, 'variableNameTransforms': ['dasherize'] } {{#block "sprites" }} {{#each sprites}} $ {{strings.name }} : ( {{px.x }} , {{px.y }} , {{px.offset_x }} , {{px.offset_y }} , {{px.width }} , {{px.height }} , {{px.total_width }} , {{px.total_height }} , ' {{{escaped_image }}} ', ' {{name }} '); {{/each }} {{#block "sprite-functions" }} {{#if options.functions}} @mixin sprite-width($sprite) { width: nth($sprite, 5); } @mixin sprite-height($sprite) { height: nth($sprite, 6); } @mixin sprite-position($sprite) { $sprite-offset-x: nth($sprite, 3); $sprite-offset-y: nth($sprite, 4); background-position: $sprite-offset-x $sprite-offset-y; } @mixin sprite-image($sprite) { $sprite-image: nth($sprite, 9); background-image: url(#{$sprite-image}); } @mixin sprite($sprite) { @include sprite-image($sprite); @include sprite-position($sprite); @include sprite-width($sprite); @include sprite-height($sprite); } {{/if }} {{/block }}
接下来要解决变量名冲突的问题,我在模版里给变量名增加一个前缀,也叫 sprite-
。
1 $sprite- {{strings.name }} : ( {{px.x }} , {{px.y }} , {{px.offset_x }} , {{px.offset_y }} , {{px.width }} , {{px.height }} , {{px.total_width }} , {{px.total_height }} , ' {{{escaped_image }}} ', ' {{name }} ');
这样就好了么?还没有。虽然变量名不冲突了,但在使用的时候还是没有变化。
1 2 3 .example { @include sprite($sprite-address ); }
依旧要多写 sprite-
这个前缀,为了偷这个懒,我进行了进一步的定制。
因为 sprite
这个 @mixin
需要传入指定的变量做为参数,那能不能改成传入一个字符串,动态拼装一个变量呢?比如这样:
1 2 3 4 5 6 @mixin sprite($name ) { @include sprite-image($sprite -#{$name }); @include sprite-position($sprite -#{$name }); @include sprite-width($sprite -#{$name }); @include sprite-height($sprite -#{$name }); }
很遗憾,并不行,查了资料才知道 SASS 并不支持动态创建引用变量。虽然不支持动态变量,那就换个思路,把所需要的变量放到一个数组变量里总可以吧?这样说可能有点绕,直接看代码吧。
1 2 3 4 5 6 7 8 9 10 11 12 $sprites: ( {{#each sprites}} {{strings.name }} : $sprite- {{strings.name }} , {{/each }} ); @mixin sprite($name) { @include sprite-image(map-get($sprite, #{$name})); @include sprite-position(map-get($sprite, #{$name})); @include sprite-width(map-get($sprite, #{$name})); @include sprite-height(map-get($sprite, #{$name})); }
我单独定义了一个 $sprites
变量,里面是一个键值对的数组,键是文件名,值是通过拼装出来变量。而在 @mixin
中则使用了 map-get()
这个方法去获取到对应的变量,再接下来就是和原先一样了。
这样处理之后,直接就可以这样使用了,甚至比原有的方式更简单,都不需要写 $
符号了。
1 2 3 .example { @include sprite(address); }
最后就是如何调用我的自定义模版了,这在 webpack-spritesmith 的文档中详细的介绍,我就不具体细说了,贴一份大致的代码吧。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 new SpritesmithPlugin({ src: { cwd: path.resolve(__dirname, 'src/assets/sprites' ), glob: '*.png' }, target: { image: path.resolve(__dirname, 'src/assets/images/sprites.[hash].png' ), css: [ [path.resolve(__dirname, 'src/assets/style/sprites.scss' ), { format: 'handlebars_based_template' }] ] }, customTemplates: { 'handlebars_based_template' : path.resolve(__dirname, 'my.scss.template.handlebars' ) }, apiOptions: { cssImageRef: '~sprites.[hash].png' } })
痛点二:文件名冲突
在说这个问题之前,先说明一下, webpack-spritesmith 是可以生成多张精灵图的,虽然办法有点蠢,就是多增加一个 new SpritesmithPlugin()
实例,把里面的路径都替换即可。
当然办法是蠢的,但我可是聪明的,可以借助 fs 模块遍历精灵图存放目录的文件夹,依次执行 new SpritesmithPlugin()
就行啦,具体可点击看这里
如果项目比较大,并且有多个模块,这个时候可能就会需要根据不同模块生成对应的精灵图,也就是小图会归类到不同的文件夹,但也就出现一个情况,不同文件夹里的图片文件名可能会重名,比如这种情况:
1 2 3 4 5 6 7 sprites ├─ order │ ├─ success .png │ └─ close .png └─ payment ├─ success .png └─ fail .png
sprites 目录下有两个文件夹,分别是 order 和 payment ,并且里面都有一个 success.png
文件,假设这两个目录生成出的两个 .scss
文件需要在同一个页面上调用,就又出现上面变量名冲突的问题了。
举例的这种情况可能不常见,更多情况可能是有一个存放全局精灵图的目录,里面的文件名可能会和某个模块文件夹下的文件名重名,导致在使用的时候出现变量名冲突。
这个问题也可以用简单的办法解决,不就是改个文件名嘛,但如果项目是多人协作开发,这个问题就会变成一个潜在隐患,不知道什么时候就和别人定义的名字重名了。所以我还是决定用技术手段来解决。
方案一
我最先的思路是,能不能将文件夹的名字做为一个新增变量注入到模版中,这样在模板中就可以通过模版变量 {{...}}
的方式去使用了,但翻遍了 webpack-spritesmith 文档也没找到相关的 API ,不过倒是在模版选项里看到了 spritesheetName
的设置项,它对应的模版变量是 spritesheet_info.name
,这是一个没被使用到模版变量,正好可以用来解决我的问题。
使用也很简单,只需要在配置里增加这一项设置,并设置为文件夹的名字即可:
1 2 3 4 5 6 7 8 9 10 11 12 13 new SpritesmithPlugin({ ... target: { image: path.resolve(__dirname, 'src/assets/images/order.[hash].png' ), css: [ [path.resolve(__dirname, 'src/assets/style/order.scss' ), { spritesheetName: 'order' , format: 'handlebars_based_template' }] ] }, ... })
接下来在模版里通过 {{spritesheet_info.strings.name}}
就可以得到刚才设置的值,只需要把对应位置的变量和 @mixin
都加上这个前缀就行了,需要注意的是,在 {{#each}}
里需要通过增加 ../
的方式来访问父级属性,下面为部分模版代码。
1 2 3 4 5 6 7 8 9 10 11 12 13 $ {{spritesheet_info.strings.name }} -sprites: ( {{#each sprites}} {{strings.name }} : $ {{../spritesheet_info.strings.name }} -sprite- {{strings.name }} , {{/each }} ); @mixin {{spritesheet_info.strings.name }} -sprite($name) { @include {{spritesheet_info.strings.name }} -sprite-image(map-get($ {{spritesheet_info.strings.name }} -sprites, #{$name})); @include {{spritesheet_info.strings.name }} -sprite-position(map-get($ {{spritesheet_info.strings.name }} -sprites, #{$name})); @include {{spritesheet_info.strings.name }} -sprite-width(map-get($ {{spritesheet_info.strings.name }} -sprites, #{$name})); @include {{spritesheet_info.strings.name }} -sprite-height(map-get($ {{spritesheet_info.strings.name }} -sprites, #{$name})); @include {{spritesheet_info.strings.name }} -sprite-size(map-get($ {{spritesheet_info.strings.name }} -sprites, #{$name})); }
这样修改后,生成出来的 .scss
文件中的变量和 @mixin
都加上了文件夹名做为前缀,所以在使用上也稍微有变化。如果有用过 Compass 制作精灵图的,一定不陌生。
1 2 3 .example { @include order-sprite(success); }
方案二
这个思路是在看 webpack-spritesmith 文档时想到的,然后结合了上网的一些参考资料最终实现的。首先先看一下文档里对 generateSpriteName()
这个方法的介绍吧。
generateSpriteName - function. Takes full path to source image file and expected to return name by which it will be referenced in API. Return value will be used as sprite.name for spritesheet-templates. Default behaviour is to use filename (without dirname and extension)
大概意思是说,通过 generateSpriteName()
方法可以获取到源文件的完整路径,并且可以手动返回一个将在 API 中引用的名称,默认返回的是文件名。
既然能得到完整路径,那在返回的时候,把文件夹的名称和文件名一起返回,这样在模版中不就解决变量冲突的问题了么,毕竟文件夹名加上文件名,这样组出来的名称能重名的就很少了。
直接看配置代码吧,这些需要用到 Node 里的 path
模块。
1 2 3 4 5 6 7 8 9 10 11 12 13 new SpritesmithPlugin({ ... apiOptions: { generateSpriteName: function (fullPath ) { let parsed = path.parse(fullPath) let dir = parsed.dir.split(path.sep) let moduleName = dir[dir.length - 1 ] return moduleName + '_' + parsed.name }, cssImageRef: '~order.[hash].png' }, ... })
打开生成出来的 .scss
文件看看。
1 $sprite-order-success : (0px , 0px , 0px , 0px , 100px , 100px , 200px , 200px , '~order.fe6c69f7e7ec270381e68e2dd4a910c1.png' , 'order_success' );
那么如何使用呢?
1 2 3 .example { @include sprite(order-success); }
是不是觉得和方案一没太大差别,其实在使用上确实没太大差别。两个方案生成的变量名都是唯一的,只不过前者是从 @mixin
命名上做了区分,不同的文件夹会生成多个不同的 @mixin
;而后者会生成多个同名且代码一模一样的 @mixin
,在使用的时候,后面定义的同名 @mixin
会进行重写覆盖,但因为代码是一样的,所以使用上并无影响。
但从代码优雅上来说,还是方案一 更好,各自的变量和 @mixin
都相对独立,不受干扰。
痛点三:响应式布局
因为生成的 .scss
文件里使用的都是 px 单位,而在响应式布局下会使用 rem 或者 vw/vh 做为长度大小单位,这时候就出现一个问题,如何在响应式布局下更方便的使用生成出来的 .scss
文件呢?
这里我以 vw/vh 举例,首先先给项目安装 postcss-px-to-viewport 这个 npm 包,它可以很方便的帮我把 px 转成 vw/vh 。
这个包如何使用这里不做更多介绍,重点是在配置好后, .scss
文件定义的一些 px 单位也能正常转换成 vw 单位了。但是因为 vw 是一个相对长度单位,在不同终端下它计算出来的实际长度并不是一致的,而生成出来的精灵图文件的尺寸是固定的,导致 background-position
定位不能准确的定位到某个图片上。
要解决这个问题,就需要使用 background-size
这个属性了,但不是使用 cover/contain 这两个预设的值,因为 cover 是拉伸图片使之充满元素,虽然元素被铺满了,但是图片有可能显示不全;而 contain 刚好相反,它是拉伸图片使图片完全显示在元素内,虽然图片显示全了,但是元素可能不会被铺满。所以这里就需要手动设置背景图的宽高来解决。思路确定了,那就看看模版里有没有提供合并后图片宽高的参数。
1 $sprite- {{strings.name }} : ( {{px.x }} , {{px.y }} , {{px.offset_x }} , {{px.offset_y }} , {{px.width }} , {{px.height }} , {{px.total_width }} , {{px.total_height }} , ' {{{escaped_image }}} ', ' {{name }} ');
从数组变量中可以看到 {{px.total_width}}
和 {{px.total_height}}
这两个就是精灵图图片的宽高了,有了这两个值,就可以在 @mixin
中增加一句 background-size
的样式代码了,为了代码风格统一,我增加一个 @mixin sprite-size
。
1 2 3 4 5 6 7 8 9 10 11 @mixin sprite-size($sprite) { background-size: nth($sprite, 7) nth($sprite, 8); } @mixin sprite($name) { @include sprite-image(map-get($sprites, #{$name})); @include sprite-position(map-get($sprites, #{$name})); @include sprite-size(map-get($sprites, #{$name})); @include sprite-width(map-get($sprites, #{$name})); @include sprite-height(map-get($sprites, #{$name})); }
这样 background-size
设置的宽高就和精灵图的实际宽高一致了,再通过 px 转 vw 后,也不会出现任何问题。
另外需要注意的是,因为 vw 计算出来的实际长度大概率会出现小数,如果精灵图贴合太紧凑,就会出现图片显示不全或超出的情况,解决这个问题只需要在配置中增加 padding
的设置即可。
1 2 3 4 5 6 7 new SpritesmithPlugin({ ... spritesmithOptions: { padding: 10 }, ... })
补充痛点:嫌手动引入麻烦
最后这个痛点是因第二个痛点引发而来的,因为项目模块多,生成的 .scss
文件也很多,在页面上使用的时候,经常会忘记要先引入对应的 .scss
文件后,再去使用 @mixin
。
因为生成的都是变量和 @mixin
,所以我就在想能不能全局引用,这样就不用在每个页面上使用的时候再去引用了。但是手动一个个在 main.js
里引用还是不够智能,于是网上搜寻了一番,发现了 sass-resources-loader 这个 npm 包。
This loader will @import
your SASS resources into every required
SASS module. So you can use your shared variables & mixins across all SASS styles without manually importing them in each file. Made to work with CSS Modules!
官方文档里第一句话就说的很清楚了。因为没啥技术含量,下面接直接贴配置代码了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 chainWebpack: config => { const oneOfsMap = config.module.rule('scss' ).oneOfs.store oneOfsMap.forEach(item => { item.use('sass-resources-loader' ) .loader('sass-resources-loader' ) .options({ resources: [ './src/assets/styles/global/*.scss' , './src/assets/sprites/*.scss' ] }) .end() }) }
这里我还指定一个 global 目录下的所有 .scss
文件,这是我存放整站自定义的一些全局变量、@mixin
等一些资源。
需要注意的是, sass-resources-loader 只会把变量、@mixin
、@function
这类资源注入到全局,如果文件里包含实际的样式代码,它并不会生效。
总结
也没啥可总结的,该说的在上面都说了,非要总结的话,那就是多看官方文档,很多问题其实插件/包的作者都有考虑到,合理使用就能达到想要的效果。
最后分享下完整的配置和模版,因为上面都是代码片段,我知道很多人都偷懒,想直接用现成的。
vue.config.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 const path = require ('path' )const SpritesmithPlugin = require ('webpack-spritesmith' )module .exports = { publicPath: '' , configureWebpack: { resolve: { modules: ['node_modules' , 'assets/sprites' ] }, plugins: [ new SpritesmithPlugin({ src: { cwd: path.resolve(__dirname, 'src/assets/sprites/example' ), glob: '*.png' }, target: { image: path.resolve(__dirname, 'src/assets/sprites/example.[hash].png' ), css: [ [path.resolve(__dirname, 'src/assets/sprites/example.scss' ), { format: 'handlebars_based_template' , spritesheetName: 'example' }] ] }, customTemplates: { 'handlebars_based_template' : path.resolve(__dirname, 'my.scss.template.handlebars' ) }, apiOptions: { cssImageRef: '~example.[hash].png' }, spritesmithOptions: { algorithm: 'binary-tree' , padding: 10 } }) ] } }
my.scss.template.handlebars
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 { // Default options 'functions': true, 'variableNameTransforms': ['dasherize'] } {{#block "sprites" }} {{#each sprites}} $ {{../spritesheet_info.strings.name }} -sprite- {{strings.name }} : ( {{px.x }} , {{px.y }} , {{px.offset_x }} , {{px.offset_y }} , {{px.width }} , {{px.height }} , {{px.total_width }} , {{px.total_height }} , ' {{{escaped_image }}} ', ' {{name }} '); {{/each }} $ {{spritesheet_info.strings.name }} -sprites: ( {{#each sprites}} {{strings.name }} : $ {{../spritesheet_info.strings.name }} -sprite- {{strings.name }} , {{/each }} ); {{/block }} {{#block "sprite-functions" }} {{#if options.functions}} @mixin {{spritesheet_info.strings.name }} -sprite-width($sprite) { width: nth($sprite, 5); } @mixin {{spritesheet_info.strings.name }} -sprite-height($sprite) { height: nth($sprite, 6); } @mixin {{spritesheet_info.strings.name }} -sprite-position($sprite) { $sprite-offset-x: nth($sprite, 3); $sprite-offset-y: nth($sprite, 4); background-position: $sprite-offset-x $sprite-offset-y; } @mixin {{spritesheet_info.strings.name }} -sprite-size($sprite) { background-size: nth($sprite, 7) nth($sprite, 8); } @mixin {{spritesheet_info.strings.name }} -sprite-image($sprite) { $sprite-image: nth($sprite, 9); background-image: url(#{$sprite-image}); } @mixin {{spritesheet_info.strings.name }} -sprite($name) { @include {{spritesheet_info.strings.name }} -sprite-image(map-get($ {{spritesheet_info.strings.name }} -sprites, #{$name})); @include {{spritesheet_info.strings.name }} -sprite-position(map-get($ {{spritesheet_info.strings.name }} -sprites, #{$name})); @include {{spritesheet_info.strings.name }} -sprite-size(map-get($ {{spritesheet_info.strings.name }} -sprites, #{$name})); @include {{spritesheet_info.strings.name }} -sprite-width(map-get($ {{spritesheet_info.strings.name }} -sprites, #{$name})); @include {{spritesheet_info.strings.name }} -sprite-height(map-get($ {{spritesheet_info.strings.name }} -sprites, #{$name})); } {{/if }} {{/block }} {{#block "spritesheet-functions" }} {{#if options.functions}} @mixin {{spritesheet_info.strings.name }} -sprites($sprites) { @each $sprite in $sprites { $sprite-name: nth($sprite, 10); .sprite-#{$sprite-name} { @include {{spritesheet_info.strings.name }} -sprite($sprite); } } } {{/if }} {{/block }}
最后的最后,本篇文章涉及到的内容也已经同步更新到 vue-autumation 中,这是一个基于 Vue CLI 3 制作的 Vue 脚手架,能方便快速进行业务开发。
参考