Vue核心 列表渲染 数据监视

news/2024/5/5 8:06:18/文章来源:https://blog.csdn.net/weixin_44230693/article/details/130535850

1.13.列表渲染

1.13.1.基本列表

v-for指令

  • 用于展示列表数据
  • 语法:
  • ,这里key可以是index,更好的是遍历对象的唯一标识
  • 可遍历:数组、对象、字符串(用的少)、指定次数(用的少)
<!DOCTYPE html>
<head><meta charset="UTF-8"><title>基本列表</title><!-- 引入Vue --><script type="text/javascript" src="../js/vue.js"></script>
</head>
<body><!--v-for指令:1.用于展示列表数据2.语法: v-for="(item, index) in xxx" :key="yyy"3.可遍历: 数组、对象、字符串 (用的很少) 、指定次数(用的很少)--><!-- 准备好一个容器 --><div id="root"><!-- 遍历数组 --><h3>人员列表(遍历数组)</h3><ul> <li v-for="(p, index) of personList" :key="index">{{ p.name }}-{{ p.age }}</li> </ul><!-- 遍历对象 --> <h3>汽车信息(遍历对象)</h3> <ul> <li v-for="(value, k) of car" :key="k">{{ k }}-{{ value }}</li> </ul><!-- 遍历字符串 --> <h3>测试遍历字符串(用得少)</h3> <ul><li v-for="(char, index) of str" :key="index">{{ char }}-{{ index }}</li> </ul><!-- 遍历指定次数 --><h3>测试遍历指定次数(用得少)</h3> <ul> <li v-for="(number, index) of 5" :key="index">{{ index }}-{{ number }}</li></ul></div><script type="text/javascript">// 阻止vue在启动时生成生产提示Vue.config.productionTip = falsenew Vue({ el: '#root',  	  data:{personList: [ { id: '001', name: '张三', age: 18 }, { id: '002', name: '李四', age: 19 }, { id: '003', name: '王五', age: 20 } ],car: { name: '奥迪A8', price: '70万', color: '黑色' }, str: 'hello'},});</script>
</body>
</html>

在这里插入图片描述

1.13.2.key 的作用与原理

在这里插入图片描述
在这里插入图片描述

面试题reactvue中的key有什么作用?(key的内部原理)

  1. 虚拟DOMkey的作用:key是虚拟DOM中对象的标识,当数据发生变化时,Vue会根据新数据生成新的虚拟DOM随后Vue进行新虚拟DOM与旧虚拟DOM的差异比较,比较规则如下
  2. 对比规则
    1. 虚拟DOM中找到了与新虚拟DOM相同的key
      1. 虚拟DOM中内容没变, 直接使用之前的真实DOM
      2. 虚拟DOM中内容变了, 则生成新的真实DOM,随后替换掉页面中之前的真实DOM
    2. 旧虚拟DOM中未找到与新虚拟DOM相同的key
      1. 创建新的真实DOM,随后渲染到到页面
  3. index作为key可能会引发的问题
    1. 若对数据进行逆序添加、逆序删除等破坏顺序操作,会产生没有必要的真实DOM更新 ==> 界面效果没问题,但效率低
    2. 若结构中还包含输入类的DOM:会产生错误DOM更新 ==> 界面有问题
  4. 开发中如何选择key?
    1. 最好使用每条数据的唯一标识作为key,比如 id、手机号、身份证号、学号等唯一值
    2. 如果不存在对数据的逆序添加、逆序删除等破坏顺序的操作,仅用于渲染列表,使用index作为key是没有问题的
<!DOCTYPE html>
<head><meta charset="UTF-8"><title>key的原理</title><!-- 引入Vue --><script type="text/javascript" src="../js/vue.js"></script>
</head>
<body><!--面试题: vue中的key有什么作用? (key的内部原理)1.虚拟DOM中key的作用:key是虚拟DOM对象的标识,当数据发生变化时,Vue会根据【新数据】生成【新的虚拟DOM】随后vue进行【新虚拟DOM】 与【旧虚拟DOM】 的差异比较,比较规则如下:2.对比规则:(1).旧虚拟DOM中找到了与新虚拟DOM相同的key:i.若虚拟DOM中内容没变,直接使用之前的真实DOM!ii.若虚拟DOM中内容变了,则生成新的真实DOM,随后替换掉页面中之前的真实DOM。(2).旧虚拟DOM中未找到与新虚拟DOM相同的key创建新的真实DOM,随后渲染到到页面。3.用index作为key可能会引发的问题:1.若对数据进行:逆序添加、逆序删除等破坏顺序操作:会产生没有必要的真实DOM更新 ==> 界面效果没问题,但效率低。2.如果结构中还包含输入类的DOM:会产生错误DOM更新 ==> 界面有问题。4.开发中如何选择key?:1.最好使用每条数据的唯一标识作为key,比如id、手机号、身份证号、学号等唯一值。2.如果不存在对数据的逆序添加、逆序删除等破坏顺序操作,仅用于渲染列表用于展示.使用index作为key是没有问题的。-->   <!-- 准备好一个容器 --><div id="root"><!-- 遍历数组 --><h3>人员列表(遍历数组)</h3><button @click.once="add">添加一个老刘</button><ul> <li v-for="(p, index) of personList" :key="index">{{ p.name }}-{{ p.age }}</li> </ul></div><script type="text/javascript">// 阻止vue在启动时生成生产提示Vue.config.productionTip = falsenew Vue({ el: '#root',  	  data:{personList: [ { id: '001', name: '张三', age: 18 }, { id: '002', name: '李四', age: 19 }, { id: '003', name: '王五', age: 20 } ]},methods: { add() { const p = { id: '004', name: '老刘', age: 40 }this.persons.unshift(p) } }});</script>
</body>
</html>

在这里插入图片描述


1.13.3.列表过滤

<!DOCTYPE html>
<head><meta charset="UTF-8"><title>列表过滤</title><!-- 引入Vue --><script type="text/javascript" src="../js/vue.js"></script>
</head>
<body><!-- 准备好一个容器 --><div id="root"><!-- 遍历数组 --><h3>人员列表</h3><input type="text" placeholder="请输入名字" v-model="keyWord"><ul> <li v-for="(p,index) of filPersonList" :key="p.id"> {{ p.name }}-{{ p.age }}-{{ p.sex }} </li> </ul></div><script type="text/javascript">// 阻止vue在启动时生成生产提示Vue.config.productionTip = false// 用 watch 实现// new Vue({ // 	el: '#root',  	  // 	data:{//         keyWord: '',//         personList: [//             { id: '001', name: '马冬梅', age: 19, sex: '女' },//             { id: '002', name: '周冬雨', age: 20, sex: '女' }, //             { id: '003', name: '周杰伦', age: 21, sex: '男' },//             { id: '004', name: '温兆伦', age: 22, sex: '男' }//         ],//         filPersonList: []// 	},//     watch: { // 	    keyWord: { // 	        immediate: true, //             handler(val) {// 	            this.filPersonList = this.personList.filter((p) => { // 	                return p.name.indexOf(val) !== -1;// 	            }// 	        )} // 	    } // 	}// });// 用 computed 实现new Vue({ el: '#root',  	  data:{keyWord: '',personList: [{ id: '001', name: '马冬梅', age: 19, sex: '女' },{ id: '002', name: '周冬雨', age: 20, sex: '女' }, { id: '003', name: '周杰伦', age: 21, sex: '男' },{ id: '004', name: '温兆伦', age: 22, sex: '男' }]},computed: { filPersonList() { return this.personList.filter((p) => { return p.name.indexOf(this.keyWord) !== -1;});} }});</script>
</body>
</html>

在这里插入图片描述

1.13.4. 列表排序

<!DOCTYPE html>
<head><meta charset="UTF-8"><title>列表排序</title><!-- 引入Vue --><script type="text/javascript" src="../js/vue.js"></script>
</head>
<body><!-- 准备好一个容器 --><div id="root"><!-- 遍历数组 --><h3>人员列表</h3><input type="text" placeholder="请输入名字" v-model="keyWord"><button @click="sortType = 2">年龄升序</button> <button @click="sortType = 1">年龄降序</button> <button @click="sortType = 0">原顺序</button><ul> <li v-for="(p,index) of filPersonList" :key="p.id"> {{ p.name }}-{{ p.age }}-{{ p.sex }}<input type="text"></li> </ul></div><script type="text/javascript">// 阻止vue在启动时生成生产提示Vue.config.productionTip = falsenew Vue({ el: '#root',  	  data:{keyWord: '',sortType: 0, // 0原顺序 1降序 2升序personList: [{ id: '001', name: '马冬梅', age: 19, sex: '女' },{ id: '002', name: '周冬雨', age: 31, sex: '女' }, { id: '003', name: '周杰伦', age: 18, sex: '男' },{ id: '004', name: '温兆伦', age: 22, sex: '男' }]},computed: { filPersonList() {const arr = this.personList.filter((p) => { return p.name.indexOf(this.keyWord) !== -1;});// 判断一下是否需要排序 if (this.sortType) { arr.sort((p1, p2) => { return this.sortType === 1 ? p2.age - p1.age : p1.age - p2.age });}return arr;} }});</script>
</body>
</html>

在这里插入图片描述

1.13.5. Vue 数据监视

更新时的一个问题

this.persons[0] = {id:‘001’,name:‘马老师’,age:50,sex:‘男’} 更改data数据,Vue不监听,模板不改变

<!DOCTYPE html>
<head><meta charset="UTF-8"><title>更新时的一个问题</title><!-- 引入Vue --><script type="text/javascript" src="../js/vue.js"></script>
</head>
<body><!-- 准备好一个容器 --><div id="root"><!-- 遍历数组 --><h3>人员列表</h3><button @click="updateMei">更新马冬梅的信息</button><ul> <li v-for="(p,index) of filPersonList" :key="p.id"> {{ p.name }}-{{ p.age }}-{{ p.sex }}<input type="text"></li> </ul></div><script type="text/javascript">// 阻止vue在启动时生成生产提示Vue.config.productionTip = falsenew Vue({ el: '#root',  	  data:{keyWord: '',sortType: 0, // 0原顺序 1降序 2升序personList: [{ id: '001', name: '马冬梅', age: 19, sex: '女' },{ id: '002', name: '周冬雨', age: 31, sex: '女' }, { id: '003', name: '周杰伦', age: 18, sex: '男' },{ id: '004', name: '温兆伦', age: 22, sex: '男' }]},methods: {updateMei() {// this.persons[0].name = '马老师' // 奏效 // this.persons[0].age = 50 // 奏效 // this.persons[0].sex = '男' // 奏效 // this.persons[0] = {id:'001',name:'马老师',age:50,sex:'男'} // 不奏效this.persons.splice(0, 1, { id: '001', name: '马老师', age: 50, sex: '男' })}}});</script>
</body>
</html>

模拟一个数据监测

<!DOCTYPE html>
<head><meta charset="UTF-8"><title>模拟一个数据检测</title>
</head>
<body><script type="text/javascript">let data = { name: '尚硅谷', address: '北京'}// 创建一个监视的实例对象function Observer(obj) {// 汇总对象中所有的属性形成一个数组const keys = Object.keys(obj)// 遍历keys.forEach((k) => {Object.defineProperty(this, k, {get() {return obj[k]},set(val) {console.log(`${k}被改了,我要去解析模板,生成虚拟DOM.....我要开始忙了`);obj[k] = val;}})})}// 创建一个监视的实例对象,用于监视data中属性的变化 const obs = new Observer(data);console.log(obs);// 准备一个vm实例对象 let vm = {};vm._data = data = obs;</script>
</body>
</html>

原理

  1. vue会监视data中所有层次的数据
  2. 如何监测对象中的数据?
    1. 通过setter实现监视,且要在**new Vue()**时就传入要监测的数据
      1. 对象创建后追加的属性,Vue默认不做响应式处理
      2. 如需给后添加的属性做响应式,请使用如下API
        1. Vue.set(target, propertyName/index, value)
        2. vm.$set(target, propertyName/index, value)
  3. 如何监测数组中的数据?
    1. 通过包裹数组更新元素的方法实现,本质就是做了两件事
      1. 调用原生对应的方法对数组进行更新
      2. 重新解析模板,进而更新页面
  4. Vue修改数组中的某个元素一定要用如下方法
    1. push() pop() unshift() shift() splice() sort() reverse()这几个方法被Vue重写了Vue.set()vm.$set()

特别注意Vue.set()vm.$set() 不能给vm或vm的根数据对象(data等)添加属性

<!DOCTYPE html>
<head><meta charset="UTF-8"><title>Vue检测数据改变的原理</title><!-- 引入Vue --><script type="text/javascript" src="../js/vue.js"></script>
</head>
<body><!--原理:1.vue会监视data中所有层次的数据2.如何监测对象中的数据?通过setter实现监视,且要在new Vue()时就传入要监测的数据(1).对象创建后追加的属性,Vue默认不做响应式处理(2).如需给后添加的属性做响应式,请使用如下API:Vue.set(target, propertyName/index, value) 或vm.$set(target, propertyName/index, value)3.如何监测数组中的数据?通过包裹数组更新元素的方法实现,本质就是做了两件事:(1).调用原生对应的方法对数组进行更新(2).重新解析模板,进而更新页面4.在Vue修改数组中的某个元素一定要用如下方法:1.push() pop() unshift() shift() splice() sort() reverse()2.Vue.set()或vm.$set()特别注意:Vue.set() 和 vm.$set() **不能给vm或vm的根数据对象(data等)添加属性--><!-- 准备好一个容器 --><div id="root"><h1>学生信息</h1><button @click="student.age.sage++">对外年龄+1岁</button> <br /><button @click="addSex">添加性别属性,默认值:男</button> <br /><button @click="student.sex = '' ">修改性别</button> <br /><button @click="addFriend">在列表首位添加一个朋友</button> <br /><button @click="updateFirstFriendName">修改第一个朋友的名字为:张三</button> <br /><button @click="addHobby">添加一个爱好</button> <br /><button @click="updateHobby">修改第一个爱好为:开车</button> <br /><button @click="removeSmoke">过滤掉爱好中的抽烟</button> <br /><h2>学校名称: {{name}}</h2><h2>学校地址: {{address}}</h2><hr/><h2>学生姓名:{{student.name}}</h2><h2>学生性别:{{student.sex}}</h2><h2>学生年龄:真实{{student.age.rage}}, 对外{{student.age.sage}}</h2><h3>爱好:</h3><ul> <li v-for="(h,index) in student.hobby" :key="index">{{ h }} </li> </ul><h2>朋友们</h2><ul><li v-for="(f,index) in student.friends" :key="index">{{f.name}} -- {{f.age}}</li></ul></div><script type="text/javascript">// 阻止vue在启动时生成生产提示Vue.config.productionTip = falseconst  vm = new Vue({ el: '#root',  	  data:{name: '尚硅谷', address: '北京',student: {name: 'tom',age: {rage: 40,sage: 29},hobby: ['抽烟', '喝酒', '烫头'],friends: [{name: 'jerry', age: 35},{name: 'tony', age: 36}]}},methods: {addSex() { // Vue.set(this.student,'sex','男') this.$set(this.student, 'sex', '男');},addFriend() { this.student.friends.unshift({ name: 'jack', age: 70 }); },updateFirstFriendName() { this.student.friends[0].name = '张三';},addHobby() { this.student.hobby.push('学习'); },updateHobby() { // this.student.hobby.splice(0,1,'开车'); // Vue.set(this.student.hobby,0,'开车'); this.$set(this.student.hobby, 0, '开车'); },removeSmoke() { this.student.hobby = this.student.hobby.filter((h) => { return h !== '抽烟'; }) }}});</script>
</body>
</html>

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_296932.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

对传递函数的零极点、频率响应、稳定性的理解

对传递函数的零极点、频率响应、稳定性的理解 零极点 从传递函数求零极点 令传递函数分子为0求出零点&#xff0c;令分母为0求出零点。 频率响应 单极点系统的频率响应 A v A v d c ∗ ( 1 / ( 1 s R C ) ) AvAv_dc*(1/(1sRC)) AvAvd​c∗(1/(1sRC))&#xff0c;系统的极…

Flask 知识点整理

文章目录 1.URL与视图的映射带参数的url&#xff1a;将参数固定到了path中查询字符串的方式传参 2.模板渲染给html文件传参 3.模板访问对象属性User 是个类User是个字典 4.过滤器的使用通过一个 | 管道符进行过滤自定义过滤器 5.控制语句iffor Flask连接MySQL数据库ORM模型与表…

[MySQL / Mariadb] 数据库学习-Linux中二进制方式安装MySQL5.7

Linux中二进制方式安装MySQL5.7 安装安装方式官网下载安装包创建用户组mysql&#xff0c;用户和目录把下载的安装包&#xff0c;放到/home/mysql/将本地文件拷贝到远程&#xff1a; scp 文件名 –用户名计算机IP或者计算机名称:远程路径 验证包解压安装包&#xff0c;移动到/us…

OJ 系统常用功能介绍 快速入门 C++ Python JAVA语言在线评测

技术支持微 makytony 服务器配置 腾讯云 2H4G 5M 60GB 轻量应用服务器 承载大约 200~400人使用&#xff0c;经过压力测试&#xff0c;评测并发速度可满足130人左右的在线比赛。 系统镜像选 Ubuntu 22.04 LTS &#xff0c;Ubuntu是最热门的Linux发行版之一&#xff0c;是一款…

数组中的empty剖析

数组中的empty剖析 一、首先empty是怎么来的 直接通过new Array来新建&#xff0c;手动修改数组的length&#xff0c;逗号之间没有任何数据等 const array new Array(3); console.log(array); //* (3) [empty 3]const array2 [1, , 3]; console.log(array2); //* [1, e…

一起学 WebGL:绘制图片

大家好&#xff0c;我是前端西瓜哥。之前讲解了如何用 WebGL 绘制红色三角形&#xff0c;今天西瓜哥带大家来学习如何将图片绘制到画布上的技术&#xff1a;纹理映射&#xff08;texture mapping&#xff09;。 本文为系列文章中的一篇&#xff0c;请先阅读&#xff1a; 《一起…

python 系列 07 - 基于easyocr的ocr识别

OCR,光学文字识别&#xff0c;对文本资料进行扫描&#xff0c;然后对图像文件进行分析处理&#xff0c;获取文字及版面信息的过程。本示例通过easyocr库来演示。easyocr是一个比较流行的库&#xff0c;支持超过80种语言。安装的时候注意会附带安装torch库&#xff08;一个深度学…

【Python】序列类型③-集合

文章目录 1.集合(set)简介2.集合的定义3.集合的遍历4.集合的常用方法 1.集合(set)简介 集合是一种无序可变的容器对象 集合最大的特点:同一个集合内元素是不允许有重复的,因此集合自带"去重"效果 2.集合的定义 集合的定义有两种方式: 使用{}进行定义,这种方式不能定…

获得 随机验证码(以图片为底层)

1&#xff1a;工具类 Slf4j public class RandomValidateCode {private static String baseNumLetter "1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ";private static String font "微软雅黑";//绘制验证码图片,返回验证码文本内容pu…

基于海鸥算法改进的随机森林分类算法-附代码

基于海鸥算法改进的随机森林分类算法 文章目录 基于海鸥算法改进的随机森林分类算法1.数据集2.RF模型3.基于海鸥算法优化的RF4.测试结果5.Matlab代码6.Python代码 摘要&#xff1a;为了提高随机森林数据的分类预测准确率&#xff0c;对随机森林中的树木个数和最小叶子点数参数利…

版本控制系统Git - 配置与基本使用

Git 1 Git简介1 Git概述2 Git的作用2.1 项目版本管理2.2 多人协同开发2.3 Git 的结构2.4 Git的工作原理 2 Git安装1 下载Git2 安装Git3 配置环境变量4 测试git是否安装成功5 安装git桌面工具(可以不安装) 3 Git基本操作1 设置Git用户2 新建仓库3 查看仓库状态4 添加到暂存文件5…

【python可视化】常用数据类型

&#x1f64b;‍ 哈喽大家好&#xff0c;本次是python数据分析、挖掘与可视化专栏第二期 ⭐本期内容&#xff1a;常用数据类型 &#x1f3c6;系列专栏&#xff1a;Python数据分析、挖掘与可视化 &#x1f44d;欢迎大佬指正&#xff0c;一起学习&#xff0c;一起加油&#xff01…

C++入门3(C++新特性 using string auto)

C入门3 C新特性auto推导规则auto 作为函数的形参类型decltype基于范围for循环 typedef与usingC语言定义变量typedef 在C语言中的写法using在C11中的写法using与template的结合 string的简单使用 C新特性 auto推导规则 auto类型推导: auto定义的变量&#xff0c;可以根据初始化…

C语言单链表

本节目标&#xff1a; ①定义单链表结构体 ②初始化单链表 ③单链表增加结点&#xff08;头插法、尾插法&#xff09; ④删除指定结点 ⑤打印输出 目录 导入头文件 定义单链表结构体 初始化单链表 头插法 尾插法插入 删除指定结点 打印单链表 全部代码展示 导入头文件 …

中文大模型安全性哪家强?清华团队新发布

当前大型语言模型的火爆程度我们不用再进行赘述了&#xff0c;伴随着百度文心一言打响国内商业大模型第一枪&#xff0c;华为盘古&#xff0c;阿里通义千问&#xff0c;智谱ChatGLM,科大讯飞星火等国内公司纷纷开始布局。 另一方面由于众所周知的政策原因&#xff0c;和如火如荼…

5 分钟教你如何免费用上 GPT-4

今天要分享的就是普通用户&#xff0c;没有 OpenAI 账号&#xff0c;不需要写代码&#xff0c;你依然可以免费体验 GPT-4&#xff0c;当然&#xff0c;会有一些缺点&#xff0c;本篇文章将会手把手教你怎么用上免费版的 GPT-4 以及它的一些限制。 第一步&#xff1a;打开 Stea…

Threejs进阶之十三:CSS3DRenderer与Tween.js实现粒子小球按规律变化

今天我们使用CSS3DRendererTween.js实现Threejs官方示例中的粒子小球按规律变化的效果&#xff0c;先看下最终实现的效果 先来分析下&#xff0c;这个页面的动画效果是由512个小球组合起来的四种不同变化&#xff0c;分别是曲面、立方体、随机和圆球四种变化&#xff1b;下面我…

UDP的报文结构

UDP 报文结构 基本上所有的教科书上都是这样画的图, 但实际上 UDP 报文结构不是这样的, 这样显示应该是容易排版. 正确应该如下图 : 端口号 : 每个端口号在 UDP 报文里占两个字节, 取值范围就是: 0 ~ 65535 源 ip 和源端口描述了数据从哪里来, 目的 ip 和目的端口描述了数据去哪…

文本的清洗和标准化:如何处理混乱的数据?

❤️觉得内容不错的话&#xff0c;欢迎点赞收藏加关注&#x1f60a;&#x1f60a;&#x1f60a;&#xff0c;后续会继续输入更多优质内容❤️ &#x1f449;有问题欢迎大家加关注私戳或者评论&#xff08;包括但不限于NLP算法相关&#xff0c;linux学习相关&#xff0c;读研读博…

操作系统考试复习—第三章 优先级倒置 死锁问题

当前OS广泛采用优先级调度算法和抢占方式&#xff0c;然而在系统中存在着影响进程运行的资源从而可能产生"优先级倒置"现象 具体解释为&#xff1a;在原本的调度算法设计中&#xff0c;高优先级进程可以抢占低优先级的CPU资源&#xff0c;先执行高优先级任务。但是存…