Vue 列表渲染(Day12)

55 阅读2分钟

v-for指令

  1. 用于展示列表数据
  2. 语法:v-for="(item,index) in xxx" :key="yyy"
  3. 可遍历数组、对象、字符串(使用较少)、指定次数(使用极少)
    <div id="app">
      <h3>人员列表(遍历数组)</h3>
      <ul>
        <li v-for="(p,i) in persons" :key="i">{{p.name}}-{{p.age}}</li>
      </ul>
      <h3>人员张三(遍历对象)</h3>
      <ul>
        <li v-for="(item,index) in per" :key="index">{{index}}:{{item}}</li>
      </ul>
      <h3>测试(遍历字符串,使用较少)</h3>
      <ul>
        <li v-for="(char,index) in str" :key="index">{{index}}-{{char}}</li>
      </ul>
      <h3>测试(遍历指定次数,使用较少)</h3>
      <ul>
        <li v-for="(i,index) of 5" :key="index">{{index}}-{{i}}</li>
      </ul>
    </div>
    <script>
      Vue.config.productionTip = false;
      var vm = new Vue({
        el: "#app",
        data: {
          persons: [
            { id: "001", name: "张三", age: 18 },
            { id: "002", name: "李四", age: 19 },
            { id: "003", name: "王五", age: 20 },
          ],
          per: { name: "张三", add: "上海", friend: "李四" },
          str: "hello",
        }
      });
    </script>

key的作用与原理

  1. 虚拟DOM中key的作用
    1. 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是没有问题的

列表过滤(模糊搜索)

计算属性实现

    <div id="app">
      <h3>人员列表</h3>
      <input type="text" placeholder="请输入名字" v-model="keyWord" />
      <ul>
        <li v-for="(p,i) in filPersons" :key="p.id">
          {{p.name}}-{{p.age}}--{{p.sex}}
        </li>
      </ul>
    </div>
    <script>
      Vue.config.productionTip = false;
      var vm = new Vue({
        el: "#app",
        data: {
          keyWord: "",
          persons: [
            { id: "001", name: "张三", age: 18, sex: "女" },
            { id: "002", name: "张四", age: 19, sex: "女" },
            { id: "003", name: "李二", age: 20, sex: "男" },
            { id: "004", name: "李三", age: 21, sex: "女" },
            { id: "005", name: "王二", age: 20, sex: "男" },
            { id: "006", name: "王四", age: 22, sex: "男" },
          ],
        },
        // 用计算属性实现
        computed:{
            filPersons(){
                return this.persons.filter((p)=>{
                    return p.name.indexOf(this.keyWord)!==-1
                })
            }
        }
      });

侦听属性实现

    <div id="app">
      <h3>人员列表</h3>
      <input type="text" placeholder="请输入名字" v-model="keyWord" />
      <ul>
        <li v-for="(p,i) in filPersons" :key="p.id">
          {{p.name}}-{{p.age}}--{{p.sex}}
        </li>
      </ul>
    </div>
    <script>
      Vue.config.productionTip = false;
      var vm = new Vue({
        el: "#app",
        data: {
          keyWord: "",
          persons: [
            { id: "001", name: "张三", age: 18, sex: "女" },
            { id: "002", name: "张四", age: 19, sex: "女" },
            { id: "003", name: "李二", age: 20, sex: "男" },
            { id: "004", name: "李三", age: 21, sex: "女" },
            { id: "005", name: "王二", age: 20, sex: "男" },
            { id: "006", name: "王四", age: 22, sex: "男" },
          ],
          filPersons: [],
        },
        // 用侦听属性实现
        watch: {
          keyWord: {
            immediate: true,
            handler(val) {
              this.filPersons = this.persons.filter((p) => {
                return p.name.indexOf(val) != -1;
              });
            },
          },
        },
        
      });
    </script>