整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

05《Vue 入门教程》Vue 动态样式绑定

05《Vue 入门教程》Vue 动态样式绑定

. 简介

本小节我们将介绍 Vue 中如何动态绑定样式。包括 Class 的绑定、内联样式 Style 的绑定。掌握样式绑定的多种形式是其中的重点难点。同学们可以在学完本小节之后对样式的绑定方式加以总结,再通过反复的练习来加深印象。

2. 木子解释

操作元素的 class 列表和内联样式是数据绑定的一个常见需求。因为它们都是属性,所以我们可以用 v-bind 处理它们:只需要通过表达式计算出字符串结果即可。不过,字符串拼接麻烦且易错。因此,在将 v-bind 用于 class 和 style 时,Vue.js 做了专门的增强。表达式结果的类型除了字符串之外,还可以是对象或数组。 ---- 官方定义

通过 v-bind 指令给 DOM 元素动态绑定 Class 和 Style,一般用于根据不同数据状态切换元素样式的场景下。

2.绑定元素的 Class

我们可以通过数组和对象的两种形式绑定元素的 Class。

2.1 对象

2.1.1 对象语法

通过传给 v-bind:class 一个对象,以动态地切换 class:

<div v-bind:class="{ show: isShow }"></div>

代码解释: 上面的语法表示 show 这个 class 存在与否将取决于数据属性 isShow 是否为真值。

具体示例:

实例演示

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>
<style>
  .hide {
    display: none;
  }
</style>
<body>
  <div id="app"> 
    <div v-bind:class="{hide: isHide}">Hello !</div>
  </div>
</body>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script>
 var vm=new Vue({
    el: '#app',
  data: {
    isHide: true
  },
})
//vm.isHide=true
</script>
</html>

"运行案例" 可查看在线运行效果

代码解释: HTML 代码第 2 行,我们给 div 绑定样式,当 isHide 为真值时, 其渲染结果为 <div class="hide"></div>,否则 <div></div>。 打开控制台,修改 vm.isHide 的值可以动态改变页面效果。

2.1.2 与普通的 class 属性共存

此外,v-bind:class 指令也可以与普通的 class 属性共存。 语法:<div class="defaultClass" v-bind:class="{ classA: isA,classB:isB }">

当有如下模板:

<div
  class="defaultClass"
  v-bind:class="{ show: isShow, 'text-danger': hasError }"
></div>

和如下 data:

data: {
  isShow: true,
  hasError: false
}

结果渲染为:

<div class="defaultClass active"></div>

代码解释:isShow 或者 hasError 变化时,class 列表将相应地更新。

例如,如果 hasError 的值为 trueisShow 的值为 true,class 列表将变为 "defaultClass show text-danger"

例如,如果 hasError 的值为 trueisShow 的值为 false,class 列表将变为 "defaultClass text-danger"

在之前介绍的案例中,我们将绑定的数据对象内联定义在模板里, 这样显得比较繁琐。其实,我们可以统一定义在一个 classObject 中:

实例演示

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>
<body>
  <div id="app"> 
    <div class="defaultClass" v-bind:class="classObject">Hello !</div>
  </div>
</body>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script>
 var vm=new Vue({
    el: '#app',
  data: {
    classObject: {
      show: true,
      'text-danger': false
    }
  },
})
</script>
</html>

"运行案例" 可查看在线运行效果

结果渲染为:

<div class="defaultClass show"></div>
代码块1

代码解释: HTML 代码中,我们首先给 div 一个固定样式 defaultClass, 然后通过 classObject 给 div 绑定样式。 JS 代码 第 6-9 行,我们定义了数据 classObject,它有两个属性:1. 属性 show,值为 true,2. 属性 text-danger,值为 false。所以,最后页面渲染的效果是:<div class="defaultClass show"></div>

2.1.3 利用计算属性绑定样式

<div v-bind:class="classObject"></div>

我们也可以在这里绑定一个返回对象的计算属性。这是一个常用且强大的模式:

实例演示

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>
<body>
  <div id="app"> 
    <div v-bind:class="classObject"></div>
  </div>
</body>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script>
 var vm=new Vue({
    el: '#app',
  computed: {
    classObject: function () {
      return {
        show: true,
        'text-danger': false
      }
    }
  }
})
</script>
</html>

"运行案例" 可查看在线运行效果

结果渲染为:

<div class="defaultClass show"></div>

代码解释: HTML 代码中,我们通过 classObject 给 div 绑定样式。 JS 代码 第 6-11 行,我们定义了计算属性 classObject,它返回一个对象,该对象有两个属性:1. 属性 show,值为 true,2. 属性 text-danger,值为 false。所以,最后页面渲染的效果是:<div class="show"></div>

2.2 数组语法

我们可以把一个数组传给 v-bind:class,以应用一个 class 列表:

实例演示

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>
<body>
  <div id="app"> 
    <div v-bind:class="[classA, classB]">Hello !</div>
  </div>
</body>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script>
 var vm=new Vue({
    el: '#app',
  data: {
    classA: 'classA',
    classB: 'classB1 classB2'
  },
})
</script>
</html>

运行案例点击 "运行案例" 可查看在线运行效果

渲染为:

<div class="classA classB1 classB2"></div>

代码解释: 在 HTML 代码中,我们通过数组给 div 绑定样式,数组中有 classA 和 classB 两个值。 在 JS 代码第 6-7 行定义了 classA 和 classB 两个字符串,它的格式和元素 class 的格式相同,不同的样式类之间以空格相隔。

如果你也想根据条件切换列表中的 class,可以用三元表达式:

<div v-bind:class="[isShow ? showClass : '', classB]"></div>

这样写将始终添加 classB 的样式,但是只有在 isShow 为真时才添加 showClass

不过,当有多个条件 class 时这样写有些繁琐。所以在数组语法中也可以使用对象的形式来表达数组中的某一项:

<div v-bind:class="[{ showClass: isShow }, classB]"></div>

代码解释: 在 HTML 中,div 绑定一个样式数组,数组第一项是一个对象表达式 { showClass: isShow }。当 isShow 为 true 时样式最终绑定为:<div v-bind:class="[showClass, classB]"></div>;当 isShow 为 false 时样式最终绑定为:<div v-bind:class="[classB]"></div>

3. 绑定内联样式

和 Class 的绑定一样,Style 的绑定同样可以通过数组和对象的两种形式。

3.1 对象语法

v-bind:style 的对象语法十分直观——看着非常像 CSS,但其实是一个 JavaScript 对象。CSS 属性名可以用驼峰式 (camelCase) 或短横线分隔 (kebab-case,记得用引号括起来) 来命名:

实例演示

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>
<body>
  <div id="app"> 
    <div v-bind:style="{ backgroundColor: backgroundColor, width: width + 'px' }"></div>
  </div>
</body>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script>
 var vm=new Vue({
    el: '#app',
  data: {
    backgroundColor: 'red',
    width: 300
  }
})
</script>
</html>

"运行案例" 可查看在线运行效果

渲染为:

<div style=" background-color:red;width: 300px"></div>

代码解释: 在 HTML 代码中,我们给 div 绑定 background-color 和 width 两个内联样式,它们的值在 data 中定义。

在模板中写较为复杂的表达式语法显得比较繁琐,通常直接绑定到一个样式对象更好,这会让模板显得更加清晰:

实例演示

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>
<body>
  <div id="app"> 
    <div v-bind:style="styleObject"></div>
  </div>
</body>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script>
 var vm=new Vue({
    el: '#app',
  data: {
    styleObject: {
      "background-color": 'red',
      width: '300px'
    }
  },
})
</script>
</html>

"运行案例" 可查看在线运行效果

渲染为:

<div style="background-color:red;width: 300px"></div>
代码块1

代码解释: 在 HTML 代码中,我们给 div 绑定数据 styleObject,它们的值在 data 中定义。

3.2 数组语法

v-bind:style 的数组语法可以将多个样式对象应用到同一个元素上:

实例演示

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>
<body>
  <div id="app"> 
    <div v-bind:style="[stylesA, stylesB]"></div>
  </div>
</body>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script>
 var vm=new Vue({
    el: '#app',
  data: {
    stylesA: {
      "background-color": 'red',
      width: '300px'
    },
    stylesB: {
      color: '#fff',
      height: '300px'
    }
  }
})
</script>
</html>

"运行案例" 可查看在线运行效果

渲染为:

<div style="background-color:red;width: 300px;color:#fff;height:300px"></div>

4. 小结

本小节我们学习了如何通过v-bind来动态绑定样式。主要有以下知识点:

  • 通过 v-bind:class 动态绑定元素的 Class;
  • v-bind:style 动态绑定元素的内联样式;
  • 如果通过数组和对象的形式给 v-bind:class 和 v-bind:style 赋值。


本说明:


涉及到css样式属性的都采用,驼峰命名

什么是驼峰命名? 就是你看到 “-” 就去掉,然后“-” 后面的字母大写

例如:background-color 就写成:backgroundColor对象方式

特点: 首字母永远小写;


方式1:style方式绑定(6中方法)

  • 1、对象方式
    • 例如: :style="{ backgroundColor: activeColor, fontSize: bitfontSize + 'px' }"
  • 2、数组方式
    • 例如::style="[baseStyles, overridingStyles]"
  • 3 简单三目运算
    例如::style="[{backgroundColor:(index==0?conFontColor:'#000')},{fontSize:'20px'}]"
  • 4 多值兼容
    例如: :style="{ display: ['-webkit-box', '-ms-flexbox', 'flex'] }" 浏览器自己选择
  • 5 data对象绑定
    例如::style="styleObject" 其中styleObject在data中定义成一个对象
  • 6 css变量方式(本质还是对象方式)
    例如::style="{ --width: widthvalue}" 在css 中 使用 width: var(--width);

方法2:class方式绑定

  • 7 数组方式
    例如: :class="[active: isActive ]" 这个是官方推荐,表示isActive==true 就加入active这个样式
  • 8 三目运算(其实也是数组方式)
    例如::class="[activeStyle==index ? 'active':'']"

、实例与数据

Vue.js 应用的创建很简单,通过构造函数 Vue 就可以创建一个 Vue 的根实例,并启动 Vue 应用:

var app=new Vue ({
 //选项
})

变量 app 就代表了这个 Vue 实例。事实上,几乎所有的代码都是一个对象,写入 Vue 实例的选项内的。首先,必不可少的一个选项就是 el 。el 用于指定一个页面已存在的 DOM 元素来挂载 Vue 实例,它可以是 HTMLElement ,也可以是 CSS 选择器,比如:

<div id="app"></div>
var app=new Vue({
 el: document.getElementById('app') // 或者 el:'#app'
})

挂载成功后,可以通过 app.$el 来访问该元素。Vue 提供了很多常用的实例属性与方法,都以 $ 开头,比如 $el 。

 <div id="app">
 <input type="text" v-model="name" placeholder="请输入你的名字">
 <h1>Vue.js 最核心功能:数据的双向绑定 —— {{ name }}</h1>
 </div>
 <script>
 var app=new Vue ({
 el: '#app',
 data: {
 name: ''
 }
 })
 </script>

上述代码,在 input 标签上,有一个 v-model 的指令,它的值对应于创建的 Vue 实例的 data 选项中的 name 字段,这就是 Vue 的数据绑定。通过 Vue 实例的 data 选项,可以声明应用内需要双向绑定的数据。建议所有会用到的数据都预先在 data 内声明,这样不至于将数据散落在业务逻辑中,难以维护。

Vue 实例本身也代理了 data 对象里的所有属性,故可以这样访问:

 var app=new Vue({
 el: "#app",
 data: {
 a: 1
 }
 })
 sonsole.log(app.a); //1

除了显式地声明数据外,也可以指向一个已有的变量,并且它们之间默认建立了双向绑定,当修改其中任意一个时,另一个也会一起变化:

 var myData={
 a: 1
 }
 var app=new Vue({
 el: "#app",
 data: {
 a: myData
 }
 })
 sonsole.log(app.a); // 1
 // 修改属性,原数据也会随之修改
 app.a=2;
 console.log(myData.a); // 2
 // 反之,修改原数据,Vue 属性也会修改
 myData.a=3;
 console.log(app.a); // 3

二、生命周期

每个 Vue 实例创建时,都会经历一系列的初始化过程,同时也会调用相应的生命周期钩子,我们可以利用这些钩子,在合适的时机执行我们的业务逻辑。如果你使用过 jQuery ,一定知道它的 ready() 方法,比如:

 $(document).ready(function() {
 // DOM 加载完后,会执行这里的代码
 });

Vue 的生命周期钩子与之类似,比较常用的有:

  • created : 实例创建完成后调用,此阶段完成了数据的观测等,但尚未挂载,$el 还不可用。需要初始化处理一些数据时会比较有用。
  • mounted : el 挂载到实例上后调用,一般我们的第一个业务逻辑会在这里开始。
  • beforeDestroy : 实例销毁之前调用。主要解绑一些使用 addEventListener 监听的事件等。

这些钩子与 el 和 data 类似,也是作为选项写入 Vue 实例内,并且钩子的 this 指向的是调用它的 Vue 实例:

 var app - new Vue({
 el: '#app',
 data: {
 a: 2
 },
 created: function () {
 console.log(this.a); // 2
 }
 mounted: function () {
 console.log(this.$el); // <div id="app"></div>
 }
 })

三、插值与表达式

使用双大括号( Mustache 语法 )“ {{ }} ” 是最基本的文本插值方法,它会自动将我们双向绑定的数据实时显示出来,例如实时显示当前时间,每秒更新:

 <script>
 var app=new Vue ({
 el: '#app',
 data: {
 date: new Date()
 },
 mounted: function () {
 var _this=this; // 声明一个变量指向 Vue 实例 this, 保证作用域一致
 this.timer=setInterval(function() {
 _this.date=new Date(); // 修改数据 date
 }, 1000); // 1秒
 },
 beforeDestroy: function () {
 if (this.timer) {
 clearInterval(this.timer); // 在 Vue 实例销毁前,清除我们的定时器
 }
 }
 })
 </script>

双大括号里的内容会被替换为 data 选项中 date 的值,通过任何方法修改数据 data 选项中 date 的值,双大括号的内容都会被实时替换。这里的 {{ date }} 输出的是浏览器默认的时间格式,并非格式化的时间( 2018-10-07 10:05:59 ),所以需要注意时区。有多种方法可以对时间格式化,比如赋值前先使用自定义的函数处理。当然,Vue 的过滤器 ( filter )或计算属性 ( computed )也可以实现。

如果有时候就是想输出 HTML,而不是将数据解释后的纯文本,可以使用 v-html:

 <div id="app">
 <span v-html="link"></span>
 </div>
 <script>
 var app=new Vue({
 el: '#app',
 data: {
 link: '<a href="https://www.baidu.com/">百度</a>'
 }
 })
 </script>

link 的内容将会被渲染为一个具有点击功能的 a 标签,而不是纯文本。但是要注意,如果将用户产生的内容使用 v-html 输出后,有可能导致 XSS 攻击(跨站脚本攻击),所以要在服务端对用户提交的内容进行处理,一般可将尖括号 “<>” 转义。

如果想显示 {{ }}标签,而不进行替换,使用 v-pre 即可跳过这个元素和它的子元素的编译过程,例如:

<span v-pre>{{ 这里会显示双花括号,内容不会被编译 }}</span>

在 {{ }} 中,除了简单的绑定属性值外,还可以使用 JavaScript 表达式进行简单的运算、三元运算等,例如:

 <div id="app">
 {{ num / 100 }}
 {{ areYouOK ? '确定' : '取消' }}
 {{ text.split(',').reverse().join(',') }}
 </div>
 <script>
 var app=new Vue({
 el: '#app',
 data: {
 num: 100,
 areYouOK:false,
 text: '123,456'
 }
 })
 </script>

显示结果依次为:1、取消、456,123 。

Vue.js 只支持单个表达式,不支持语句和流控制。另外,在表达式中,不能使用用户自定义的全局变量,只能使用 Vue 白名单内的全局变量,例如 Math 和 Date 。以下是一些无效的示例:

 <!-- 这是语句,不是表达式 -->
 {{ var text='123,456' }}
 <!-- 不能使用流控制,要使用三目运算 -->
 {{ if (areYouOK) return msg }}

四、过滤器

Vue.js 支持在 {{ }} 插值的尾部添加一个管道符“ ( | ) ” 对数据进行过滤,经常用于格式化文本,比如字母全部大写、货币千位使用逗号分隔等。过滤的规则是自定义的,通过给 Vue 实例添加选项 filters 来设置,例如可以对时间进行格式化处理,实时显示当前时间:

 <div id="app">
 {{ date | formatDate }}
 </div>
 <script>
 
 // 在月份、日期、小时等小于 10 时前面补 0
 var padDate=function(value) {
 return value < 10 ? '0' + value : value;
 };
 var app=new Vue({
 el: "#app",
 data: {
 date: new Date()
 },
 filters: {
 formatDate: function (value) { // 这里的 value 就是需要过滤的数据
 var date=new Date(value);
 var yaer=date.getFullYear();
 var month=padDate(date.getMonth() + 1);
 var day=padDate(date.getDate());
 var hours=padDate(date.getHours());
 var minutes=padDate(date.getMinutes());
 var seconds=padDate(date.getSeconds());
 // 整理返回格式化后的日期
 return yaer + '-' + month + '-' + day + ' ' + hours + ':' + minutes + ':' + seconds;
 }
 },
 mounted: function () {
 var _this=this; // 声明一个变量指向 Vue 实例 this , 保证作用域一致
 this.timer=setInterval({
 _this.date=new Date(); // 修改数据 date
 }, 1000);
 },
 beforeDestroy: function() {
 if (this.timer) {
 clearInterval(this.timer); // 在 Vue 实例销毁前,清除我们的定时器
 }
 }
 })
 </script>

过滤器也可以串联,而且可以接收参数,例如:

 <!-- 串联 -->
 {{ message | filterA | filterB }}
 <!-- 接收参数 -->
 {{ message | filterA('arg1', 'arg2') }}

过滤器应当用于处理简单的文本转换,如果要实现更为复杂的数据变换,应该使用计算属性。