Shinkai005

V1

2022/05/14阅读:15主题:红绯

尚硅谷Vue2.0+Vue3.0全套教程-笔记2

029-列表渲染

代码

<body>
  <!-- 
    v-for指令:
      1.用于展示列表数据
      2.语法:v-for="(item, index) in xxx" :key="yyy"
      3.可遍历:数组、对象、字符串(用的很少)、指定次数(用的很少)
  -->

  <!-- 准备好一个容器-->
  <div id="root">
   <!-- 遍历数组 -->
   <h2>人员列表(遍历数组)</h2>
   <ul>
    <li v-for="(p,index) of persons" :key="index">
     {{p.name}}-{{p.age}}
    </li>
   </ul>

   <!-- 遍历对象 -->
   <h2>汽车信息(遍历对象)</h2>
   <ul>
    <li v-for="(value,k) of car" :key="k">
     {{k}}-{{value}}
    </li>
   </ul>

   <!-- 遍历字符串 -->
   <h2>测试遍历字符串(用得少)</h2>
   <ul>
    <li v-for="(char,index) of str" :key="index">
     {{char}}-{{index}}
    </li>
   </ul>
   
   <!-- 遍历指定次数 -->
   <h2>测试遍历指定次数(用得少)</h2>
   <ul>
    <li v-for="(number,index) of 5" :key="index">
     {{index}}-{{number}}
    </li>
   </ul>
  </div>

  <script type="text/javascript">
   Vue.config.productionTip = false
   
   new Vue({
    el:'#root',
    data:{
     persons:[
      {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>

笔记:

v-for指令:

​ 1.用于展示列表数据

​ 2.语法:v-for="(item, index) in xxx" :key="yyy"

​ 3.可遍历:数组、对象、字符串(用的很少)、指定次数(用的很少)

030-key作用与原理

代码:

<body>
  <!-- 准备好一个容器-->
  <div id="root">
   <!-- 遍历数组 -->
   <h2>人员列表(遍历数组)</h2>
   <button @click.once="add">添加一个老刘</button>
   <ul>
    <li v-for="(p,index) of persons" :key="index">
     {{p.name}}-{{p.age}}
     <input type="text">
    </li>
   </ul>
  </div>

  <script type="text/javascript">
   Vue.config.productionTip = false
   
   new Vue({
    el:'#root',
    data:{
     persons:[
      {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>

元素上的key最后不会被渲染在属性上.

下面内容是从 li的前侧生成一个新数据,并以非唯一表示 index作为key.

页面样式
页面样式
点击按钮后发生
点击按钮后发生
未改变前vue做了什么
未改变前vue做了什么
diff算法
diff算法

个人感觉有点繁琐~我从目的角度出发解释一下

vue本身是为了方便,也就是同样的内容会选择复用. 这个ok?

当把index作为key,并且unshift,数组前生成时,key是不是会变换?(这个其实已经违背了唯一标识了, 本身就是个错误的方式,只不过比较经典所以大家都拿这个错误的例子来做提问 ,但是很少有人思考,本身就是错的方式,即使结果对了那也是巧合而已.)

key变换之后,vue并不会看后面的东西,他只认key,也就是说(这里对比下 人和机器)

人看到上面diff对比, 我们要的是 老刘它对应的input 绑定.

vue看到的是, 你把 张三换成了 老刘而已,因为key才是vue趋向于第一判定的东西.

下面验证:

  1. vue匹配 第一行 key正常, 内容变(更改), 后面内容没变化复用.//检测不到变化的.在dom层面上.
  2. 第二行, key正常 李四变张三,input复用
  3. 一样
  4. 第四行, key新的,直接写就行.
id为key
id为key

再解释这个,

第一行,key变了,ok不用思考了,vue认为是一个全新的li.

第二行,可以对应上了,后面内容没有变,直接复用

后面一样.

这个和自己写代码一样的,我们追求的是眼前的任务,完成即可,(软件工程上的一句话, 永远要相信自己的代码依旧有bug)因此,自己的代码必然有适合的场景和不适合的场景....你不按标准的方式去使用别人的代码 (你是测试么???????,当然为了面试 忍一忍.)

面试题:react、vue中的key有什么作用?(key的内部原理)

  1. 虚拟DOM中key的作用:

    1. key是虚拟DOM对象的标识,当数据发生变化时,Vue会根据【新数据】生成【新的虚拟DOM】,

    2. 随后Vue进行【新虚拟DOM】与【旧虚拟DOM】的差异比较,比较规则如下:

    3. 对比规则:

      1. 旧虚拟DOM中找到了与新虚拟DOM相同的key:

        (1)若虚拟DOM中内容没变, 直接使用之前的真实DOM!

        (2)若虚拟DOM中内容变了, 则生成新的真实DOM,随后替换掉页面中之前的真实DOM。

      2. 旧虚拟DOM中未找到与新虚拟DOM相同的key

        顺序错了吧.

        应该是先找,没找到直接生成,未找到才看内容,没变复用,变了生成新的

        也行其实,小瑕疵~很厉害了.

      3. 创建新的真实DOM,随后渲染到到页面。

  2. 用index作为key可能会引发的问题:

    • 若对数据进行:逆序添加、逆序删除等破坏顺序操作:
      • 会产生没有必要的真实DOM更新 ==> 界面效果没问题, 但效率低。
    • 如果结构中还包含输入类的DOM:
      • 会产生错误DOM更新 ==> 界面有问题。
  3. 开发中如何选择key?

    • 最好使用每条数据的唯一标识作为key , 比如id、手机号、身份证号、学号等唯一值。

    • 如果不存在对数据的逆序添加、逆序删除等破坏顺序操作,仅用于渲染列表用于展示,使用index作为key是没有问题的。

      还是我的观点,只是结果碰巧和正确结果一样,但是方式是不对的.

      类比小时候做选择题, 大神又快又nice, 标准答案虽然繁琐但是逻辑通顺,还有人是投骰子;一样的正确,但是方式啧啧啧,(况且,编码是要把过程露出来的,忒丢人~)

思考题:

image-20220514134445632
image-20220514134445632

把input标签绑定了 key 会怎么样?

image-20220514140432658
image-20220514140432658

完全没问题了. 从上面老师的解析可以看出来,只不过dom结构上vue识别不出来每一个input的区别,只要随便绑定个东西让他分出来区别即可.

从页面样式上看出来都是一样的,但是结果却不同,原因就是在每个input没区别.稍微加个区别即可

(so,你用了错误的方式问我一个问题,我能用一个更离谱的方式给你一个正确结果.

这是内卷.....)

031-列表过滤

代码

<body>
  <!-- 准备好一个容器-->
  <div id="root">
   <h2>人员列表</h2>
   <input type="text" placeholder="请输入名字" v-model="keyWord">
   <ul>
    <li v-for="(p,index) of filPerons" :key="index">
     {{p.name}}-{{p.age}}-{{p.sex}}
    </li>
   </ul>
  </div>

  <script type="text/javascript">
   Vue.config.productionTip = false
   
   //用watch实现
   //#region 
   /* new Vue({
    el:'#root',
    data:{
     keyWord:'',
     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:'男'}
     ],
     filPerons:[]
    },
    watch:{
     keyWord:{
      immediate:true,
      handler(val){
       this.filPerons = this.persons.filter((p)=>{
        return p.name.indexOf(val) !== -1
       })
      }
     }
    }
   }) */

   //#endregion
   
   //用computed实现
   new Vue({
    el:'#root',
    data:{
     keyWord:'',
     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:'男'}
     ]
    },
    computed:{
     filPerons(){
      return this.persons.filter((p)=>{
       return p.name.indexOf(this.keyWord) !== -1
      })
     }
    }
   }) 
  
</script>
    </body>

老规矩自己实现先~

中间有个思路, vue有个思路转换, 因为直接修改this.persons 不光会让原数组改变,再也回不来,以及会显示到页面上, 所以一般都取一个数组来获取,然后再决定怎么展示. 别修改原数据

(其实拿到后台那么一堆数据以后,也不会改原数据了~都是先存一次~)

计算属性和watch都能实现优先用计算属性~

032-列表排序

代码

<body>
  <!-- 准备好一个容器-->
  <div id="root">
   <h2>人员列表</h2>
   <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 filPerons" :key="p.id">
     {{p.name}}-{{p.age}}-{{p.sex}}
     <input type="text">
    </li>
   </ul>
  </div>

  <script type="text/javascript">
   Vue.config.productionTip = false
   
   new Vue({
    el:'#root',
    data:{
     keyWord:'',
     sortType:0//0原顺序 1降序 2升序
     persons:[
      {id:'001',name:'马冬梅',age:30,sex:'女'},
      {id:'002',name:'周冬雨',age:31,sex:'女'},
      {id:'003',name:'周杰伦',age:18,sex:'男'},
      {id:'004',name:'温兆伦',age:19,sex:'男'}
     ]
    },
    computed:{
     filPerons(){
      const arr = this.persons.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>

这种方法没什么说的,一个计算属性直接实现~

分类:

前端

标签:

JavaScript

作者介绍

Shinkai005
V1

公众号:深海笔记Shinkai