Vue-渲染:条件渲染、列表渲染

条件渲染

v-show

显示与隐藏。
v-show=true表示显示
v-show=false表示隐藏
实现原理:调用display来控制显示与隐藏

    <div id ="root">
        <h2 v-show="false">欢迎,{{name}}</h2>
    </div>

控制台显示:
在这里插入图片描述
v-show的值当然也可以是返回值为true或false的表达式。

v-if

v-if也可以控制显示与隐藏
v-if=true表示显示
v-if=false表示隐藏
实现原理:将整个结构删除

    <div id ="root">
        <h2 v-if="false">欢迎,{{name}}</h2>
    </div>

控制台显示:
在这里插入图片描述
所以 v-if比v-show的消耗更大

v-else-if

v-if 一起使用,和 else if的用法一样:
先判断v-if是否满足条件,如果不满足再判断 v-else-if是否满足条件

        <div v-if="n===1">n=1</div>
        <div v-else-if="n===2">n=2</div>
        <div v-else-if="n===3">n=3</div>

v-else

和else用法一样,和 v-if,v-else-if 一起用:
当v-if,v-else-if 都不满足条件时就执行v-else,v-else后面无需跟条件

        <div v-if="n===1">n=1</div>
        <div v-else-if="n===2">n=2</div>
        <div v-else-if="n===3">n=3</div>
        <div v-else>哈哈</div>

v-if,v-else-if 和 v-else连用时要连着使用中间不能插入其他语句,如在v-if和v-else-if两条语句之间插入一个<div></div>,v-if和v-else-if就来不连来了,就不能正常判断了。

eg:

<!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>Document</title>
    <script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
    <div id ="root">
        <h2 v-show="true">欢迎,{{name}}</h2>
        <h2>当前的n值是:{{n}}</h2>
        <button @click="n++">点击n+1</button>
        <div v-if="n===1">n=1</div>
        <div v-else-if="n===2">n=2</div>
        <div v-else-if="n===3">n=3</div>
        <div v-else>哈哈</div>
    </div>
    <script type='text/javascript'>
    Vue.config.productionTip = false;

        new Vue({
            el:'#root',
            data: {
                name:"yang",
                n:0
            }
        })
    </script>
</body>
</html>

在这里插入图片描述

v-show 和v-if

v-if适用于切换频率较低的场景。
v-show适用于切换频率较高的场景。
使用v-if的时,元素可能无法获取到,而使用v-show一定可以获取到。

template

<template> </template>

<template>标签是模板的意思,它的一个优点是不会被解析到页面上,即不影响页面结构

template和v-if结合使用

        <template v-if="n===1">
            <h2>Hello</h2>
            <h2>你好</h2>
        </template>

解析结果:
在这里插入图片描述
外层没有template标签
而且template只能和v-if联用,不能和v-show联用。

列表渲染

v-for

循环生成:想要生成谁,就在谁身上使用v-for

遍历数组

格式:

       <ul>
        <li v-for="item in(或of) 要遍历的数组">
            {{item}}
        </li>
       </ul>

一般情况下每条数据有一个对应的key值,每条数据的key值是唯一的,遍历数组时实际上还有一个参数,代表的是数组的下标,我们通常将该参数设置为key值。

       <ul>
        <li v-for="(item,index)in 要遍历的数组" :key="index">
             {{item}}
        </li>
       </ul>

当然,如果有自己定义的id属性,也可以将key定义成自己设置的id属性:

<body>
    <div id ="root">
       <ul>
        <li v-for="(p,index) in persons" :key="p.id">
            {{p.name}}-{{p.age}}
        </li>
       </ul>
    </div>
    <script type='text/javascript'>
    Vue.config.productionTip = false;

        new Vue({
            el:'#root',
            data: {
                name:"yang",
                persons:[
                    {id:'001',name:'张三',age:18},
                    {id:'002',name:'李四',age:21},
                    {id:'003',name:'王五',age:19}
                ]
            }
        })
    </script>
</body>

在这里插入图片描述

遍历对象

格式:

 <ul>
     <li v-for="(value,key) in 对象名" :key="key">
     	{{key}}-{{value}}
     </li>
</ul>

eg:

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>Document</title>
    <script type="text/javascript" src="../js/vue.js"></script>
  </head>
  <body>
    <div id="root">
      <ul>
        <li v-for="(value,key) in person" :key="key">{{key}}-{{value}}</li>
      </ul>
    </div>
    <script type="text/javascript">
      Vue.config.productionTip = false;

      new Vue({
        el: "#root",
        data: {
          name: "yang",
          person:{
            name: "yang",
            age: 18,
            gender: "male",
          }
        },
      });
    </script>
  </body>
</html>

在这里插入图片描述

遍历字符串

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>Document</title>
    <script type="text/javascript" src="../js/vue.js"></script>
  </head>
  <body>
    <div id="root">
     <ul>
        <li v-for="(char,index) in str" :key="index">{{index}}-{{char}}</li>
      </ul>
    </div>
    <script type="text/javascript">
      Vue.config.productionTip = false;

      new Vue({
        el: "#root",
        data: {
          str:"hello"
        },
      });
    </script>
  </body>
</html>

在这里插入图片描述

遍历指定次数

<ul>
  <li v-for="(number,index) in 5" :key="index">{{index}}-{{number}}</li>
</ul>

在这里插入图片描述

v-for中key的作用与原理

key是由vue内部使用的,是供拟vue中虚拟DOM作用的。

vue数据的转化——虚拟DOM

首先我们要知道vue不是直接生成真实DOM的,而是先生成虚拟DOM,之后再转化为真实DOM.
代码:

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>Document</title>
    <script type="text/javascript" src="../js/vue.js"></script>
  </head>
  <body>
    <div id="root">
        <h2>人员列表</h2>
      <ul>
        <li v-for="(p,index) in 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: {
          name: "yang",
          persons: [
            { id: "001", name: "张三", age: 18 },
            { id: "002", name: "李四", age: 21 },
            { id: "003", name: "王五", age: 19 },
          ]
        },

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

数据转换:

在这里插入图片描述

vue中key的作用

key是虚拟DOM对象的标识,当数据发生变化时,Vue会根据新数据生成新的虚拟DOM,随后Vue会通过key进行【新虚拟DOM】与【旧虚拟DOM】的差异比较,比较规则如下:
对比规则:(Diff算法)

  1. 旧虚拟DOM中找到了与新虚拟DOM相同的key;
  • 若虚拟DOM中内容没变,直接使用之前的真实DOM
  • 若虚拟DOM中内容变了,则生成新的真实DOM随后替换掉页面中之前的真实DOM.
  1. 旧虚拟DOM中未找到与新虚拟DOM相同的key
    创建新的真实DOM,随后渲染到到页面。

演示:
代码:

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>Document</title>
    <script type="text/javascript" src="../js/vue.js"></script>
  </head>
  <body>
    <div id="root">
      <h2>人员列表</h2>
      <button @click.once="addPerson">点击添加赵六</button>
      <ul>
        <li v-for="(p,index) in 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: {
          name: "yang",
          persons: [
            { id: "001", name: "张三", age: 18 },
            { id: "002", name: "李四", age: 21 },
            { id: "003", name: "王五", age: 19 },
          ],
        },
        methods: {
          addPerson() {
            const p = { id: "004", name: "赵六", age: 23 };
            this.persons.push(p);
          },
        },
      });
    </script>
  </body>
</html>


在这里插入图片描述

点击添加按钮之后vue的处理过程(以处理一个节点为例子)

在这里插入图片描述

vue中key去index还是自定义的id

使用index出现的问题:

上述例子如果把新的数据插入到数组开头就会出现问题:

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>Document</title>
    <script type="text/javascript" src="../js/vue.js"></script>
  </head>
  <body>
    <div id="root">
        <h2>人员列表</h2>
        <button @click.once="addPerson">点击添加赵六</button>
      <ul>
        <li v-for="(p,index) in 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: {
          name: "yang",
          persons: [
            { id: "001", name: "张三", age: 18 },
            { id: "002", name: "李四", age: 21 },
            { id: "003", name: "王五", age: 19 },
          ]
        },
        methods: {
            addPerson(){
                const p ={id:"004",name:"赵六",age:23}
                this.persons.unshift(p)
            }
        },

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

添加前:
在这里插入图片描述
添加后:
在这里插入图片描述
位置不太对。
分析出现问题原因
在这里插入图片描述
这样不仅出现了错误,效率也非常底。因为由于key相同的名字不同,就将自己的名字又创建一边放在真实DOM中,就等于说所有的名字都是又创建一边的,没有实现复用,效率底。

小结
用index作为key可能会引发的问题:

  1. 若对数据进行:逆序添加、逆序删除等破坏顺序操作:
    会产生没有必要的真实DOM更新==>界面效果没问题,但效率低。
  2. 如果结构中还包含输入类的DOM:
    会产生错误DOM更新==>界面有问题。
使用自己定义的id就不会出现了:
<!DOCTYPE html>
<html lang="en">
  <head>
    <title>Document</title>
    <script type="text/javascript" src="../js/vue.js"></script>
  </head>
  <body>
    <div id="root">
        <h2>人员列表</h2>
        <button @click.once="addPerson">点击添加赵六</button>
      <ul>
        <li v-for="(p,index) in persons" :key="p.id">{{p.name}}-{{p.age}}
            <input type="text">
        </li>
      </ul>
    </div>
    <script type="text/javascript">
      Vue.config.productionTip = false;

      new Vue({
        el: "#root",
        data: {
          name: "yang",
          persons: [
            { id: "001", name: "张三", age: 18 },
            { id: "002", name: "李四", age: 21 },
            { id: "003", name: "王五", age: 19 },
          ]
        },
        methods: {
            addPerson(){
                const p ={id:"004",name:"赵六",age:23}
                this.persons.unshift(p)
            }
        },

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

添加前:
在这里插入图片描述
添加后:
在这里插入图片描述
这是因为没个对象都有自己的id作为key值,那就不会使用vue生成的index,就不会出现”错位“现象。
在这里插入图片描述

选择index还是id总结

  1. 最好使用每条数据的唯一标识作为key,比如id、手机号、身份证号、学号等唯一值。
  2. 如果不存在对数据的逆序添加、逆序删除等破坏顺序操作,仅用于渲染列表用于展示,使用index作为key是没有问题的。

列表过滤——模糊搜索

通过条件对列表进行过滤查询:

需求:输入框输入名字,可以进行搜索显示
效果:
在这里插入图片描述
在这里插入图片描述

watch实现

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>Document</title>
    <script type="text/javascript" src="../js/vue.js"></script>
  </head>
  <body>
    <div id="root">
    <input type="text" v-model="keyWord" placeholder="请输入名字">
      <ul>
        <li v-for="(p,index) in filPerson" :key="p.id">{{p.name}}-{{p.age}}-{{p.age}}</li>
      </ul>
      
    </div>
    <script type="text/javascript">
      Vue.config.productionTip = false;
      new Vue({
        el: "#root",
        data: {
          keyWord: "",
          persons: [
            { id: "001", name: "张三", age: 18,sex:"男" },
            { id: "002", name: "李四", age: 21,sex:"男" },
            { id: "003", name: "王五", age: 19,sex:"男" },
            { id: "004", name: "张浩", age: 19,sex:"男" },
            { id: "005", name: "小四", age: 19,sex:"男" },
          ],
          filPerson:[]
        },
        watch:{
            keyWord:{
                immediate:true,
                handler(newValue){
                this.filPerson = this.persons.filter((p)=>{
                    // 过滤名字中包含搜索值得数据
                    // 空串中都包含空串""
                    return p.name.indexOf(newValue)!=-1
                })
            }
            }
        }

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

计算属性实现

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>Document</title>
    <script type="text/javascript" src="../js/vue.js"></script>
  </head>
  <body>
    <div id="root">
    <input type="text" v-model="keyWord" placeholder="请输入名字">
      <ul>
        <li v-for="(p,index) in filPerson" :key="p.id">{{p.name}}-{{p.age}}-{{p.age}}</li>
      </ul>
    </div>
    <script type="text/javascript">
      Vue.config.productionTip = false;
    //   计算属性实现
    new Vue({
        el:'#root',
        data: {
          keyWord: "",
          persons: [
            { id: "001", name: "张三", age: 18,sex:"男" },
            { id: "002", name: "李四", age: 21,sex:"男" },
            { id: "003", name: "王五", age: 19,sex:"男" },
            { id: "004", name: "张浩", age: 19,sex:"男" },
            { id: "005", name: "小四", age: 19,sex:"男" },
          ]
        },
          computed:{
            filPerson(){
                return this.persons.filter((p)=>{
                    return p.name.indexOf(this.keyWord)!=-1
                })
            }

          }
        })
    </script>
  </body>
</html>

列表排序

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>Document</title>
    <script type="text/javascript" src="../js/vue.js"></script>
  </head>
  <body>
    <div id="root">
      <input type="text" v-model="keyWord" placeholder="请输入名字" />
      <button @click="sortType=2">年龄升序</button>
      <button @click="sortType=1">年龄降序</button>
      <button @click="sortType=0">原顺序</button>
      <ul>
        <li v-for="(p,index) in filPerson" :key="p.id">
          {{p.name}}-{{p.age}}-{{p.sex}}
        </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: 18, sex: "男" },
            { id: "002", name: "李四", age: 21, sex: "男" },
            { id: "003", name: "王五", age: 19, sex: "男" },
            { id: "004", name: "张浩", age: 30, sex: "男" },
            { id: "005", name: "小四", age: 19, sex: "男" },
          ],
        },
        computed: {
          filPerson() {
            const arr = this.persons.filter((p) => {
              return p.name.indexOf(this.keyWord) != -1;
            });
            if (this.sortType) {
              arr.sort((a, b) => {
                return this.sortType === 1 ? b.age - a.age : a.age - b.age;
              });
            }
            return arr;
          },
        },
      });
    </script>
  </body>
</html>

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

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值