1.条件渲染

1).v-if

  • 写法:(非常暴力,会直接移除元素标签)
    • (1).v-if=”表达式”
    • (2).v-else-if=”表达式”
    • (3).v-else=”表达式”
  • 适用于:切换频率较低的场景。
  • 特点:不展示的DOM元素直接被移除。
  • 注意:v-if可以和:v-else-if、v-else一起使用,但要求结构不能被“打断”。

2).v-show(他不会暴力的去动DOM树,只会做一些样式上的隐藏)

  • 写法:v-show=”表达式”
  • 适用于:切换频率较高的场景。
  • 特点:不展示的DOM元素未被移除,仅仅是使用样式隐藏掉

3).备注:使用v-if的时,元素可能无法获取到(因为使用v-if会直接删除目标元素标签),而使用v-show一定可以获取到。

代码如下:

<body>
    <!-- 准备好一个容器-->
    <div id="root">
        <h2>当前的n值是:{{n}}</h2>
        <button @click="n++">点我n+1</button>
        <!-- 使用v-show做条件渲染 -->
        <h2 v-show="false">欢迎来到{{name}}</h2>
        <h2 v-show="1 === 1">欢迎来到{{name}}</h2>

        <!-- 使用v-if做条件渲染 -->
        <h2 v-if="false">欢迎来到{{name}}</h2>
        <h2 v-if="1 === 1">欢迎来到{{name}}</h2>

        <!-- v-else和v-else-if -->
        <div v-if="n === 1">Angular</div>
        <div v-else-if="n === 2">React</div>
        <div v-else-if="n === 3">Vue</div>
        <div v-else>未来的前端框架</div>

        <!-- v-if与template的配合使用(在渲染到页面上的时候不会改变页面结构) -->
        <template v-if="n === 1">
            <h2>你好</h2>
            <h2>五邑大学</h2>
            <h2>江门</h2>
        </template>
    </div>

   
    <script type="text/javascript">
        Vue.config.productionTip = false

        const vm = new Vue({
            el : '#root',
            data : {
                name : '德莱联盟',
                n : 0
            }
        })
    </script>
</body>

结果展示:

  • 1.使用v-show做条件渲染(v-if也是同理)
    image
  • 2.使用v-if嵌套v-else-if和v-else
    image

拓展: v-if与template的配合使用(在渲染到页面上的时候不会改变页面结构)

  • 当我们有需求使用一个条件渲染多个元素时,可以使用v-if与template的配合使用(在渲染到页面上的时候不会改变页面结构)
  • 如果使用div包裹多个元素一起渲染的话会改变页面结构:
    image
  • 但是使用 v-if 结合 template 使用则不会出现这种情况
    image

2.列表渲染(重点)

1).基本的列表渲染:(v-for的基本使用)

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

代码如下:

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

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

    <!-- 3.遍历字符串 -->
    <h2>测试遍历字符串(用得少)</h2>
    <ul>
        <li v-for="(char,index) of str" :key="index">
            {{char}}-{{index}}
        </li>
    </ul>
   
    <!-- 4.遍历指定次数 -->
    <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>

结果展示:

image

2).Key的内部实现原理(重点)

  • 面试题:react、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是没有问题的。

代码展示:(要求在张三前面添加 老刘-40 id为4)

<!-- 准备好一个容器-->
<div id="root">
    <!-- 遍历数组 -->
    <h2>人员列表(遍历数组)</h2>
    <button @click.once="add">添加一个老刘</button>
    <ul>
        <li v-for="(p,index) of 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:{
            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>

结果展示

  • 使用index作为key时:
    image
    image

  • 使用 唯一标识 id 作为 key时:
    image

原理解析(对比算法):

image

不写key Vue会默认将index作为key

image

3.列表过滤(相当于关键词搜索)

1).复习数组方法:过滤器 => filter()

  • filter() 方法创建一个新数组,其中所有元素都通过了由提供的回调函数实现的测试。
  • 注意: filter()方法不会更改原始数组。

语法如下:

Array.filter(callback(element[, index[, array]])[, thisArg])
  • filter 方法不会更改原始数组,但会返回一个新数组,其中包含满足提供的测试条件的所有元素。
  • filter 方法将回调函数作为第一个参数,并为数组的每个元素执行回调函数。
  • 在回调函数的每次迭代中,每个数组元素值都作为第一个参数传递给回调函数。

2).复习数组方法:indexOf()

  • 实现列表过滤需要配合indexOf来使用
  • indexOf() 方法可返回某个指定的字符串值在字符串中首次出现的位置,如果没有找到匹配的字符串则返回 -1。

语法如下:

//查找字符串 "welcome":
var str="Hello world, welcome to the universe.";
var n=str.indexOf("welcome");//13

3).列表过滤的结合实现:

  • 实现这个需求基本需要两个执行步骤
    • 1. 获取用户输入的信息(关键字) => 双向数据绑定 v-model
    • 2. 将获取到的信息(关键字)进行实时数据对比(filter) => 计算属性(computed)或者监视属性(watch)

代码如下:

<!-- 准备好一个容器-->
<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){//这里只需要输入的数据不需要Oldval
     //              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:{//初次读取时会执行一次,作用相当于 watch 中的 immediate
             filPerons(){
                 return this.persons.filter((p)=>{
                     // 返回数组中存在关键字的元素
                     return p.name.indexOf(this.keyWord) > -1
                 })
             }
         }
     })
</script>

结果展示:

image

4.列表排序(注意: 这种方法会改变原始数组!)

  • 列表排序用到数组的sort()方法,这里发复习一下:

这里最常用到的就是 数组的排序方法了 arr.sort()

1.默认 arr.sort()

var arr =[0,1,56,23,34,3]
arr.sort()
console.log(arr)//打印[0, 1, 23, 3, 34, 56]

2.升序 arr.sort(a , b) => a-b

var arr =[0,1,56,23,34,3]
arr.sort(a , b)=>{
return a-b
}
console.log(arr)//打印[0, 1, 23, 3, 34, 56]

3.降序 arr.sort(a , b) => b-a

var arr =[0,1,56,23,34,3]
arr.sort(a , b)=>{
return b-a
}
console.log(arr)//打印[56, 34, 23, 3, 1, 0]

进入主题(实现排序)

代码如下:

<script type="text/javascript">
Vue.config.productionTip = false

//用computed实现
new Vue({
el:'#root',
data:{
sortType:0,//设置排序类型 0为原序 1为升序 2为降序
keyWord:'',
persons:[
{id:'001',name:'马冬梅',age:9,sex:'女'},
{id:'002',name:'周冬雨',age:20,sex:'女'},
{id:'003',name:'周杰伦',age:12,sex:'男'},
{id:'004',name:'温兆伦',age:2,sex:'男'}
]
},
computed:{//初次读取时会执行一次,作用相当于 watch 中的 immediate
filPerons(){
const person = this.persons.filter((p)=>{
// 返回数组中存在关键字的元素
return p.name.indexOf(this.keyWord) > -1
})

// 判断是否需要排序
// 这里可以直接写 this.sortType 因为1和2都是真
if (this.sortType !== 0) {
person.sort((p1 , p2)=>{
return this.sortType === 1 ? p1.age-p2.age : p2.age-p1.age
})
}

// 最后返回整理好的数组
return person;
}
}
})
</script>

运行结果如下:

image
image
image