发布时间:2023-11-29 12:30
Vue 中的动态样式分为动态绑定 class 和动态绑定 style。
class样式的动态添加,分为以对象方式添加和以数组方式添加两种。
语法
{key它就是样式名称:布尔值【true生效,false不生效】}
案例
<style>
.active {
color: red;
}
</style>
<div id="app">
<!-- v-bind动态绑定的简写,表示动态绑定数据源中的titleClass -->
<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>
如果我们想要在触发点击事件的时候,动态的追加新的属性,该怎么做?
我们一共有三种方案,分别是直接在点击事件中追加新属性、通过改变titleClass
的地址来追加、通过 Vue 中的方法追加。
我们先来看第一种方案,通过点击事件直接追加新属性:
<style>
.active {
color: red;
}
.font30 {
font-size: 30px;
}
</style>
<div id="app">
<!-- v-bind动态绑定的简写,表示动态绑定数据源中的titleClass -->
<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>
注意,这种方案是有很大弊端的:
在
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">
<!-- v-bind动态绑定的简写,表示动态绑定数据源中的titleClass -->
<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>
上面列举了三种通过改变地址达到追加新属性效果的方法,在这里着重说一下后两种方法。
方法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">
<!-- v-bind动态绑定的简写,表示动态绑定数据源中的titleClass -->
<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>
小结
从上面的案例中,我们可以看出使用动态绑定 Class 的方式添加动态样式时,这种用对象方式添加的方法一般用于开关显示的样式,不太适合添加新的属性样式。
学习了动态绑定样式的方式后,我们可以将这种方式应用到 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}">aaa</li>
<li @click="setNav('b')" :class="{active:b}">bbb</li>
<li @click="setNav('c')" :class="{active:c}">ccc</li>
</ul>
<ul>
<li v-if="a">11111</li>
<li v-if="b">22222</li>
<li v-if="c">33333</li>
</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>
概述:
以数组方式添加 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>
注意:在 Vue 中调用 push unshift shift pop splice sort reverse 时都会让视图更新。
动态绑定style,也分为以对象方式添加和以数组方式添加两种。
<div id="app">
<!-- style样式的动态添加,对象和数组方式 -->
<!-- 对象 -->
<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>
参考文章:
https://blog.csdn.net/reembarkation/article/details/125515876
https://blog.csdn.net/qq_30100043/article/details/53422657
手把手教你Win系统配置深度学习(GPU)环境: Anaconda3+CUDA+cuDNN+pytorch
STM32蓝牙控制循迹避障小车源代码——3.舵机、超声波测距模块
还在发愁写API文档?推荐一款阿里腾讯都在用的API管理神器!
【kaldi】chain-model的TCP server部署
基于Kubernetes的容器编排和持续交付的Choerodon平台的后端环境搭建
servlet和java区别_JavaWeb中的jsp和servlet的区别
使用 Koa + TS + ESLlint 搭建node服务器的过程详解