Geeks_Z の Blog Geeks_Z の Blog
首页
  • 学习笔记

    • 《HTML》
    • 《CSS》
    • 《JavaWeb》
    • 《Vue》
  • 后端文章

    • Linux
    • Maven
    • 汇编语言
    • 软件工程
    • 计算机网络概述
    • Conda
    • Pip
    • Shell
    • SSH
    • Mac快捷键
    • Zotero
  • 学习笔记

    • 《数据结构与算法》
    • 《算法设计与分析》
    • 《Spring》
    • 《SpringMVC》
    • 《SpringBoot》
    • 《SpringCloud》
    • 《Nginx》
  • 深度学习文章
  • 学习笔记

    • 《PyTorch》
    • 《ReinforementLearning》
    • 《MetaLearning》
  • 学习笔记

    • 《高等数学》
    • 《线性代数》
    • 《概率论与数理统计》
  • 增量学习
  • 哈希学习
GitHub (opens new window)

Geeks_Z

AI小学生
首页
  • 学习笔记

    • 《HTML》
    • 《CSS》
    • 《JavaWeb》
    • 《Vue》
  • 后端文章

    • Linux
    • Maven
    • 汇编语言
    • 软件工程
    • 计算机网络概述
    • Conda
    • Pip
    • Shell
    • SSH
    • Mac快捷键
    • Zotero
  • 学习笔记

    • 《数据结构与算法》
    • 《算法设计与分析》
    • 《Spring》
    • 《SpringMVC》
    • 《SpringBoot》
    • 《SpringCloud》
    • 《Nginx》
  • 深度学习文章
  • 学习笔记

    • 《PyTorch》
    • 《ReinforementLearning》
    • 《MetaLearning》
  • 学习笔记

    • 《高等数学》
    • 《线性代数》
    • 《概率论与数理统计》
  • 增量学习
  • 哈希学习
GitHub (opens new window)
  • Linux

  • Java

  • 微服务笔记

  • MySQL

  • Nginx

  • HTML

  • CSS

  • JavaWeb

  • Vue

    • Start
    • Node和NPM
    • 快速入门
    • Vue实例
    • 组件化
    • 模块化
    • webpack
    • vue-cli
    • Promies
    • Vuex
    • Axios
    • vue-router
    • ref $refs(元素、组件引用 )
    • 生命周期
    • Mix(混入)配置项
    • 安装插件 use()
    • 功能样式
    • 项目开发配置
    • 样式绑定
      • 绑定 class
      • 绑定图片路径(静态, 动态)
        • 静态绑定
        • 对图片编码的原因
        • url-loader 和 file-loader 关系
        • 动态绑定
        • 按照之前的写法会报错
        • webpack 引入才可以
        • 原因
        • 直接放在 static 文件夹下
        • 关于~(准确性未知)
      • 样式 scoped 与样式穿透
      • scoped
        • 实现原理
      • scoped 穿透
        • >>>
        • /deep/
        • ::v-deep
        • :deep
      • Reference
    • 事件
  • Git

  • 开发规范

  • SpringCloud微服务权限系统

  • bug

  • Software

  • ProgramNotes
  • Vue
Geeks_Z
2022-10-31
目录

样式绑定

绑定 class

Vue 最好不要亲手操作 DOM

  1. 字符串写法(个数一个,名字不确定)
<div id="root">
  <div class="basic" :class="mood" @click="change"></div>
</div>
<script>
  const app = Vue.createApp({
    el: '#root',
    data() {
      return {
        value: 100,
        mood: 'normal'
      }
    },
    methods: {
      change(){
        this.mood = 'happy'
      }
    },
  })
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

其中 :class 里面的是 Vue 实例中的变量,该变量的值才是元素真实的 class,Vue 编译后会将变量替换合并至前面的 class 里面:

Untitled

适用于样式的类名会切换

  1. 如果元素后续会添加很多个样式:绑定一个数组(个数不确定,名字不确定)
<div id="root">
  <div class="basic" :class="classArr" @click="change"></div>
</div>
<script>
  const app = Vue.createApp({
    el: '#root',
    data() {
      return {
        classArr: ['class1', 'class2']
      }
    },
  })
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
  1. 还可以是一个对象(个数确定,名字也确定)
<div id="root">
  <div class="basic" :class="classObj" @click="change"></div>
</div>
<script>
  const app = Vue.createApp({
    el: '#root',
    data() {
      return {
        classObj: {
          class1: false,
          class2: true   // true表示添加该类,false不添加
        }
      }
    },
  })
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

style 也可以交给 Vue 来动态绑定,需要改为多单词大小写模式

绑定图片路径(静态, 动态)

静态绑定

在布局时直接写好图片或背景的路径。

  • 在 html 中设置 img 的 src 属性

    <div>
      <img src="../assets/images/1.jpeg" />
    </div>
    
    1
    2
    3

    Untitled

  • 在 css 中设置 background 属性

    <div>
    </div>
    
    <style>
    	div{
    		background: url('../assets/images/1.jpeg') no-repeat;
    </style>
    
    1
    2
    3
    4
    5
    6
    7
  • 在 data 中声明,并在模板中绑定

    export default {
      data() {
        return {
          // 顶部导航背景图片配置
          background: {
            // 背景图片地址
            backgroundImage: 'url(' + require('../../../static/img/person/temp1.png') + ')',
            // 背景图片是否重复
            backgroundRepeat: 'no-repeat',
            // 背景图片大小
            backgroundSize: 'cover',
            // 背景颜色
            backgroundColor: '#000',
            // 背景图片位置
            backgroundPosition: 'center top',
          },
        }
      },
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19

    Untitled

可以看到不管是在 html 中引入或在 css 中引入图片都会被解析成 base64 编码,打包之后 dist 文件夹中也不会有图片,而是在压缩文件中存储 base64 编码。

对图片编码的原因

加载一张图片就需要发送一次 http 请求,当图片过多时会降低页面性能,因此 webpack 引入了 url-loader 解决这个问题。

  1. url-loader 会对引入的图片编码,生成 dataURI 。相当于把图片数据翻译成一串字符,再把这些字符打包到文件当中,最终只需要引入这个文件就可以访问图片。
  2. 当然如果图片较大,编码也会消耗性能,因此 url-loader 提供了一个 limit 参数,小于 limit 字节的文件会被转为 dataURl,大于 limit 的还是会使用 file-loader 进行 copy,一般会放在 static 文件夹下面。

url-loader 和 file-loader 关系

简单的将,url-loader 封装了 file-loader。打包时 url-loader 的工作分两种情况:

  1. 文件大小小于 limit 参数,url-loader 会把文件转为 dataURL;
  2. 文件大小大于 limit,url-loader 会调用 file-loader 进行处理,参数也会直接传给 file-loader,file-loader 将图片拷贝到 static 文件夹下。

动态绑定

将图片的路径绑定在一个 js 变量里,运行时动态绑定。

按照之前的写法会报错

<div>
  <img :src="img" />
</div>
<script>
  export default {
    data() {
      return {
        img: '../assets/images/1.jpeg',
      }
    },
  }
</script>
1
2
3
4
5
6
7
8
9
10
11
12

Untitled

webpack 引入才可以

用 require 或 import 就可以正常展示,并且最终效果跟在 html 中或者 css 中直接绑定效果是一样的。

  • require

    <div>
      <img :src="img" />
    </div>
    <script>
      export default {
        data() {
          return {
            img: require('../assets/images/1.jpeg'),
          }
        },
      }
    </script>
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
  • import

    <div>
      <img :src="img" />
    </div>
    <script>
    import img1 from '../assets/images/1.jpeg'
      export default {
        data() {
          return {
            img: img1,
          }
        },
      }
    </script>
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13

原因

使用不同的方式设置图片源,webpack 对他们的处理方式也是不同的:

  • 使用 import 或者 require 或者 静态绑定 都会被 webpack 的 url-loader 当做依赖模块处理;
  • 如果是直接写在 js 中,因为 js 是动态的,所以 webpack 不会处理的,打包后也不会显示在 dist 目录中。

直接放在 static 文件夹下

第三种情况,图片放在 static 文件夹下面,在 html、css、js 中直接引入,可以发现图片都可以正常展示。

Untitled

webpack 只能处理静态资源。assets 和 static 两个文件都是静态的,但是它们是有区别的

  • static 文件夹下面的文件是无法被 webpack 处理的,必须使用绝对路径来引用这些文件。

  • 其他地方的文件或图片都可以被 webpack 解析成模块依赖,这时候就可以用 url-loader 和 css-loader 去处理。

  • 如果在 js 中直接返回图片地址,因为 js 是动态的,所以 webpack 不会去处理。

  • 但是可以使用 require 或 import 将图片当成模块加载进来,这样就会被 webpack 当成静态文件解析,然后就可以被 url-loader 处理。

关于~(准确性未知)

当这样引入出现错误时

Untitled

需要改为:

Untitled

个人理解: url 中的不会被当做静态资源引入??(待验证)

原因:

webpack 资源处理的规则分为:

  • 相对路径:没有前缀的路径;
  • 带~的路径:相对根目录的路径

没看懂

// 相对路径:
'./assets/start.png'
'assets/start.png' // 没有前缀的路径,被webpack解析为相对路径

// 带~的路径 动态引入
'~@/assets/theme/start.png' // 被webpack解析为 require(src/assets/theme/start.png)  @在webpack 被resolve.alias配置成等价于 /src

// 相对根目录的路径
'/assets/start.png' //webpack不解析
1
2
3
4
5
6
7
8
9

样式 scoped 与样式穿透

scoped

作用**:防止全局同 css 类名样式的污染**。style 标签使用scoped  后, style 标签里的样式只会作用于该组件(第三方组件库如 Element-UI 内部组件就不会被影响),而不会渗透到子组件中(除了子组件的根节点)。

所以一个子组件的根节点会同时受其父组件的 scoped CSS 和子组件的 scoped CSS 的影响。这样设计是为了让父组件可以从布局的角度出发,调整其子组件根元素的样式。

实现原理

在 html 标签上添加data-v-xxxxxxxx属性,然后在 css 类名后添加属性选择器,即利用 css 类选择 + 属性选择器实现样式局部化:

// 原始文本
<template>
  <div class="parent">
    我是来自父组件的
  </div>
</template>

<style lang="scss" scoped>
  .parent {
    color: #333;
  }
</style>
1
2
3
4
5
6
7
8
9
10
11
12
// 转换后的
<template>
  <div data-v-2f3286d4 class="parent">  // 这里加了个data-v-....属性
    我是来自父组件的
  </div>
</template>

<style>
  .parent[data-v-2f3286d4] {       // 这里通过类+属性选择器来选择
    color: #333;
  }
</style>
1
2
3
4
5
6
7
8
9
10
11
12

父组件有 scoped,子组件无 scoped 的详细步骤:

  1. 父组件中的元素以及子组件中的根元素都会被加上data-v-xxxxxxxx 属性
  2. 将添加了scoped 的 style 中的样式编译为类名加属性选择器的样式(.classname[data-v-xxxxxxxx])
  3. 子组件中的样式因为未添加这样的属性而无法被选择器选择到,只能使用子组件中的原始的样式。

Untitled

通常的情况是父组件(我们写的)加 scoped,公共组件或第三方库不加 scoped

更多细节:Vue 中 scoped 属性浅析 - 韩帅 - 博客园 (cnblogs.com) (opens new window)

scoped 穿透

在 Vue 项目中,当我们引入第三方组件库时,有时需要局部修改第三方组件库中子元素的样式,而又不想去除 scoped 属性,以免造成组件之间的样式覆盖。这时我们可以通过特殊的方式穿透 scoped。有以下一些方法

>>>

如果项目使用的是 css 原生样式,可以直接使用 >>> 进行修改

外层 >>> 第三方组件{
        样式
}

/* 编译前 */
<style scoped>
.a >>> .b {
	/* ... */
}

/* 编译后 */
.a[data-v-f3f3eg9] .b {
	/* ... */
}
</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

/deep/

项目中如果使用了预处理器: scss 、sass、less 等, 操作符 >>> 可能会因为无法编译而报错。此时可以使用 /deep/ 进行穿透。

注意:vue-cli3 以上版本废弃该用法

外层 /deep/ 第三方组件 {
   样式
}
<style lang="scss" scoped>

/* 用法1 */
.a {
 /deep/ .b {
  /* ... */
 }
}

/* 用法2 */
.a /deep/ .b {
  /* ... */
 }
</style>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

::v-deep

如果使用了预处理器都可以使用 ::v-deep ,但现在(2022 年 5 月 9 日 21:27:32)貌似又不推荐了,在新的 vue3.0 单文件规范中 ::v-deep 写法已经被废弃了

<style lang="scss" scoped>

/* 用法1 */
.a{
 ::v-deep .b {
  /* ... */
 }
}

/* 用法2 */
.a ::v-deep .b {
  /* ... */
}

</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

:deep

现在用 ::v-deep 会报错,推荐使用 ****:deep(<inner-selector>) 。**报错如下:

[@vue/compiler-sfc]::v-deep usage as a combinator has been deprecated. Use :deep(<inner-selector>) instead.
1
:deep(.el-form-item) {
  margin-bottom: 23px;
  @height: 45px;
}
1
2
3
4

Reference

  • vue 样式穿透应用场景注意事项 - 简书 (jianshu.com) (opens new window)

  • vue 动态定义图片路径 - 小玲慕斯 - 博客园 (cnblogs.com) (opens new window)

上次更新: 2025/02/26, 08:57:57
项目开发配置
事件

← 项目开发配置 事件→

最近更新
01
RAIL
02-26
02
IOCTF
02-25
03
DGM
02-25
更多文章>
Theme by Vdoing | Copyright © 2022-2025 Geeks_Z | MIT License
京公网安备 11010802040735号 | 京ICP备2022029989号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式