目录
1.页面样式绑定:
1.概述:
页面样式绑定在 Vue 中是一种将样式与数据动态关联起来的方式,使得页面的样式可以根据数据的变化而自动更新。
2.绑定方式:
1.通过类名绑定:
1.通过动态类名绑定:(:class)
plain
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
<!--准备样式 -->
//基础样式:宽400,长100,实线黑色边框(宽1)
.basic {
width: 400px;
height: 100px;
border: 1px solid black;
}
//容器1样式:实线红色边框,宽4,容器背景渐变色
.box1 {
border: 4px solid red;
/*background-color: rgba(255, 255, 0, 0.6);*/
background: linear-gradient(30deg, yellow, pink, orange, yellow);
}
//容器2样式:虚线边框,宽4,边框颜色rgb,容器背景灰色
.box2 {
border: 4px dashed rgb(2, 197, 2);
background-color: gray;
}
//容器3样式:容器背景蓝色
.box3 {
background-color: skyblue;
}
//容器4样式:容器背景黄绿色
.box4 {
background-color: yellowgreen;
}
// //容器5样式:字体大小30,为字体添加阴影效果
.box5 {
font-size: 30px;
text-shadow: 2px 2px 10px red;
}
//容器6样式:设置边框圆角
.box6 {
border-radius: 20px;
}
</style>
</head>
<body>
<!--2.准备一个容器-->
<div id="root">
<div class="basic" :class="classStr">
{{name}}
</div>
</div>
<!--1.引入Vue js 文件-->
<script src="vue/vue.js"></script>
<script type="text/javascript">
//3.创建Vue对象
let vm = new Vue({
data() {
return {
name: '猿究院',
classStr: 'box2',
}
}
}).$mount("#root");
</script>
</body>
</html>
上面案例中我们定义了一些样式,并在div子容器中通过指令语法动态绑定了data属性中的对应属性,实现了将data属性值对应的容器样式动态的绑定到了div子容器中(注意在div子容器绑定样式时有两个类名,实际上他们对应的样式效果是叠加的)实际样式效果如下所示:

2.通过类名数组绑定:
plain
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
<!--准备样式 -->
//基础样式:宽400,长100,实线黑色边框(宽1)
.basic {
width: 400px;
height: 100px;
border: 1px solid black;
}
//容器1样式:实线红色边框,宽4,容器背景渐变色
.box1 {
border: 4px solid red;
/*background-color: rgba(255, 255, 0, 0.6);*/
background: linear-gradient(30deg, yellow, pink, orange, yellow);
}
//容器2样式:虚线边框,宽4,边框颜色rgb,容器背景灰色
.box2 {
border: 4px dashed rgb(2, 197, 2);
background-color: gray;
}
//容器3样式:容器背景蓝色
.box3 {
background-color: skyblue;
}
//容器4样式:容器背景黄绿色
.box4 {
background-color: yellowgreen;
}
// //容器5样式:字体大小30,为字体添加阴影效果
.box5 {
font-size: 30px;
text-shadow: 2px 2px 10px red;
}
//容器6样式:设置边框圆角
.box6 {
border-radius: 20px;
}
</style>
</head>
<body>
<!--2.准备一个容器-->
<div id="root">
<div class="basic" :class="classArr">
{{name}}
</div>
</div>
<!--1.引入Vue js 文件-->
<script src="vue/vue.js"></script>
<script type="text/javascript">
//3.创建Vue对象
let vm = new Vue({
data() {
return {
name: '猿究院',
classArr: ['box4', 'box5', 'box6'],
}
}
}).$mount("#root");
</script>
</body>
</html>
上面案例中通过类名数组动态绑定多个类对应的容器样式,再将这些容器样式进行叠加后绑定到div子容器中,最终div子容器的样式效果如下所示:

3.通过类名对象进行绑定:
plain
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
<!--准备样式 -->
//基础样式:宽400,长100,实线黑色边框(宽1)
.basic {
width: 400px;
height: 100px;
border: 1px solid black;
}
//容器1样式:实线红色边框,宽4,容器背景渐变色
.box1 {
border: 4px solid red;
/*background-color: rgba(255, 255, 0, 0.6);*/
background: linear-gradient(30deg, yellow, pink, orange, yellow);
}
//容器2样式:虚线边框,宽4,边框颜色rgb,容器背景灰色
.box2 {
border: 4px dashed rgb(2, 197, 2);
background-color: gray;
}
//容器3样式:容器背景蓝色
.box3 {
background-color: skyblue;
}
//容器4样式:容器背景黄绿色
.box4 {
background-color: yellowgreen;
}
// //容器5样式:字体大小30,为字体添加阴影效果
.box5 {
font-size: 30px;
text-shadow: 2px 2px 10px red;
}
//容器6样式:设置边框圆角
.box6 {
border-radius: 20px;
}
</style>
</head>
<body>
<!--2.准备一个容器-->
<div id="root">
<div class="basic" :class="classObject">
{{name}}
</div>
</div>
<!--1.引入Vue js 文件-->
<script src="vue/vue.js"></script>
<script type="text/javascript">
//3.创建Vue对象
let vm = new Vue({
data() {
return {
name: '猿究院',
classObject: {
box1: true,
box5: true,
box3: false
},
}
}
}).$mount("#root");
</script>
</body>
</html>
在此案例中我们通过类对象进行样式绑定,在data中定义一个ClassObiect的对象,此对象的每个属性都表示一个容器样式的容器名,值为布尔值,true表示启用该容器样式,false则表示不用,最终div子容器样式效果如下所示:

2.内联样式绑定:(:sytle)
1.通过样式对象语法绑定:
plain
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
<!--准备样式 -->
//基础样式:宽400,长100,实线黑色边框(宽1)
.basic {
width: 400px;
height: 100px;
border: 1px solid black;
}
//容器1样式:实线红色边框,宽4,容器背景渐变色
.box1 {
border: 4px solid red;
/*background-color: rgba(255, 255, 0, 0.6);*/
background: linear-gradient(30deg, yellow, pink, orange, yellow);
}
//容器2样式:虚线边框,宽4,边框颜色rgb,容器背景灰色
.box2 {
border: 4px dashed rgb(2, 197, 2);
background-color: gray;
}
//容器3样式:容器背景蓝色
.box3 {
background-color: skyblue;
}
//容器4样式:容器背景黄绿色
.box4 {
background-color: yellowgreen;
}
// //容器5样式:字体大小30,为字体添加阴影效果
.box5 {
font-size: 30px;
text-shadow: 2px 2px 10px red;
}
//容器6样式:设置边框圆角
.box6 {
border-radius: 20px;
}
</style>
</head>
<body>
<!--2.准备一个容器-->
<div id="root">
<div class="basic" :style="styleObject">
{{name}}
</div>
</div>
<!--1.引入Vue js 文件-->
<script src="vue/vue.js"></script>
<script type="text/javascript">
//3.创建Vue对象
let vm = new Vue({
data() {
return {
name: '猿究院',
styleObject: {
fontSize: '40px',
color: 'red'
},
}
}
}).$mount("#root");
</script>
</body>
</html>
说明:此时通过内联式绑定样式效果,在data的styleObject对象中就不能在写容器样式对应的容器名了,而要写具体的样式效果。并且由于内联式级别高于类选择器,因此basic的样式效果会被覆盖。此时div子容器的样式效果如下图所示:

2.通过样式数组语法绑定:
plain
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
<!--准备样式 -->
//基础样式:宽400,长100,实线黑色边框(宽1)
.basic {
width: 400px;
height: 100px;
border: 1px solid black;
}
//容器1样式:实线红色边框,宽4,容器背景渐变色
.box1 {
border: 4px solid red;
/*background-color: rgba(255, 255, 0, 0.6);*/
background: linear-gradient(30deg, yellow, pink, orange, yellow);
}
//容器2样式:虚线边框,宽4,边框颜色rgb,容器背景灰色
.box2 {
border: 4px dashed rgb(2, 197, 2);
background-color: gray;
}
//容器3样式:容器背景蓝色
.box3 {
background-color: skyblue;
}
//容器4样式:容器背景黄绿色
.box4 {
background-color: yellowgreen;
}
// //容器5样式:字体大小30,为字体添加阴影效果
.box5 {
font-size: 30px;
text-shadow: 2px 2px 10px red;
}
//容器6样式:设置边框圆角
.box6 {
border-radius: 20px;
}
</style>
</head>
<body>
<!--2.准备一个容器-->
<div id="root">
<div class="basic" :style="styleArr">
{{name}}
</div>
</div>
<!--1.引入Vue js 文件-->
<script src="vue/vue.js"></script>
<script type="text/javascript">
//3.创建Vue对象
let vm = new Vue({
data() {
return {
name: '猿究院',
styleArr: [
{
fontSize: '40px',
color: 'blue'
},
{
backgroundColor: 'yellowgreen'
}
]
}
}
}).$mount("#root");
</script>
</body>
</html>
说明:此时通过样式数组进行样式效果绑定,将样式效果以数组的形式进行定义,最终叠加绑定到div子容器上,注意:basic样式仍会被覆盖;

2.条件渲染:
1.概述:
在vue中通过v-if,v-else-if,v-else等语句进行条件判断当前内容是否执行渲染展示
2.语法:
plain
v-if='条件1'.....
v-else-if='条件2'....
v-else-if='条件3'....
......
v-else ........
3.使用方法:
plain
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--2.准备一个容器-->
<div id="root">
<h2>当前count的值是:{{count}}</h2>
<button @click="count++">点击count++</button>
<div v-if="count==1">v-if....</div>
<div v-else-if="count==2">v-else-if ....</div>
<div v-else-if="count==3">v-else-if ....</div>
<div v-else>v-else ....</div>
</div>
<!--1.引入Vue js 文件-->
<script src="vue/vue.js"></script>
<script type="text/javascript">
//3.创建Vue对象
let vm = new Vue({
data() {
return {
count: 0
}
}
}).$mount("#root");
</script>
</body>
</html>
说明:上述案例中通过v-if,v-else-if,v-else对变量count的值进行判断,根据count的不同值,在页面渲染展示不同的内容



4.注意事项;
v-if 指令会移除当条件不满足时页面的DOM元素;
v-else-if指令执行过程中不能被其他业务中断,否则中断之后的逻辑判断不再执行;
v-if指令适合执行内容隐藏-显示切换频率不高的场景,如果切换频率较高,则应使用v-show指令,因为v-show指令不会删除不满足条件的DOM元素,而是会将其通过CSS隐藏起来,因此效率比较高;
3.列表渲染
1.概述:
列表渲染主要是通过v-for指令对数组,对象,字符串等数据进行遍历;
2.语法:
plain
v-for="(item,index) in 遍历对象" :key='对象的键'
3.使用:
1.遍历数组:
plain
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--2.准备一个容器-->
<div id="root">
<!-- 遍历数组 -->
<ul>
<!-- v-for :key-->
<!-- item 循环的每一个值,index 下标 -->
<!-- <li v-for="item in persons">-->
<li v-for="(item,index) in persons" :key="item.id">
{{index}}-{{item.name}}-{{item.age}}
</li>
</ul>
</div>
<!--1.引入Vue js 文件-->
<script src="vue/vue.js"></script>
<script type="text/javascript">
//3.创建Vue对象
let vm = new Vue({
data() {
return {
persons: [
{id: '001', name: '张三', age: 20},
{id: '002', name: '李四', age: 22},
{id: '003', name: '王武 ', age: 18}
],
}
}
}).$mount("#root");
</script>
</body>
</html>
说明:上面案例中我们使用v-for指令对person数组进行遍历展示,注意我们的key在选择时使用的时元素的id,而没有使用元素在数组中的下标index,主要是为了保证它的唯一性,当使用index作为key时,再执行一些逆序操作时可能会存在一些问题;

2.遍历对象:
plain
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--2.准备一个容器-->
<div id="root">
<!-- 遍历对象 -->
<ul>
<!-- (item 值,index 属性名) -->
<li v-for="(item,index) in numbers" :key="index">
{{index}}-{{item}}
</li>
</ul>
</div>
<!--1.引入Vue js 文件-->
<script src="vue/vue.js"></script>
<script type="text/javascript">
//3.创建Vue对象
let vm = new Vue({
data() {
return {
numbers: {
a: 1,
b: 2,
c: 3
},
}
}
}).$mount("#root");
</script>
</body>
</html>

3.遍历字符串:
plain
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--2.准备一个容器-->
<div id="root">
<!-- 遍历字符串 -->
<ul>
<!-- (item 字符,index 下标) -->
<li v-for="(item,index) in str" :key="index">
{{index}}-{{item}}
</li>
</ul>
</div>
<!--1.引入Vue js 文件-->
<script src="vue/vue.js"></script>
<script type="text/javascript">
//3.创建Vue对象
let vm = new Vue({
data() {
return {
str: 'hello'
}
}
}).$mount("#root");
</script>
</body>
</html>

4.遍历次数:
plain
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--2.准备一个容器-->
<div id="root">
<!-- 遍历固定次数 -->
<ul>
<!-- (item 次数,index 下标) -->
<li v-for="(item,index) in 5" :key="index">
{{index}}-{{item}}
</li>
</ul>
</div>
<!--1.引入Vue js 文件-->
<script src="vue/vue.js"></script>
<script type="text/javascript">
//3.创建Vue对象
let vm = new Vue({
data() {
return {
}
}
}).$mount("#root");
</script>
</body>
</html>

4.key的原理:
1.案例:
plain
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--2.准备一个容器-->
<div id="root">
<h2>人员列表</h2>
<button @click="add">添加老刘到列表中</button>
<ul>
<li v-for="(item,index) in persons" :key="index">
{{index}}-{{item.name}}-{{item.age}}
<input type="text"/>
</li>
</ul>
</div>
<!--1.引入Vue js 文件-->
<script src="vue/vue.js"></script>
<script type="text/javascript">
//3.创建Vue对象
let vm = new Vue({
data() {
return {
persons: [
{id: '001', name: '张三', age: 20},
{id: '002', name: '李四', age: 22},
{id: '003', name: '王武 ', age: 18}
]
}
},
methods: {
add() {
this.persons.unshift({id: '004', name: '老刘 ', age: 25}) //插入到第一个元素位置
}
}
}).$mount("#root");
</script>
</body>
</html>
上面案例中我们给按钮绑定了一个事件,当事件触发时,会添加老刘的信息到对象数组中,再通过v-for指令来遍历对象数组,此时的key为下标index

点击按钮,触发事件,将老刘添加到首位

通过结果看,似乎没有问题,但当前面数据后面的文本框内有内容时,还会一一对应吗


从测试结果来看,出现了数据错乱的现象。例如,新添加 "老刘" 到首位后,本应在其后的输入框为空,但却显示了原本张三对应的数据 "1"。
这种异常情况主要源于在 `v-for` 遍历时使用 `index` 作为 `key`。在该案例中,输入框内容与 `key`(即 `index`)存在绑定关系。初始时,数据 "1" 对应的 `index` 为 0,代表张三。然而,当 "老刘" 添加至首位后,`index` 为 0 的位置被 "老刘" 占据,导致数据与 `index` 的对应关系错乱,从而引发了上述显示错误。
实际上,从虚拟 DOM 的角度深入分析,在理想情况下,仅新增 "老刘" 这一数据时,其余数据未发生实质性改变,不应重新生成新的虚拟 DOM 对象。但由于 Vue 依靠 `key` 来判断节点身份,在新增数据到数组首位时,其余数据的下标发生改变,也就意味着以 `index` 作为 `key` 时其值发生了变化。此时,Vue 会判定这些节点均为新节点,进而生成新的虚拟 DOM 对象。这不仅会导致如输入框数据错乱等显示问题,而且即使不考虑数据错乱,这种因 `key` 变化而频繁生成新虚拟 DOM 对象的情况,会显著增加 Diff 算法的计算量以及真实 DOM 的更新操作次数。因为每次生成新虚拟 DOM 后,都需要与旧虚拟 DOM 进行全面的差异比对,然后根据比对结果更新真实 DOM,大量不必要的操作严重降低了 Vue 的执行效率。
综上所述,在使用 `v-for` 指令遍历动态数据列表时,强烈建议使用具有唯一性且稳定不变的属性作为 `key`,避免使用 `index`,以确保数据与 DOM 节点的正确绑定以及 Vue 应用的高效运行。
所以如果将index作为key则不应该进行逆序操作,如下面案例2所示
plain
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--2.准备一个容器-->
<div id="root">
<h2>人员列表</h2>
<button @click="add">添加老刘到列表中</button>
<ul>
<li v-for="(item,index) in persons" :key="index">
{{index}}-{{item.name}}-{{item.age}}
<input type="text"/>
</li>
</ul>
</div>
<!--1.引入Vue js 文件-->
<script src="vue/vue.js"></script>
<script type="text/javascript">
//3.创建Vue对象
let vm = new Vue({
data() {
return {
persons: [
{id: '001', name: '张三', age: 20},
{id: '002', name: '李四', age: 22},
{id: '003', name: '王武 ', age: 18}
]
}
},
methods: {
add() {
this.persons.push({id: '004', name: '老刘 ', age: 25}) //插入到最后
}
}
}).$mount("#root");
</script>
</body>
</html>

此时我们再添加老刘到最后,再看看数据是否错乱

此时发现数据是一一对应的,没有发现错乱,这是因为我们添加数据到末尾,没有改变原数据的index,也就不会出现错乱,同时原数据也不会重新生成虚拟DOM对象,Vue的效率也会相对较高
那如果一定要逆序插入数据,但又不想出现上面的问题,那该如何实现呢。
要实现这个需求,此时v-for指令中的key就不能是index了,而应该是遍历的数据中的一个属性(最好是唯一属性),如下面案例3所示:
plain
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--2.准备一个容器-->
<div id="root">
<h2>人员列表</h2>
<button @click="add">添加老刘到列表中</button>
<ul>
<li v-for="(item,index) in persons" :key="item.id">
{{index}}-{{item.name}}-{{item.age}}
<input type="text"/>
</li>
</ul>
</div>
<!--1.引入Vue js 文件-->
<script src="vue/vue.js"></script>
<script type="text/javascript">
//3.创建Vue对象
let vm = new Vue({
data() {
return {
persons: [
{id: '001', name: '张三', age: 20},
{id: '002', name: '李四', age: 22},
{id: '003', name: '王武 ', age: 18}
]
}
},
methods: {
add() {
this.persons.unshift({id: '004', name: '老刘 ', age: 25}) //插入到第一个元素位置
}
}
}).$mount("#root");
</script>
</body>
</html>

此时我们添加老刘到首位,再看看是否可以实现

通过测试结果可以看出,我们成功将老刘添加到了首位,并且数据没有出现错乱
在上面的案例中,我们是通过遍历元素的id为key,因此数据后面的输入框内容也是和数据id绑定在一起的,所以当我们添加老刘时,并不会改变其余元素的key,因此就可以成功将数据添加到首位,且不会造成数据错乱
2:总结:
key的作用:
1.虚拟DOM中key 的作用: key作为虚拟DOM的标识。
当数据发生改变时,VUE会根据【新的数据】生成【新的虚拟DOM】,随后与旧的虚拟DOM进行差异比对
1.旧的虚拟DOM中找到了与新的虚拟DOM相同的 key
-
如果虚拟DOM中的内容没有改变则使用之前的虚拟DOM
-
如果虚拟DOM中的内容改变了,生成新的虚拟DOM,再将虚拟DOM对应得真实DOM中发生改变的部分进行覆盖
2.如果旧的虚拟DOM中没有找到与新的虚拟DOM相同的key,创建新的真实DOM 渲染到页面中
2.index能否作为key?
1.如果对数据进行了逆序的操作(破坏了顺序的操作),会产生没有必要的真实DOM更新
2.如果对数据的操作没有破坏顺序,那么就可以使用index作为key
3.图示:
