Vue知识点整理(一)- Vue核心(4)- 列表渲染和数据监测

  • Post author:
  • Post category:vue



目录


一、列表渲染


1.1 列表渲染指令


1.2 简单案例练习 – 列表渲染指令使用


1.3 key作用与原理(重要)


1.4 列表过滤和列表排序


1.4.1 列表过滤


1.4.2 列表排序


二、Vue监视数据


2.1 Vue监视数据的原理


2.2 案例练习


一、列表渲染

1.1 列表渲染指令

v-for指令:

  1. 用于展示列表数据
  2. 语法:v-for= “(item, index) in xxx”  :key = “yyy”
  3. 可遍历:数组、对象、字符串(较少使用)、指定次数(较少使用)

1.2 简单案例练习 – 列表渲染指令使用

  <body>
    <div class="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,key) of game" :key="key">{{key}} -- {{value}}</li>
      </ul>

      <!-- 遍历字符串 -->
      <h2>测试遍历字符串(较少使用)</h2>
      <ul>
        <li v-for="(char,index) of str" :key="index">{{index}} -- {{char}}</li>
      </ul>

      <!-- 遍历指定次数 -->
      <h2>测试遍历指定次数(较少使用)</h2>
      <ul>
        <li v-for="(number,index) of 5" :key="index">
          {{index}} -- {{number}}
        </li>
      </ul>
    </div>
  </body>
  <script>
    Vue.config.productionTip = false;

    new Vue({
      el: ".root",
      data: {
        persons: [
          { id: "001", name: "张三", age: "20" },
          { id: "002", name: "李四", age: "21" },
          { id: "003", name: "王五", age: "22" },
        ],
        game: {
          name: "艾尔登法环",
          price: "¥298",
          creater: "宫崎英高",
        },
        str: "hello",
      },
    });
  </script>

1.3 key作用与原理(重要)

vue中key有什么作用?(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是没有问题的

1.4 列表过滤和列表排序

1.4.1 列表过滤

采用计算属性computed实现

  <body>
    <div class="root">
      <h2>人员列表</h2>
      <input type="text" placeholder="请输入名字" v-model="keyWord" />
      <ul>
        <li v-for="(p,index) of filPerson" :key="index">
          {{p.name}} - {{p.age}} - {{p.sex}}
        </li>
      </ul>
    </div>
  </body>
  <script>
    Vue.config.productionTip = false;

    new Vue({
      el: ".root",
      data: {
        keyWord: "",
        persons: [
          { id: "001", name: "马冬梅", age: "20", sex: "女" },
          { id: "002", name: "周冬雨", age: "21", sex: "女" },
          { id: "003", name: "周杰伦", age: "22", sex: "男" },
          { id: "004", name: "温兆伦", age: "23", sex: "男" },
        ],
      },
      computed: {
        filPerson() {
          return this.persons.filter((p) => {
            return p.name.indexOf(this.keyWord) !== -1;
          });
        },
      },
    });
  </script>

采用数据侦听watch实现

    // watch写法
    new Vue({
      el: ".root",
      data: {
        keyWord: "",
        persons: [
          { id: "001", name: "马冬梅", age: "20", sex: "女" },
          { id: "002", name: "周冬雨", age: "21", sex: "女" },
          { id: "003", name: "周杰伦", age: "22", sex: "男" },
          { id: "004", name: "温兆伦", age: "23", sex: "男" },
        ],
        filPerson: [],
      },
      watch: {
        keyWord: {
          immediate: true,
          handler(val) {
            this.filPerson = this.persons.filter((p) => {
              return p.name.indexOf(val) !== -1;
            });
          },
        },
      },
    });

1.4.2 列表排序

  <body>
    <div class="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 filPerson" :key="index">
          {{p.name}} - {{p.age}} - {{p.sex}}
        </li>
      </ul>
    </div>
  </body>
  <script>
    Vue.config.productionTip = false;

    // computed实现
    new Vue({
      el: ".root",
      data: {
        keyWord: "",
        sortType: 0, //0原顺序,1降序,2升序
        persons: [
          { id: "001", name: "马冬梅", age: "24", sex: "女" },
          { id: "002", name: "周冬雨", age: "21", sex: "女" },
          { id: "003", name: "周杰伦", age: "20", sex: "男" },
          { id: "004", name: "温兆伦", age: "23", sex: "男" },
        ],
      },
      computed: {
        filPerson() {
          const arr = this.persons.filter((p) => {
            return p.name.indexOf(this.keyWord) !== -1;
          });
          // 判断是否需要排序, 可直接判断布尔值,0为false,1和2都为true
          if (this.sortType) {
            arr.sort((p1, p2) => {
              return this.sortType === 1 ? p2.age - p1.age : p1.age - p2.age;
            });
          }
          return arr;
        },
      },
    });

二、Vue监视数据

2.1 Vue监视数据的原理


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)使用这些API:push()、pop()、shift()、unshift()、splice()、sort()、reverse()

(2)Vue.set() 或 vm.$set()



注意:Vue.set() 和vm.$set() 不能给vm 或 vm的根数据对象 添加属性

2.2 案例练习

  <body>
    <div class="root">
      <h2>学生信息</h2>
      <button @click="student.age ++">年龄+1</button><br />
      <button @click="addSex">添加性别属性,默认值:男</button><br />
      <button @click="student.sex = '未知'">修改性别属性:未知</button><br />
      <button @click="addFriend">在列表首位添加一个朋友</button><br />
      <button @click="updateFirstFriendName">修改第一个朋友的名字为:Tom</button
      ><br />
      <button @click="addHobby">添加一个爱好</button><br />
      <button @click="updateHobby">修改第一个爱好为:露营</button><br />
      <h3>姓名:{{student.name}}</h3>
      <h3>年龄:{{student.age}}</h3>
      <h3 v-if="student.sex">性别:{{student.sex}}</h3>
      <h3>爱好:</h3>
      <ul>
        <li v-for="(h,index) in student.hobby" :key="index">{{h}}</li>
      </ul>
      <h3>好友:</h3>
      <ul>
        <li v-for="(f,index) in student.friends" :key="index">
          {{f.name}} -- {{f.age}}
        </li>
      </ul>
    </div>
  </body>
  <script>
    Vue.config.productionTip = false;

    const vm = new Vue({
      el: ".root",
      data: {
        student: {
          name: "王小明",
          age: "24",
          hobby: ["篮球", "电子游戏", "唱歌"],
          friends: [
            { name: "周星星", age: "20" },
            { name: "吴仔", age: "30" },
          ],
        },
      },
      methods: {
        addSex() {
          // 两种写法
          // Vue.set(this.student, "sex", "男");
          vm.$set(this.student, "sex", "男");
        },
        addFriend() {
          this.student.friends.unshift({ name: "张三", age: "18" });
        },
        updateFirstFriendName() {
          this.student.friends[0].name = "Tom";
        },
        addHobby() {
          this.student.hobby.push("拳击");
        },
        updateHobby() {
          // 三种写法
          // this.student.hobby.splice(0, 1, "露营");
          // Vue.set(this.student.hobby,0,'露营');
          vm.$set(this.student.hobby, 0, "露营");
        },
      },
    });
  </script>



版权声明:本文为JHY97原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。