【Vue】08 列表渲染和key的作用与原理

1.13. 列表渲染
1.13.1. 基本列表

v-for 指令
● 用于展示列表数据
● 语法:<li v-for="(item, index) of items" :key="index">,这里 key 可以是 index,更好的是遍历对象的唯一标识
● 可遍历:数组、对象、字符串(用的少)、指定次数(用的少)

<title>基本列表</title>
<script type="text/javascript" src="../js/vue.js"></script>

<div id="root">
  <!-- 遍历数组 -->
  <h3>人员列表(遍历数组)</h3>
  <ul>
    <li v-for="(p,index) of persons" :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.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>

1.13.2. key 的作用与原理 

原理 

 面试题:react、vue中的 key 有什么作用?(key的内部原理)
1、虚拟DOM中key的作用:key 是虚拟DOM中对象的标识,当数据发生变化时,Vue会根据新数据生成新的虚拟DOM,随后Vue进行新虚拟DOM与旧虚拟DOM的差异比较,比较规则如下:


2、对比规则
a、旧虚拟 DOM 中找到了与新虚拟 DOM 相同的 key
        ⅰ. 若虚拟DOM中内容没变, 直接使用之前的真实DOM。
        ⅱ . 若虚拟DOM中内容变了, 则生成新的真实DOM,随后替换掉页面中之前的真实DOM。
b、旧虚拟DOM中未找到与新虚拟DOM相同的key。
        创建新的真实DOM,随后渲染到到页面。


3、用 index 作为 key 可能会引发的问题
a、若对数据进行逆序添加、逆序删除等破坏顺序操作,会产生没有必要的真实DOM更新 ==> 界面效果没问题,但效率低。
b、若结构中还包含输入类的DOM:会产生错误DOM更新 ==> 界面有问题。

4、开发中如何选择key?
a、最好使用每条数据的唯一标识作为key,比如 id、手机号、身份证号、学号等唯一值。
b、如果不存在对数据的逆序添加、逆序删除等破坏顺序的操作,仅用于渲染列表,使用index作为key是没有问题的。

<title>key的原理</title>
<script type="text/javascript" src="../js/vue.js"></script>

<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>

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw== 编辑

1.13.3. 列表过滤

<title>列表过滤</title>
<script type="text/javascript" src="../js/vue.js"></script>

<div id="root">
  <h2>人员列表</h2>
  <input type="text" placeholder="请输入名字" v-model="keyWord">
  <ul>
    <li v-for="(p,index) of filPersons" :key="p.id">
      {{ 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: '男' }
				],
				filPersons: []
			},
			watch: {
				keyWord: {
					immediate: true,
					handler(val) {
						this.filPersons = 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: {
      filPersons() {
        return this.persons.filter((p) => {
          return p.name.indexOf(this.keyWord) !== -1
        })
      }
    }
  }) 
</script>

1.13.4. 列表排序

<title>列表排序</title>
<script type="text/javascript" src="../js/vue.js"></script>

<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 filPersons" :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: {
      filPersons() {
        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>

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值