vue教程 条件渲染,列表渲染

一、条件渲染

1、v-if,v-else,v-show,v-esle-if(2.1.0后新增)的使用

v-if的使用

<div v-if="isShow">
	<h2>title</h2>
	<p>detail</p>
</div>

v-else的使用

<div id="app">
    <div v-if="isShow">
        <h2>title_show</h2>
        <p>detail_show</p>
    </div>
    <div v-else>
        <h2>title_hidden</h2>
        <p>detail_hidden</p>
    </div>
</div>

v-else-if的使用

<div id="app">
    <div v-if="count>10">
        <h2>title_10</h2>
        <p>detail_10</p>
    </div>
    <div v-else-if="count>0">
        <h2>title_0</h2>
        <p>detail_0</p>
    </div>
    <div v-else>
        <h2>title_hidden</h2>
        <p>detail_hidden</p>
    </div>
</div>

v-show的使用

<div id="app">
    <div v-show="isOk">
        <h2>title_show</h2>
        <p>detail_show</p>
    </div>
    <div v-show="!isOk">
        <h2>title_hidden</h2>
        <p>detail_hidden</p>
    </div>
</div>

2、v-if与v-show的区别

  • v-if是通过移除标签来实现隐藏和显示的切换,在切换过程中条件块内的子组件以及监听器会被销毁和重建。
  • v-if在初始渲染条件为假时,则不会进行渲染,只有当v-if条件变为真的时候,才开始渲染。且v-if条件变为假的时候,直接销毁。
  • v-show,在初始化渲染条件下就会创建,且始终在内存中存在。通过css控制隐藏与现实的切换。

3、 < template >元素上使用v-if条件渲染分组

有时候会出现一组元素标签需要进行v-if进行条件渲染。通常做法是在外面包裹一个div,然后在div上进行v-if处理。当然,vue中也可以使用template标签进行一组元素标签的包裹,在template标签上做v-if处理。渲染处出来的结果不包含template

#template只起到包裹作用,自身不会被渲染到html中。
 <template v-if="isOk">
        <h2>title_show</h2>
        <p>detail_show</p>
    </template>
    <template v-else>
        <h2>title_hidden</h2>
        <p>detail_hidden</p>
    </template>

4、条件渲染的重用问题(表单元素)

被v-if,v-else-if,v-else包裹的组件或元素,vue会尽可能的复用,使用新的数据去更新旧的dom。这种效率较高的dom使用方式,有时候也会导致一些显示上的问题,主要体现在表单元素上。
重复利用dom下的显示问题情形

#vue虽然会重用input的时候,刷新palceholder,但是不能刷新value,导致切换的时候,显示同样的数据。
#当然,因为vue在重复利用旧的dom时,会尽可能的用新的数据来刷新旧的dom,如果两个input,指定v-model,在切换的时候,也会用v-model对应的变量的数据来刷新旧的dom。
<div id="app">
    <button @click="toggle">切换</button>
    <div v-if="isLogin">
        <h2>登录</h2>
        <input placeholder="请输入账号">
    </div>
    <div v-if="!isLogin">
        <h2>注册</h2>
        <input placeholder="请输入密码">
    </div>
</div>

利用key来避免元素的重复利用

<template v-if="loginType === 'username'">
  <label>Username</label>
  <input placeholder="Enter your username" key="username-input">
</template>
<template v-else>
  <label>Email</label>
  <input placeholder="Enter your email address" key="email-input">
</template>

二、列表渲染

基于数组的v-for使用

  • v-for=“item in list” 只接受value一个参数的形式。
  • v-for="(item,index) in list" 接受value,index两个参数的形式。
<div id="app">
    <div  style="margin-top: 10px; background-color: #eee" v-for="(item, index) in list"  :key="index">
        <h2>{{item.title}}</h2>
        <p>{{item.detail}}</p>
    </div>
</div>

基于对象的v-for使用

v-for遍历对象,实际是调用的object.keys(object).forEach(…)形式遍历。

  • v-for=“item in object” 只接受value一个参数的形式。
  • v-for="(item,key) in object" 接受 value,key两个参数的形式。
  • v-for="(item,key, index) in object" 接受value,key,index三个参数的形式。
 <div  style="margin-top: 10px; background-color: #eee" v-for="(value, key, index) in object"  :key="index">
        {{  key }} - {{ value }} - {{ index }}
    </div>
    
data: {
  object : {
        name : 'meng',
        age : 24,
        gender : '男'
    }
}

基于数字的v-for使用

v-for 也可以接受整数。在这种情况下,它会把模板重复对应次数。

<div v-for="item in 10">
    {{ item }}
</div>

< template>上使用v-for

< template>标签主要用于创建分组,减少外层无意义的div包裹。< template>自身不会被渲染。

<div id="app">
    <template v-for="(item,key,idnex) in object">
        <p> {{ key }} - {{item}} </p>
    </template>
</div>

维护状态

当vue更新使用v-for渲染的元素列表时,默认采用“就地更新”的策略。如果原有列表数据项的位置发生改变,比如插入,删除,排序,过滤等。vue并不会根据改变的数据的位置来修改dom的位置,而是直接用新顺序的数据,更新原有顺序的dom列表。这种刷新方式,如果有临时dom状态,或者依赖子组件状态,且这些状态不能通过新的数据项来更新,那么显示就会出现异常。 比如:


<div id="app">
    <button @click="add">新增</button>
    <div v-for="(item, index) in list" style="border: 1px solid red; margin-top: 20px">
        输如框<input type="text">
        <p>{{ item }}</p>
        <button @click="remove(index)" >删除</button>
    </div>
</div>

<script>

const vm = new Vue({
    el : '#app',
    data: {
        list: [ 'meng', 24, '男' ]
    },
    methods: {
        toggle(){
            this.isLogin = ! this.isLogin;
        },
        remove( index ){
            this.list = this.list.filter(  function( item, itemIndex ){
                  return index != itemIndex;
            });
        },
        add(){
            this.list.push(this.list.length);
        }
    }
});
</script>

与v-if切换时,利用旧的dom类似的问题,也可以利用key attribute来处理。当v-for中的dom项,指定唯一标示key之后,vue就能跟踪每个节点的身份,从而重用和重新排序现有元素。

<div v-for="item in items" v-bind:key="item.id">
	...
</div>

数组更新检测

vue只能感知到数组本身的变化,而检测不到数组内部的元素变化。但是vue对数组的一些方法进行了重写,当通过调用以下方法来改变数组元素时,vue能感知到数组内部元素的变化,从而触发视图更新.

  • push()
    push() 方法可向数组的末尾添加一个或多个元素,并返回新的长度。

    #list含有[1,2,3]
    list.push(4);
    #list含有[1,2,3,4]
    
  • pop()
    数组从末尾删除一个元素。

    #list含有[1,2,3]
    list.pop();
    #list含有[1,2]
    
  • shift()
    shift() 方法用于把数组的第一个元素从其中删除,并返回第一个元素的值。

    #list含有[1,2,3]
    list.shift();
    #list含有[2,3]
    
  • unshift()
    unshift() 方法可向数组的开头添加一个或更多元素,并返回新的长度。

    #list含有[1,2,3]
    list.unshift(4,5);
    #list含有[4,5,1,2,3]
    
  • splice()
    splice() 方法向/从数组中添加/删除项目,然后返回被删除的项目。(该方法改变原始数组)

    <div id="app">
        <button @click="add">增加</button>
        <button @click="remove">删除</button>
        <button @click="replace">替换</button>
        {{ JSON.stringify(list) }}
    </div>
    
    <script>
    
    /*
    *  splice()方法
    *   第一个参数: index 必须; 整数,规定添加,删除,替换的起始位置.
    *   第二个参数: howmany 必须; 整数,表示要删除的项目的数量.可以为0.
    *   第三个参数: item1,...,itemx
    **/
    const vm = new Vue({
        el : '#app',
        data: {
            list: [1,2,3,4,5]
        },
        methods: {
            add(){
                //指定第二个参数为0,即不删除元素;
                //指定第二个以后的参数,表示新插入的元素;
                this.list.splice(3, 0, 10);
            },
            remove(){
                //指定删除一个元素,但是不增加新元素.
                this.list.splice(3,1);
            },
            replace(){
                //用新元素替换旧的元素.
                this.list.splice(3, 1, 10,11);
            }
        }
    });
    </script>
    
  • sort()
    sort() 方法用于对数组的元素进行排序。数组在原数组上进行排序,不生成副本。不传参时默认的排序规则是: 按照字符串升序的规则排序。

    也可以传递一个回调函数,回调函数第一个参数是数组后面的值,第二个参数是前面的值。 比如[1,2,3,4], 第一个参数是2,第二个参数就是1.

    • 若a 小于 b,在排序后的数组中 a 应该出现在 b 之前,则返回一个小于0的值。
    • 若a 等于 b,则返回0。
    • 若a 大于 b,则返回一个大于0的值。
    <div id="app">
    <button @click="sort">排序</button>
    {{ JSON.stringify(list) }}
    </div>
    
    <script>
        const vm = new Vue({
            el : '#app',
            data: {
                list: [3,2,4,1,5]
            },
            methods: {
                sort(){
    
                    this.list.sort( function( first, last ){
    	
                       console.log( first, last )
                       	#这里是返回大于0,等于0,小于0的值;
                       	#而不是返回true,false的布尔值。
                        return first - last
                    } );
                }
            }
        });
    
    
  • reverse()

数组检测 和 对象检测 需要注意的问题

1、vue不能检测到利用索引改变数组项的情形
       vm.items[index] = 2; 并不会更新视图。

2、vue不能检测到数组长度修改的情形
       vm.items.length = 10;

3、在vue模板初始化后,再添加到data下的对象,不会响应式。如果确定需要某个元素,可以现在data中声明一个,初始化为null即可。


关于数组分页,过滤,排序的处理方式

1、第一种方式,定义一个过滤方法,返回一个处理后的数组

#这种方式没有缓存,每次调用都去调用方法,运算出结果。
<li v-for="n in even(numbers)">{{ n }}</li>

data: {
  numbers: [ 1, 2, 3, 4, 5 ]
},
methods: {
  even: function (numbers) {
    return numbers.filter(function (number) {
      return number % 2 === 0
    })
  }
}

2、第二种方式,定义一个计算属性,get方法返回一个处理后的数组

#这种方式利用计算属性的缓存
<li v-for="n in evenNumbers">{{ n }}</li>

data: {
  numbers: [ 1, 2, 3, 4, 5 ]
},
computed: {
  evenNumbers: function () {
    return this.numbers.filter(function (number) {
      return number % 2 === 0
    })
  }
}

v-for 和 v-if 同时作用在一个元素

当他们处于同一个节点,v-for优先级高于v-if, 也就是说 v-for先渲染出列表,然后v-if判断渲染出的列表项是否显示。

  • 如果想部分项渲染节点,这种优先级机制十分有用。

    <div v-for="item in list" bv-if="item.isSelect">
    </div>
    
  • 如果是想有条件的跳过循环的执行。可以使用< template> 或者 外面多包裹一个div,将v-if至于循环的外层元素。

    <template v-if="isShow">
         <div v-for="item in list">{{item}}</div>
    </template>
    
发布了58 篇原创文章 · 获赞 34 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/qq_36723759/article/details/104441039