本小节我们将介绍 Vue 中如何动态绑定样式。包括 Class 的绑定、内联样式 Style 的绑定。掌握样式绑定的多种形式是其中的重点难点。同学们可以在学完本小节之后对样式的绑定方式加以总结,再通过反复的练习来加深印象。
操作元素的 class 列表和内联样式是数据绑定的一个常见需求。因为它们都是属性,所以我们可以用 v-bind 处理它们:只需要通过表达式计算出字符串结果即可。不过,字符串拼接麻烦且易错。因此,在将 v-bind 用于 class 和 style 时,Vue.js 做了专门的增强。表达式结果的类型除了字符串之外,还可以是对象或数组。 ---- 官方定义
通过 v-bind 指令给 DOM 元素动态绑定 Class 和 Style,一般用于根据不同数据状态切换元素样式的场景下。
我们可以通过数组和对象的两种形式绑定元素的 Class。
通过传给 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 的值可以动态改变页面效果。
此外,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 的值为 true,isShow 的值为 true,class 列表将变为 "defaultClass show text-danger"。
例如,如果 hasError 的值为 true,isShow 的值为 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>
<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>
我们可以把一个数组传给 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>;
和 Class 的绑定一样,Style 的绑定同样可以通过数组和对象的两种形式。
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 中定义。
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>
本小节我们学习了如何通过v-bind来动态绑定样式。主要有以下知识点:
本说明:
涉及到css样式属性的都采用,驼峰命名
什么是驼峰命名? 就是你看到 “-” 就去掉,然后“-” 后面的字母大写
例如:background-color 就写成:backgroundColor对象方式
特点: 首字母永远小写;
、实例与数据
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 的生命周期钩子与之类似,比较常用的有:
这些钩子与 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') }}
过滤器应当用于处理简单的文本转换,如果要实现更为复杂的数据变换,应该使用计算属性。
*请认真填写需求信息,我们会在24小时内与您取得联系。