当前位置: 首页 > news >正文

Vue中的数据渲染【4】

目录

  • 1.页面样式绑定:
      • 1.概述:
      • 2.绑定方式:
        • 1.通过类名绑定:
          • 1.通过动态类名绑定:(:class)
          • 2.通过类名数组绑定:
          • 3.通过类名对象进行绑定:
        • 2.内联样式绑定:(:sytle)
          • 1.通过样式对象语法绑定:
          • 2.通过样式数组语法绑定:
  • 2.条件渲染:
      • 1.概述:
      • 2.语法:
      • 3.使用方法:
      • 4.注意事项;
  • 3.列表渲染
      • 1.概述:
      • 2.语法:
      • 3.使用:
        • 1.遍历数组:
        • 2.遍历对象:
        • 3.遍历字符串:
        • 4.遍历次数:
      • 4.key的原理:
        • 1.案例:
        • 2:总结:
          • key的作用:
            • 1.虚拟DOM中key 的作用: key作为虚拟DOM的标识。
            • 2.index能否作为key?
        • 3.图示:

1.页面样式绑定:

1.概述:

页面样式绑定在 Vue 中是一种将样式与数据动态关联起来的方式,使得页面的样式可以根据数据的变化而自动更新。

2.绑定方式:

1.通过类名绑定:
1.通过动态类名绑定:(:class)
  <!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.通过类名数组绑定:
  <!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.通过类名对象进行绑定:
  <!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.通过样式对象语法绑定:
  <!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.通过样式数组语法绑定:
  <!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.语法:

  v-if='条件1'.....v-else-if='条件2'....v-else-if='条件3'..........v-else ........

3.使用方法:

<!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的不同值,在页面渲染展示不同的内容![](https://cdn.nlark.com/yuque/0/2024/png/45532635/1732158019754-79e8d49d-c41f-4bed-b8ee-913d72018687.png)

4.注意事项;

  •  v-if 指令会移除当条件不满足时页面的DOM元素;
    
  •  v-else-if指令执行过程中不能被其他业务中断,否则中断之后的逻辑判断不再执行;
    
  •  v-if指令适合执行内容隐藏-显示切换频率不高的场景,如果切换频率较高,则应使用v-show指令,因为v-show指令不会删除不满足条件的DOM元素,而是会将其通过CSS隐藏起来,因此效率比较高;
    

3.列表渲染

1.概述:

列表渲染主要是通过v-for指令对数组,对象,字符串等数据进行遍历;

2.语法:

v-for="(item,index)  in 遍历对象" :key='对象的键'   

3.使用:

1.遍历数组:
<!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.遍历对象:
<!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.遍历字符串:
 <!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.遍历次数:
 <!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.案例:
<!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所示

 <!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所示:
 <!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.图示:

http://www.dtcms.com/a/334192.html

相关文章:

  • Docker自定义镜像
  • 138-基于FLask的重庆市造价工程信息数据可视化分析系统
  • Chrome腾讯翻译插件transmart的安装
  • RK3588芯片在AR眼镜中的核心技术优势是什么?
  • VS Code配置MinGW64编译ALGLIB库
  • 新字符设备驱动实验
  • pytest tmpdir fixture介绍(tmpdir_factory)(自动在测试开始前创建一个临时目录,并在测试结束后删除该目录)
  • c# WebAssembly,在网页上能运行多线程,异步,锁,原子加,减等代码吗
  • springboot集成websocket
  • css实现圆角+边框渐变+背景半透明
  • 深入详解PCB布局布线技巧-去耦电容的摆放位置
  • 上位机知识篇---Linux日志
  • Python基础语法 从入门到精通
  • MATLAB基础训练实验
  • GitHub PR 提交流程
  • 车载控制器硬件电路-各电源轨和功能模块定义以及作用
  • 从冒泡到快速排序:探索经典排序算法的奥秘(二)
  • 【Qt开发】常用控件(四)
  • 适合2D而非3D的游戏
  • 链表。。。
  • YOLOv5、YOLOv8的损失函数、正负样本匹配策略和anchor_free/anchor_base的差异对比
  • 免费数独游戏,多难度等级挑战
  • 存储设备的核心单位:扇区、页与块
  • CentOS 7 一键部署 上Maria Database(MariaDB)10.3.38 安装手册(避开 Oracle 19c 路径)
  • 北京JAVA基础面试30天打卡11
  • JetPack系列教程(八):PDF库——让Android应用也能优雅“翻页”
  • ESP32 C3 开发板使用教程 01-测试显示屏
  • 【系统分析师】软件需求工程——第11章学习笔记(下)
  • Android 移动端 UI 设计:前端常用设计原则总结
  • 【Docker项目实战】使用Docker部署Notepad轻量级记事本