前端【CSS】23【样式穿透】【svg精灵图制作】

 1、样式穿透

在使用elementUI的时候,el-card提供了插槽,可以在使用的时候根据具名插槽指定自己想要的插槽内容,但是当要修改插槽内样式的时候,直接通过类名定位改样式,不好使,此时可以通过样式穿透来实现修改样式

 1 <template>
 2   <div class="login-page">
 3     <el-card>
 4       <!-- 1、卡片标题,使用具名插槽 -->
 5       <template #header>面经后台管理系统</template>
 6       <!-- 2、卡片内容,默认插槽,可以不用嵌套template -->
 7       卡片内容
 8     </el-card>
 9   </div>
10 </template>
11 
12 <script>
13 import { loginAPI } from '@/api/user'
14 
15 export default {
16   name: 'LoginIndex',
17 }
18 </script>
19 
20 <style lang="scss" scoped>
21 .login-page {
22   height: 100vh;
23   background: url(@/assets/login-bg.svg) no-repeat center;
24   background-size: cover;
25   // 使用element-ui,组件名,就是类名
26   .el-card {
27     width: 420px;
28     position: absolute;
29     left: 50%;
30     top: 50%;
31     transform: translate(-50%, -50%);
32     
33     // 想要修改具名插槽的样式, 直接通过.el-card__header类名修改,不好使
34     // 样式穿透,用于修改子组件元素的样式, 修改子组件header插槽的样式
35     ::v-deep .el-card__header {
36       text-align: center;
37       background-color: #727cf5;
38       color: #fff;
39       height: 80px;
40       line-height: 40px;
41     }
42     .el-form {
43       padding: 0 20px;
44     }
45   }
46 }
47 </style>

 

/deep/ 表示深度选择器

  css中通常会在 style 标签内添加 scoped 来避免父组件对子组件的影响,添加了之后只能修改当前组件的样式。

  这样做的原理是通过在打包的时候给每个样式都添加一个独一无二的hash值,从而避免父组件对子组件的样式的影响。

1 .title[data-v-211e4c4a] {  // 添加scoped后的效果
2     color: #ff0;
3 }

  设置了上述scoped的话,如果想要在父组件中修改子组件的样式时应该怎么样做呢?

  如果去掉scoped的话就会影响全局样式,但是加上scoped又不能在当前组件修改子组件的样式,这个时候就可以使用 /deep/ 了。

1 <style scoped>
2      /deep/ .title{
3         color: #ff0;
4     }
5 </style>

  除了 /deep/ 以外,>>> 和 ::v-deep也可以实现同样的效果

  注意:/deep/ 只能在像 less , sass 等css预处理器中使用,在原生css中使用无效,所以原生css当中应使用 >>> 。

 

 

css样式穿透

1 <style scoped>
2   父元素 >>> 子元素 {
3      color: red;
4   }
5 </style>

less样式穿透

1 <style lang="less" scoped>
2   父元素 /deep/  子元素 {
3      color: red
4   }
5 </style>

scss样式穿透

1 <style scoped>
2   父元素::v-deep  子元素 {
3      color: red
4   }
5 </style>

 

 

2、svg精灵图制作

  

   

  使用svg-sprite-loader

  1、下载依赖

1 npm i svg-sprite-loader

  2、添加配置vue.config.js

  1 'use strict'
  2 const path = require('path')
  3 
  4 function resolve (dir) {
  5   return path.join(__dirname, dir)
  6 }
  7 
  8 const port = process.env.port || 8081 // dev port
  9 
 10 module.exports = {
 11   publicPath: '/',
 12   outputDir: 'dist',
 13   assetsDir: 'static',
 14   lintOnSave: process.env.NODE_ENV === 'development',
 15   productionSourceMap: false,
 16   // 配置代理转发
 17   devServer: {
 18     port: port,
 19     open: true,
 20     overlay: {
 21       warnings: false,
 22       errors: true
 23     }
 24   },
 25   configureWebpack: {
 26     name: '黑马智慧园区',
 27     resolve: {
 28       alias: {
 29         '@': resolve('src')
 30       }
 31     }
 32   },
 33   chainWebpack (config) {
 34     // it can improve the speed of the first screen, it is recommended to turn on preload
 35     config.plugin('preload').tap(() => [
 36       {
 37         rel: 'preload',
 38         // to ignore runtime.js
 39         // https://github.com/vuejs/vue-cli/blob/dev/packages/@vue/cli-service/lib/config/app.js#L171
 40         fileBlacklist: [/\.map$/, /hot-update\.js$/, /runtime\..*\.js$/],
 41         include: 'initial'
 42       }
 43     ])
 44     // 配置cdn
 45     // when there are many pages, it will cause too many meaningless requests
 46     config.plugins.delete('prefetch')
 47 
 48     // 配置 svg-sprite-loader
 49     config.module
 50       .rule('svg')
 51       .exclude.add(resolve('src/icons'))
 52       .end()
 53     config.module
 54       .rule('icons')
 55       .test(/\.svg$/) // 查找所有 .svg结尾的文件
 56       .include.add(resolve('src/icons')) // 解析src/icons目录
 57       .end()
 58       .use('svg-sprite-loader')   // 使用svg-sprite-loader,帮助我们完成svg精灵图的制作
 59       .loader('svg-sprite-loader')
 60       .options({
 61         symbolId: 'icon-[name]'  // 指定symbolId格式,icon-文件名,如果不指定,则默认为文件名,
 62       })
 63       .end()
 64 
 65     config
 66       .when(process.env.NODE_ENV !== 'development',
 67         config => {
 68           config
 69             .plugin('ScriptExtHtmlWebpackPlugin')
 70             .after('html')
 71             .use('script-ext-html-webpack-plugin', [{
 72               // `runtime` must same as runtimeChunk name. default is `runtime`
 73               inline: /runtime\..*\.js$/
 74             }])
 75             .end()
 76           config
 77             .optimization.splitChunks({
 78               chunks: 'all',
 79               cacheGroups: {
 80                 libs: {
 81                   name: 'chunk-libs',
 82                   test: /[\\/]node_modules[\\/]/,
 83                   priority: 10,
 84                   chunks: 'initial' // only package third parties that are initially dependent
 85                 },
 86                 elementUI: {
 87                   name: 'chunk-elementUI', // split elementUI into a single package
 88                   priority: 20, // the weight needs to be larger than libs and app or it will be packaged into libs or app
 89                   test: /[\\/]node_modules[\\/]_?element-ui(.*)/ // in order to adapt to cnpm
 90                 },
 91                 commons: {
 92                   name: 'chunk-commons',
 93                   test: resolve('src/components'), // can customize your rules
 94                   minChunks: 3, //  minimum common number
 95                   priority: 5,
 96                   reuseExistingChunk: true
 97                 }
 98               }
 99             })
100           // https:// webpack.js.org/configuration/optimization/#optimizationruntimechunk
101           config.optimization.runtimeChunk('single')
102         }
103       )
104   }
105 }

  3、使用

    使用时,通过xlink:href='#文件名称'  或者 xlink:href='#自定义的symbolId'

    

  4、将这个svg封装成组件

 1 <template>
 2   <div v-if="isExternal" :style="styleExternalIcon" class="svg-external-icon svg-icon" v-on="$listeners" />
 3   <svg v-else :class="svgClass" aria-hidden="true" v-on="$listeners">
 4     <!--
 5       这里渲染svg图标的固定写法 iconName是由我们传给组件的iconClass和固定的字符串拼接得到的渲染名称
 6       我们传入不同的iconClass它就会渲染出来不同的图标!!!!
 7      -->
 8     <use :xlink:href="iconName" />
 9   </svg>
10 </template>
11 
12 <script>
13 // doc: https://panjiachen.github.io/vue-element-admin-site/feature/component/svg-icon.html#usage
14 import { isExternal } from '@/utils/validate'
15 
16 export default {
17   name: 'SvgIcon',
18   // props组件的参数 决定我们使用它的时候 如何通过传递不同的属性 让他渲染不同的小图标
19   props: {
20     iconClass: {
21       type: String,
22       required: true
23     },
24     className: {
25       type: String,
26       default: ''
27     }
28   },
29   computed: {
30     isExternal() {
31       return isExternal(this.iconClass)
32     },
33     iconName() {
34       return `#icon-${this.iconClass}`
35     },
36     svgClass() {
37       if (this.className) {
38         return 'svg-icon ' + this.className
39       } else {
40         return 'svg-icon'
41       }
42     },
43     styleExternalIcon() {
44       return {
45         mask: `url(${this.iconClass}) no-repeat 50% 50%`,
46         '-webkit-mask': `url(${this.iconClass}) no-repeat 50% 50%`
47       }
48     }
49   }
50 }
51 </script>
52 
53 <style scoped>
54 .svg-icon {
55   width: 1em;
56   height: 1em;
57   vertical-align: -0.15em;
58   fill: currentColor;
59   overflow: hidden;
60 }
61 
62 .svg-external-icon {
63   background-color: currentColor;
64   mask-size: cover!important;
65   display: inline-block;
66 }
67 </style>

  5、使用组件

  icons/index.js

 1 import Vue from 'vue'
 2 // 1.全局注册名称为 svg-icon 组件 在任何一个.vue文件中
 3 // 都可以通过 <svg-icon/> 进行图标渲染
 4 import SvgIcon from '@/components/SvgIcon'
 5 Vue.component('svg-icon', SvgIcon)
 6 
 7 // 2. 把svg目录下的所有的.svg文件都变成 模块化可用的状态
 8 const req = require.context('./svg', false, /\.svg$/)
 9 const requireAll = requireContext => {
10   requireContext.keys().map(requireContext)
11 }
12 
13 requireAll(req)
14 
15 // 最终实现的效果:<svg-icon icon-class="svg图标的名称"/> -> 渲染出来一个图标

  icons/svg/下面放全部的svg图

  main.js中注册svg

1 // 注册svg
2 import '@/icons'

  组件中使用上面的svg组件,此处的more就是渲染more.svg图标

1 <svg-icon icon-class="more" />

 

posted @ 2024-04-09 11:22  为你编程  阅读(564)  评论(0编辑  收藏  举报