• Vue动态样式绑定



    Vue 中的动态样式分为动态绑定 class 和动态绑定 style。

    1. 动态绑定class

    class样式的动态添加,分为以对象方式添加和以数组方式添加两种。

    1.1 以对象方式添加

    • 语法

      {key它就是样式名称:布尔值【true生效,false不生效】}

    • 案例

      <style>
          .active {
              color: red;
          }
      style>
      
      <div id="app">
          
          <div :class="titleClass">我是一个标题div>
          <button @click="addClass">添加样式button>
      div>
      <script>
          const vm = new Vue({
              el: '#app',
              data: {  
                  // 可以添加多个样式,用逗号隔开
                  titleClass: { active: false }
              },
              methods: {
                  addClass() {
                      // 点击切换
                      this.titleClass.active = !this.titleClass.active
                  }
              }
          })
      script>
      
      • 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

      在这里插入图片描述

      如果我们想要在触发点击事件的时候,动态的追加新的属性,该怎么做?

      我们一共有三种方案,分别是直接在点击事件中追加新属性、通过改变titleClass的地址来追加、通过 Vue 中的方法追加。

      我们先来看第一种方案,通过点击事件直接追加新属性:

      <style>
          .active {
              color: red;
          }
      
          .font30 {
              font-size: 30px;
          }
      style>
      
      <div id="app">
          
          <div :class="titleClass">我是一个标题div>
          <button @click="addClass">添加样式button>
      div>
      
      <script>
          const vm = new Vue({
              el: '#app',
              data: {
                  titleClass: { active: false },
                  // titleStyle: []
              },
              methods: {
                  addClass() {
                      this.titleClass.active = true//这里执行的时候会刷新数据,会顺带执行了下一句
                      this.titleClass.font30 = true//注意,把上一句注释,只执行这一句的时候,样式不会生效,因为这里是是新加的属性,并没有被劫持,不会被动态添加
                  }
              }
          })
      script>
      
      • 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

      在这里插入图片描述

      注意,这种方案是有很大弊端的:

      addClass方法中,如果把this.titleClass.active = true这一句注释,直接执行它的下一句this.titleClass.font30 = true,则点击添加样式时,div 的样式不会发生任何改变。

      这是因为font30样式并没有被劫持(这个属性并没有写在数据源中),并不能动态地和 div 绑定,上述代码之所以能够成功执行该样式,是因为active样式和 div 是动态绑定的,当active的布尔值发生变化,引发视图更新时,会顺带追加font30的样式。所以当this.titleClass.active = true这一句注释,只执行它的下一句this.titleClass.font30 = true,虽然数据发生了改变,但因为该数据不是响应式的,不会引发视图更新,所以此时视图并不会发生改变。

      第二种方案:通过改变titleClass的地址来追加:

      <style>
          .active {
              color: red;
          }
      
          .font30 {
              font-size: 30px;
          }
      style>
      <div id="app">
          
          <div :class="titleClass">我是一个标题div>
          <button @click="addClass">添加样式button>
      div>
      <script>
          const vm = new Vue({
              el: '#app',
              data: {
                  titleClass: { active: false },
              },
              methods: {
                  addClass() {
                      // 方法1:直接改变地址
                      // 改变地址,也会动态添加上字体属性
                      // this.titleClass = { ...this.titleClass, font30: true }
      
                      // 方法2:使用JSON.stringify和JSON.parse拷贝一个新对象出来
                      // 改变地址 JSON.stringify(this.titleClass):将某个对象转换成 JSON 字符串形式
                      // JSON.parse:将数据转换为 JavaScript 对象。
                      // let titleClass = JSON.parse(JSON.stringify(this.titleClass))
                      // titleClass.font30 = true
                      // this.titleClass = titleClass
      
      
                      // 方法3:使用Object.assign()方法
                      // Object.assign()是对象的静态方法,可以用来复制对象的可枚举属性到目标对象,第一次是深复制
                      this.titleClass = Object.assign({}, this.titleClass, { font30: true })
                  }
              }
          })
      script>
      
      • 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

      在这里插入图片描述

      上面列举了三种通过改变地址达到追加新属性效果的方法,在这里着重说一下后两种方法。

      方法2,使用JSON.stringify和JSON.parse拷贝一个新对象出来的原理是这样的,如果我们有一个复杂的对象,想要复制到另外一处,就需要对该对象进行复制操作。因为 js 对象数据是引用数据类型。如果只是简单的使用=复制对象,会修改掉原来的对象(因为他们真是保存的数据是一个地址,两个变量都指向都一个地址)。

      所以如果想要真实拷贝一份对象数据,且不能影响原来对象,则可以将原对象进行JSON.stringify操作,将该对象转换为 json 字符串,然后再新定义一个对象,使用JSON.parse转换该 json 字符串为对象。这样我们新得到的对象就是一份和原对象无关联的对象了,可以任意使用而不会影响原对象。

      方法3,Object.assign()方法用于对象的合并,将源对象( source )的所有可枚举属性,复制到目标对象( target )。

      文末附有参考文章链接,文章中较好地解释了这两种方法的实现原理。

      在 Vue2 中,动态地给一个对象增加属性太麻烦了,这是因为 Vue2 是使用Object.defineProperty方法进行数据劫持的。这种方法在初始化的时候就已经将数据源中的数据进行了劫持,而新增的属性没有被劫持。而而 Vue3 中就没有这个问题,Vue3 中劫持的是一个对象,我们只要给对象增加属性,视图就可以发生改变。

      由于上面的原因,Vue2 中提供了一种简便的方法,让我们能够动态地追加属性,就是$set方法。

      $set方法

      语法:

      this.$set(给哪个对象添加属性,添加什么属性,该属性的值是什么)

      案例:

      <style>
          .active {
              color: red;
          }
      
          .font30 {
              font-size: 30px;
          }
      style>
      <div id="app">
          
          <div :class="titleClass">我是一个标题div>
          <button @click="addClass">添加样式button>
      div>
      <script>
          const vm = new Vue({
              el: '#app',
              data: {
                  titleClass: { active: false },
              },
              methods: {
                  addClass() {
                      // Vue方法
                      // 动态给对象添加成员属性(Vue中的方法)
                      this.$set(this.titleClass, 'font30', true)
                  }
              }
          })
      script>
      
      • 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

      在这里插入图片描述

    • 小结

      从上面的案例中,我们可以看出使用动态绑定 Class 的方式添加动态样式时,这种用对象方式添加的方法一般用于开关显示的样式,不太适合添加新的属性样式。

      学习了动态绑定样式的方式后,我们可以将这种方式应用到 tab 切换当中。

    1.2 tab 切换案例

    DOCTYPE html>
    <html lang="en">
    
        <head>
            <meta charset="UTF-8">
            <meta http-equiv="X-UA-Compatible" content="IE=edge">
            <meta name="viewport" content="width=device-width, initial-scale=1.0">
            <title>vue学习使用title>
            <script src="./js/vue.js">script>
            <style>
                .active {
                    color: red;
                    transition: all 2s;
                }
            style>
        head>
    
        <body>
            <div id="app">
                <ul>
                    <li @click="setNav('a')" :class="{active:a}">aaali>
                    <li @click="setNav('b')" :class="{active:b}">bbbli>
                    <li @click="setNav('c')" :class="{active:c}">cccli>
                ul>
                <ul>
                    <li v-if="a">11111li>
                    <li v-if="b">22222li>
                    <li v-if="c">33333li>
                ul>
            div>
    
            <script>
                const vm = new Vue({
                    el: '#app',
                    data: {
                        a: true,
                        b: false,
                        c: false
                    },
                    methods: {
                        setNav(attrName) {
                            this.a = false
                            this.b = false
                            this.c = false
                            this[attrName] = true
                        }
                    }
                })
            script>
    
        body>
    
    html>
    
    • 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

    在这里插入图片描述

    1.3 以数组方式添加

    概述:

    以数组方式添加 class 动态绑定,更适合追加新的属性。也就是说,一般对于追加新样式,我们使用数组方式进行动态绑定。

    案例:

    <style>
        .active {
            color: red;
        }
    
        .font30 {
            font-size: 30px;
        }
    style>
    
    <div id="app">
        
        <div :class="titleStyle">我是一个标题div>
        <button @click="addStyle">添加样式button>
    div>
    
    <script>
        const vm = new Vue({
            el: '#app',
            data: {
                // titleClass: { active: false },
                titleStyle: []
            },
            methods: {
                addStyle() {
                    // 给数组添加元素,元素就是样式名称,这样它会就追加样式
                    // push unshift shift pop splice sort reverse 调用时都会让视图更新
                    this.titleStyle.push('active')
                    this.titleStyle.push('font30')
                }
            }
        })
    script>
    
    • 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

    在这里插入图片描述

    注意:在 Vue 中调用 push unshift shift pop splice sort reverse 时都会让视图更新。

    2. 动态绑定style

    动态绑定style,也分为以对象方式添加和以数组方式添加两种。

    <div id="app">
    
        
    
        
        <div :style="{color:'blue',fontSize:'30px'}">我是一个标题div>
    
        
        <div :style="[{color:'red'},{fontSize:'30px'}]">我是一个标题div>
    div>
    
    <script>
        const vm = new Vue({
            el: '#app',
            data: {
            },
            methods: {
            }
        })
    script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    在这里插入图片描述


    参考文章:

    https://blog.csdn.net/reembarkation/article/details/125515876

    https://blog.csdn.net/qq_30100043/article/details/53422657

  • 相关阅读:
    基于android的轻餐饮点餐APP(ssm+uinapp+Mysql)
    代码随想录算法训练营DAY37|C++贪心算法Part.6|738.单调递增的数字、968.监控二叉树、贪心算法总结
    华为nova10Pro和华为nova9Pro有哪些区别 哪个性能更强
    【初阶数据结构】单链表(C语言实现+动图演示)
    NUCLEO-L552ZE SWD外部接口定义
    C#,深度学习OpenCV目标检测级联分类器数据集的自主制作方法与《层级分类器集成生成环境》源代码
    【开源】基于Vue和SpringBoot的智能教学资源库系统
    Python中的变量与注释
    一款优秀的智慧社区系统应具备哪些功能
    YOLO改进系列之注意力机制(GatherExcite模型介绍)
  • 原文地址:https://blog.csdn.net/weixin_45605541/article/details/126674565