VUE的列表渲染

这是我关于VUE的列表渲染的学习笔记如下:
第一步、我们先初步认识https://www.cnblogs.com/buluzombie/p/15617040.html
我们要实现列表渲染就要借助于v-for指令来实现。
其使用方法:
1.这个指令可以遍历数据进行渲染列表进而展示数据。
2.其使用格式:语法:v-for=“(item, index) in items” :key=“item.message"或者v-for=”(item, index) of items" :key=“item.message”
3.v-for可遍历:数组、对象、字符串(用的很少)、指定次数(用的很少)
代码案例如下:

<!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>列表渲染(基本使用)</title>
                  <script type="text/javascript" src="../vue_js/vue.js"></script>
                  <style>
                                    li {
                                                      list-style: none;
                                    }
                  </style>
</head>

<body>
                  <!--用 v-for 把一个数组对应为一组元素-->
                  <div id="root">
                                    <h1>遍历数组</h1>
                                    <ul>
                                                      <li v-for="(c,i) of city" :key="i">
                                                                        {{c}}------{{c.id}}------{{c.cityName}}
                                                      </li>
                                    </ul>
                                    <h1>遍历对象</h1>
                                    <ul>
                                                      <li v-for="(v,k) of person" :key="k">
                                                                        {{v}}-----{{k}}
                                                      </li>
                                    </ul>
                                    <h1>遍历字符串</h1>
                                    <ul>
                                                      <li v-for="(v,k) of str" :key="k">
                                                                        {{v}}-----{{k}}
                                                      </li>
                                    </ul>
                                    <h2>测试遍历指定次数(用得少)</h2>
                                    <ul>
                                                      <li v-for="(number,index) of 5" :key="index">
                                                                        index:{{index}}----value:{{number}}
                                                      </li>
                                    </ul>
                  </div>
                  <script>
                                    Vue.config.productionTip = false
                                    const vm = new Vue({
                                                      el: '#root',
                                                      data: {
                                                                        city: [
                                                                                          { id: '001', cityName: '张三' },
                                                                                          { id: '002', cityName: '李四', },
                                                                                          { id: '003', cityName: '王五', }],
                                                                        person: {
                                                                                          eat: '饭',
                                                                                          eye: '一双眼睛',
                                                                                          ears: '一双耳朵',
                                                                                          face: '一张脸'
                                                                        },
                                                                        str: 'Chinese'
                                                      }
                                    });
                  </script>
</body>

</html>

第二步、key的原理
1.虚拟DOM中key的作用:
key是虚拟DOM对象的标识,当数据发生变化时,Vue会根据【新数据】生成【新的虚拟DOM】, 随后Vue进行【新虚拟DOM】与【旧虚拟 DOM】的差异比较
2.比较规则如下:
(1).旧虚拟DOM中找到了与新虚拟DOM相同的key:
①.若虚拟DOM中内容没变, 直接使用之前的真实DOM!
②.若虚拟DOM中内容变了, 则生成新的真实DOM,随后替换掉页面中之前的真实DOM。
(2).旧虚拟DOM中未找到与新虚拟DOM相同的key:创建新的真实DOM,随后渲染到到页面。
3. 用index作为key可能会引发的问题:
(1)若对数据进行:逆序添加、逆序删除等破坏顺序操作:会产生没有必要的真实DOM更新 ,界面效果没问题, 但效率低。
(2)如果结构中还包含输入类的DOM:会产生错误DOM产生, 界面有问题。
4. 开发中如何选择key?
(1)最好使用每条数据的唯一标识作为key, 比如id、手机号、身份证号、学号等唯一值。
(2).如果不存在对数据的逆序添加、逆序删除等破坏顺序操作,仅用于渲染列表用于展示,使用index作为key是没有问题的。

<!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>key的作用和原理</title>
                  <script type="text/javascript" src="../vue_js/vue.js"></script>
                  <style>
                                    li {
                                                      list-style: none;
                                    }
                  </style>
</head>

<body>
                  <h1>ul列表</h1>
                  <div id="demo">
                                    <button @click.once="addFruit">向水果列表添加水果</button>
                                    <ul>
                                                      <li v-for="(fruit,index) of fruits" :key="index">
                                                                        {{fruit}}-----{{index}}:<input type="text">

                                                      </li>
                                    </ul>
                  </div>
                  <script>
                                    Vue.config.productionTip = false;
                                    const vm = new Vue({
                                                      el: '#demo',
                                                      data: {
                                                                        fruits: ['苹果', '梨子', '香蕉', '橘子', '红枣', '葡萄']
                                                      },
                                                      methods: {
                                                                        addFruit() {
                                                                                          let f = "柚子"
                                                                                          //往前加
                                                                                          this.fruits.unshift(f)
                                                                                          //往后加
                                                                                          //this.fruits.push(f)
                                                                        }
                                                      },
                                    });
                  </script>
</body>

</html>

没有点击按钮之前的图片:
![在这里插入图片描述](https://img-blog.csdnimg.cn/aa3adb9ba319487a80f10d72d4d48483.png

点击按钮之后的图片:
在这里插入图片描述
在这里有一个明显的问题,当我们再列表的前面添加数据的时候,输入框里面的内容的位置错乱,本应该再苹果那里,但是点击之后却显示再柚子的位置上。为啥会这样呢?
列表渲染的更新主要是根据key来更新, key是虚拟DOM对象的标识,VUE会根据VUE数据的变化,产生新的虚拟DOM,接着产生新的真实DOM。新旧虚拟DOM会根据key进行比较。新数据的柚子和旧数据的苹果进行比较,发现不一样,就创建新的DOM,接着比较后面输入框,发现新旧虚拟DOM都有输入框input,所以直接使用旧的真实DOM,所以“苹果----0”就会直接服用旧的真实DOM,还是位于key=0的位置上。
第三步、列表过滤
我们可以filter函数的基础上利用watch侦听器实现或者计算属性实现,下面就是都采用了这两种方式实现的:
一般计算属性可以实现的,watch也可以实现,但是我们一般来说都会采用计算属性,计算属性一般可能更加简单一些。

<!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>列表过滤</title>
                  <script type="text/javascript" src="../vue_js/vue.js"></script>
</head>

<body>

                  <div id="root">
                                    <h1>使用watch侦听器实现</h1>
                                    <input type="text" placeholder="请输入名字" v-model="keyWord1">
                                    <ul>
                                                      <li v-for="(p,index) of filPerons" :key="index">
                                                                        {{p.name}}-{{p.age}}-{{p.sex}}
                                                      </li>
                                    </ul>
                                    <h1>使用计算属性实现</h1>
                                    <input type="text" placeholder="请输入提示信息" v-model="keyWord2">
                                    <ul>
                                                      <li v-for="(f,index) of filPerons1" :key="index">
                                                                        {{f.name}}-{{f.color}}-{{f.varieties}}
                                                      </li>
                                    </ul>
                  </div>
                  <script>
                                    Vue.config.productionTip = false;
                                    const vm = new Vue({
                                                      el: '#root',
                                                      data: {
                                                                        keyWord1: '',
                                                                        keyWord2: '',
                                                                        persons: [
                                                                                          { id: '001', name: '关晓彤', age: 19, sex: '女' },
                                                                                          { id: '002', name: '鞠婧祎', age: 20, sex: '女' },
                                                                                          { id: '003', name: '赵露思', age: 21, sex: '女' },
                                                                                          { id: '004', name: '李易峰', age: 22, sex: '男' }
                                                                        ],
                                                                        fuits: [
                                                                                          { id: '001', name: '香蕉', color: '黄色', varieties: '芝麻蕉' },
                                                                                          { id: '002', name: '苹果', color: '青色', varieties: '红将军' },
                                                                                          { id: '003', name: '大枣', color: '红色', varieties: '壶瓶枣' },
                                                                                          { id: '004', name: '梨子', color: '黄色', varieties: '黄金梨' }
                                                                        ],
                                                                        filPerons: [],
                                                      },
                                                      watch: {
                                                                        keyWord1: {
                                                                                          immediate:true,
                                                                                          handler(val) {
                                                                                                            this.filPerons = this.persons.filter((p) => {
                                                                                                                              return p.name.indexOf(val) !== -1
                                                                                                            })
                                                                                          }
                                                                        }
                                                      },
                                                      computed: {
                                                                        filPerons1: {
                                                                                          get() {
                                                                                                            return this.fuits.filter((p) => {
                                                                                                                              return p.name.indexOf(this.keyWord2) !== -1
                                                                                                            })
                                                                                          }
                                                                        }
                                                      }
                                    });

                  </script>
</body>

</html>

在这里插入图片描述

在这里插入图片描述
第四步、列表排序:
这里实现列表排序主要是sort实现的以及根据sortType来判断排序的方式,如顺序升序,降序排序,以及原始排序,实现排序方式的代码是“return this.sortType === 1 ? (s2.score - s1.score) : (s1.score - s2.score)”也就是一个三元表达式。

<!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>列表排序</title>
                  <script type="text/javascript" src="../vue_js/vue.js"></script>
                  <style>
                                    li {
                                                      list-style: none;
                                    }
                  </style>
</head>

<body>
                  <div id="root">
                                    <input type="text" placeholder="请输入名字" v-model="searchStudent">
                                    <button @click="sortType = 2">分数升序</button>
                                    <button @click="sortType = 1">分数降序</button>
                                    <button @click="sortType = 0">原始顺序</button>
                                    <ul>
                                                      <li v-for="(v,k) of sortStudent" :key="v.id">
                                                                        {{v.studentName}}----{{v.score}}
                                                      </li>
                                    </ul>
                  </div>
                  <script>
                                    Vue.config.productionTip = false;
                                    const vm = new Vue({
                                                      el: '#root',
                                                      data: {
                                                                        searchStudent: '',
                                                                        sortType:0,
                                                                        student: [
                                                                                          { id: '001', studentName: '张三', score: 100 },
                                                                                          { id: '002', studentName: '李四', score: 89 },
                                                                                          { id: '003', studentName: '王五', score: 94 },
                                                                                          { id: '004', studentName: '小明', score: 84 },
                                                                                          { id: '005', studentName: '小刚', score: 99 },
                                                                                          { id: '006', studentName: '小华', score: 67 },
                                                                                          { id: '007', studentName: '小红', score: 81 },
                                                                                          { id: '008', studentName: '小芳', score: 62 },
                                                                                          { id: '009', studentName: '赵虎', score: 97 },
                                                                                          { id: '010', studentName: '张龙', score: 99 },
                                                                                          { id: '011', studentName: '马汉', score: 73 },
                                                                                          { id: '012', studentName: '罗三', score: 92 },
                                                                                          { id: '013', studentName: '刘贝', score: 91 }
                                                                        ]
                                                      },
                                                      computed: {
                                                                        sortStudent() {
                                                                                          console.log(this.sortType);
                                                                                          const studentArr = this.student.filter((s) => {
                                                                                                            return s.studentName.indexOf(this.searchStudent) !== -1;
                                                                                          });
                                                                                          if (this.sortType) {
                                                                                                            studentArr.sort((s1, s2) => {
                                                                                                                              return this.sortType === 1 ? (s2.score - s1.score) : (s1.score - s2.score)
                                                                                                            });
                                                                                          }
                                                                                          return studentArr;
                                                                        }

                                                      }
                                    });
                  </script>
</body>

</html>

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

在这里插入图片描述

第五步、VUE监测数据变化的原理(来源于:https://www.cnblogs.com/buluzombie/p/15617040.html,大家可以直接到这个网址去看)
Vue 监视数据的原理:
1.vue 会监视 data 中所有层次的数据。
2. 如何监测对象中的数据?
  通过 setter 实现监视,且要在 new Vue 时就传入要监测的数据。(如下图)
  (1)对象中后追加的属性,vue 默认不做响应式处理
  (2)如需给后添加的属性做响应式,请使用如下API:
    Vue.set(target, propertyName/index, value) 或 vm. s e t ( t a r g e t , p r o p e r t y N a m e / i n d e x , v a l u e ) 3. 如何监测数组中的数据?  通过包裹数组更新元素的方法实现,本质就是做了两件事:  ( 1 )调用原生对应的方法对数据进行更新。  ( 2 )重新解析模板,进而更新页面。 4. 在 V u e 修改数组中的某个元素一定要用如下方法:   1. 使用这些 A P I : p u s h ( ) 、 p o p ( ) 、 s h i f t ( ) 、 u n s h i f t ( ) 、 s p l i c e ( ) 、 s o r t ( ) 、 r e v e r s e ( )    2. V u e . s e t ( ) 或 v m . set(target, propertyName/index, value) 3. 如何监测数组中的数据?   通过包裹数组更新元素的方法实现,本质就是做了两件事:   (1)调用原生对应的方法对数据进行更新。   (2)重新解析模板,进而更新页面。 4. 在Vue修改数组中的某个元素一定要用如下方法:   1.使用这些 API: push()、pop()、shift()、unshift()、splice()、sort()、reverse()   2. Vue.set() 或 vm. set(target,propertyName/index,value)3.如何监测数组中的数据?  通过包裹数组更新元素的方法实现,本质就是做了两件事:  (1)调用原生对应的方法对数据进行更新。  (2)重新解析模板,进而更新页面。4.Vue修改数组中的某个元素一定要用如下方法:  1.使用这些APIpush()pop()shift()unshift()splice()sort()reverse()  2.Vue.set()vm.set()
在这里插入图片描述
其中的案例代码如下:

<!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 type="text/javascript" src="../vue_js/vue.js"></script>
                  <style>
                                    #s {
                                                      width: 100px;
                                                      height: 100px;
                                                      background-color: rgb(72, 23, 128);
                                                      text-align: center;
                                                      font-size: 70px;
                                                      color: white;
                                    }
                  </style>
</head>

<body>
                  <div id="root">
                                    <button @click="num++">点击按钮实现下面的数字加一</button><br>
                                    <div id="s">{{num}}</div><br>
                                    <button @click="myFriend.age++">年龄+1</button>
                                    <button @click="myFriend.sex = '“由于情况特殊,所以该选项位置”' ">修改性别</button> <br />
                                    <button @click.once="addBallGame('冰球')">在球类列表再添加一个其他的球类项目(但是只能增加一次)</button>
                                    <button @click="addFriend">在列表首位添加一个朋友</button> <br />
                                    <button @click="updateFirstFriendName">修改第一个朋友的名字为:张三</button> <br />
                                    <button @click="updateHobby">修改第2个爱好为Basketball</button> <br />
                                    <button @click="removeRugby">过滤掉爱好中的橄榄球</button> <br />
                                    <h2>这是我朋友的年龄,他的名字是{{myFriend.name}},今年是{{myFriend.age}}岁。他的性别是<span
                                                                        v-if="myFriend.sex">{{myFriend.sex}}</span></h2>
                                    <h2>我这个朋友善于球类运动项目,比如下面这些:</h2>
                                    <ul>
                                                      <li v-for="(value,index) of myFriend.habby" :key="index">
                                                                        {{value}}
                                                      </li>
                                    </ul>
                                    <h2>他除了我之外也有很多其他朋友,如下面这些人:</h2>
                                    <ul>
                                                      <li v-for="(hf,index) in myFriend.hisFriends" :key="index">
                                                                        {{hf.name}}----{{hf.age}}------{{hf.sex}}
                                                      </li>
                                    </ul>
                  </div>
                  <script>
                                    Vue.config.productionTip = false; //阻止 vue 在启动时生成生产提示。
                                    const vm = new Vue({
                                                      el: '#root',
                                                      data: {
                                                                        num: 0,
                                                                        myFriend: {
                                                                                          name: '小明',
                                                                                          age: 18,
                                                                                          sex: '男',
                                                                                          habby: ['足球', '篮球', '排球', '羽毛球', '网球', '乒乓球', '橄榄球', '台球'],
                                                                                          hisFriends: [
                                                                                                            { name: '小华', age: 19, sex: '男' },
                                                                                                            { name: '小刚', age: 19, sex: '男' },
                                                                                                            { name: '小芳', age: 17, sex: '女' },
                                                                                                            { name: '小红', age: 20, sex: '女' },
                                                                                                            { name: '小坤', age: 18, sex: '男' }
                                                                                          ]
                                                                        }
                                                      },
                                                      methods: {
                                                                        addBallGame(ball) {
                                                                                          this.myFriend.habby.push(ball);
                                                                        },
                                                                        addFriend() {
                                                                                          this.myFriend.hisFriends.unshift({ name: 'jack', age: 70, sex: '男' })
                                                                        },
                                                                        updateFirstFriendName() {
                                                                                          this.myFriend.hisFriends[0].name = "张三";
                                                                        },
                                                                        updateHobby() {
                                                                                          // this.student.hobby.splice(0,1,'Basketball车')
                                                                                          // Vue.set(this.student.hobby,1,'Basketball')
                                                                                          this.$set(this.myFriend.habby, 1, 'Basketball')
                                                                        },
                                                                        removeRugby(){
                                                                                          this.myFriend.habby = this.myFriend.habby.filter((obj)=>{
                                                                                                            return obj!='橄榄球'
                                                                                          })
                                                                        }
                                                      },
                                    });
                  </script>
</body>

</html>
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值