zoukankan      html  css  js  c++  java
  • Vuejs——(4)v-if、v-for

     

    目录(?)[+]

     

    (二十)v-if

    ①标准v-if用法

    简单来说,该值为true则显示该标签,为false则不显示;

    如例:

    [javascript] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. <div id="app">  
    2.     <div v-if="abc">{{abc.a}}</div>  
    3. </div>  
    4. <script>  
    5.     var vm = new Vue({  
    6.         el: '#app',  
    7.         data: {  
    8.             abc: {  
    9.                 a: "1"  
    10.             }  
    11.         }  
    12.     })<pre name="code" class="javascript">  

    </script>
    
    
    

    当abc这个对象存在时,显示这一行数据,其内容为abc.a的值;

    假如abc这个对象不存在,那么则不显示;

    也可以用另外一个变量来控制其是否显示(能否显示决定于该值隐式转换为boolean类型时是true还是false);

    例如假如上面有abc这个对象,但这个对象是空对象(没有属性a),但空对象隐式转换后为true,因此会有div,但这个div里没有内容;

    ②template v-if 包装以同时影响多个html标签;

    即假如多个标签(且他们是连续的),被一个变量控制是否显示,那么每个都这么写显然太繁琐,因此用一个template标签将这些标签包裹起来,用v-if标签控制该template标签是否显示,实际渲染时,template标签不会显示,只会显示其内的标签;

    如示例:

    [javascript] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. <div id="app">  
    2.     <template v-if="abc">  
    3.         <div>{{abc[0]}}</div>  
    4.         <div>{{abc[1]}}</div>  
    5.         <div>{{abc[2]}}</div>  
    6.     </template>  
    7. </div>  
    8. <script>  
    9.     var vm = new Vue({  
    10.         el: '#app',  
    11.         data: {  
    12.             abc: [1, 2, 3]  
    13.         }  
    14.     })  
    15. </script>  

    由于非空数组是值为true,空数组的值为false,因此方便控制;

    另外,这里只是演示,事实上更好的写法的v-for来控制内部三个标签来同时显示(当然,如果不需要显示全部的则不应该这么写);

    显示内容:

    <divid="app">

        <div>1</div>

        <div>2</div>

        <div>3</div>

    </div>

    ③v-show     用于控制该标签的display样式

    他的特点是,dom存在于页面内,已经渲染、事件绑定完毕,区别只是是否显示。

    例如:

    [javascript] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. <div v-show="a">{{test}}</div>  

    a的值为true,则正常显示;

    a的值为false,则自动添加display:none

    v-show不支持template写法(即不能同时控制多个同级连续div);

    ④v-else v-if和v-show的补充语句;

    即v-if和v-show的判断为true时,不显示v-else标签的内容;否则显示v-else标签的内容。

    例如:

    [javascript] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. <div id="app">  
    2.     <div v-show="a">{{test}}</div>  
    3.     <div v-else>def</div>  
    4. </div>  
    5. <script>  
    6.     var vm = new Vue({  
    7.         el: '#app',  
    8.         data: {  
    9.             a: true,  
    10.             test: "abc"  
    11.         }  
    12.     })  
    13. </script>  

    显示abc;

    若把data中的a改为false,则显示def;

    另外,标签之间需要连续,如以下,v-else则不能正常生效:

    [javascript] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. <div v-show="a">{{test}}</div>  
    2. <div>another</div>  
    3. <div v-else>def</div>  

    另外,不要在组件的情况下使用v-else,而是采用v-show=”!变量名”来变相起到v-else的效果

    ⑤v-if和v-show的比较

    v-if

    v-show

    渲染时间

    第一次为真时

    刚开始就渲染

    切换形式

    动态生成,局部编译/卸载

    控制display属性

    生成消耗

    较小(只生成为真的部分)

    较大(生成全部)

    切换消耗

    较大(切换时需要局部编译)

    较小(因为生成时已经渲染完成)


    v-if是在第一次条件为真时,进行渲染(比如他下面还有其他组件);

    v-show因为只是控制display的属性,因此开始就会渲染;

    (二十一)v-for列表渲染

    ①标准写法

    [javascript] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. <li v-for="i in items">{{i}}</li>  

    【1】items是一个对象或者数组;

    【2】该格式相当于for(var i in items){//略}

    【3】插值的i相当于items[i]

    【4】该li会被复制多个,然后依次被items[i]渲染,直到渲染完毕;

    示例:

    [html] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. <div id="app">  
    2.     <ul>  
    3.         <li v-for="i in items">{{i}}</li>  
    4.     </ul>  
    5. </div>  
    6. <script>  
    7.     var vm = new Vue({  
    8.         el: '#app',  
    9.         data: {  
    10.             items: {  
    11.                 a: "1",  
    12.                 b: "2",  
    13.                 c: "3"  
    14.             }  
    15.         }  
    16.     })  
    17. </script>  

    结果:

    <divid="app">

        <ul>

            <li>1</li>

            <li>2</li>

            <li>3</li>

        </ul>

    </div>

    ②索引编号:

    在标签里使用$index,即表示当前索引在v-for中的编号(从0开始);

    例如上面改为:

    [javascript] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. <li v-for="i in items">{{i}}'s index is {{$index}}</li>  
    显示的是从0~2

    ③template v-for 用于包裹多个标签的v-for

    简单来说,需要将多个标签都用v-for遍历,那么就需要用template标签。

    同样,template在实际渲染的时候不会出现,只是起到一个包裹作用。

    如代码:

    [javascript] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. <div id="app">  
    2.     <ul>  
    3.         <template v-for="i in items">  
    4.             <li>Index is {{$index}}</li>  
    5.             <li>Content is {{i}}</li>  
    6.         </template>  
    7.     </ul>  
    8. </div>  
    9. <script>  
    10.     var vm = new Vue({  
    11.         el: '#app',  
    12.         data: {  
    13.             items: {  
    14.                 a: "1",  
    15.                 b: "2",  
    16.                 c: "3"  
    17.             }  
    18.         }  
    19.     })  
    20. </script>  

    显示结果是:

    <ul>

            <li>Index is0</li><li>Content is 1</li>

            <li>Index is1</li><li>Content is 2</li>

            <li>Index is2</li><li>Content is 3</li>

    </ul>

    ④监视数组变动(修改数组)

    当data的某个属性是一个数组时,用v-for可以遍历,但显然数组是可能变动的,因此对以下变动也进行数据绑定;

    push()         数组末尾添加

    pop()           数组末尾取出

    shift()          数组开头取出

    unshift()      数组开头添加

    splice()        删除并插入

    sort()           排序

    reverse()     数组顺序颠倒

    当利用以上方法变更数组时,被渲染的内容会实时更新;

    ⑤监视数组的改变(用另一个数组进行替换)

    但数组从一个数组变为另一个数组时(记得,数组是按引用传递的),数据绑定依然生效;

    但前提是使用以下方法:

    filter()         过滤,参数是一个函数,取其返回值为true的元素被添加到新数组

    concat()       合并两个数组,返回的数组是合并后的

    slice()          返回数组的拷贝,从开始索引到结束索引(前含后不含)

    ⑥track-by(以下推测不完全确定,因为我没数据去测试)

    按照说明,假如用一个新的对象数组来替换已有的对象数组(并且两个对象数组其对象的属性不同),那么由于v-for默认是通过数据对象的特征来决定已有作用域和DOM元素的复用程度,可能导致重新渲染整个列表(比如列表很大的话可能会导致效率很低)。

    按照我的理解,大概就是从这样一个数组:(我推测是这样的)

    [javascript] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. items: [  
    2.     {name: "a", age: 10},  
    3.     {name: "b", age: 11},  
    4.     {name: "c", age: 12}  
    5. ]  

    变成这样

    [javascript] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. items = [  
    2.     {name: "A", height: 150},  
    3.     {name: "B", height: 160},  
    4.     {name: "C", height: 170}  
    5. ]  

    会导致列表重新渲染,如果列表内容特别多,那么就可能带来影响效率和性能。

    解决这种方法的办法,就是使用track-by,即加入一个包含某特定属性的标识符,当这个属性的标识符其值相等时,则尽可能复用这个已有对象的作用域和DOM元素。

    例如标签写法如下:

    [html] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. <li v-for="item in items" track-by="id">{{item.name}}</li>  

    数据从:

    [html] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. items: [  
    2.     {id: 1, name: "a", age: 10},  
    3.     {id: 2, name: "b", age: 11},  
    4.     {id: 3, name: "c", age: 12}  
    5. ]  

    变为:

    [html] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. items = [  
    2.     {id: 3, name: "A", height: 150},  
    3.     {id: 2, name: "B", height: 160},  
    4.     {id: 1, name: "C", height: 170}  
    5. ]  

    那么在替换时,会复用。

    注意,复用并不是使用之前同id的对象所在的dom位置,例如并不会将name=C的元素放在原有的name=a的元素的位置(即使他们id都为1),而是依然根据数组下标的顺序来显示数据。

    ⑦track-by=”$index”(不确定+1)

    当数组没有某一个共同属性时(比如上面的id),但依然需要复用的话,那么就用这个。

    他会强制v-for进入原位更新模式,片断不会被移动(我推测这个片断指v-for的dom标签),简单的根据对应的索引的值来刷新dom,这种模式可以处理数组中重复的值。(应该是指对于重复的值,比如像上面那种id为同一个数值的,也可以正常复用)。

    由于替换方式简单暴力(索引肯定是一样的),所以高效。

    ————————————————————————

    这让数据替换非常高效,但是也会付出一定的代价。因为这时DOM 节点不再映射数组元素顺序的改变,不能同步临时状态(比如 <input> 元素的值)以及组件的私有状态。因此,如果 v-for 块包含 <input> 元素或子组件,要小心使用 track-by="$index"

    ——————我表示以上这段话没看懂——————

    如以下代码,reverse()依然在起作用啊

    [javascript] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. <div id="app">  
    2.     <ul>  
    3.         <li v-for="item in items" track-by="$index">{{item.name}}</li>  
    4.     </ul>  
    5.     <button onclick="chagne()">change</button>  
    6. </div>  
    7. <script>  
    8.     var vm = new Vue({  
    9.         el: '#app',  
    10.         data: {  
    11.             items: [  
    12.                 {id: 1, name: "a", age: 10},  
    13.                 {id: 2, name: "b", age: 11},  
    14.                 {id: 3, name: "c", age: 12}  
    15.             ]  
    16.         }  
    17.     })  
    18.     function chagne() {  
    19.         vm.items = [  
    20.             {id: 3, name: "A", height: 150},  
    21.             {id: 2, name: "B", height: 160},  
    22.             {id: 1, name: "C", height: 170}  
    23.         ];  
    24.         vm.items.reverse();  
    25.     }  
    26. </script>  

    ⑧数组的一些方法:

    $set(索引, 被替换的值)

    简单来说,以下代码是不会触发数据绑定的:

    [javascript] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. vm.items[0] = {name: "test"};  

    替代方法是:

    [javascript] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. vm.items.$set(0, {name: "test"});  

    $remove(被移除的对象)

    假如要移除某个对象(注意,由于对象是按引用传递,因此不能简单用看起来一样的对象来移除某个对象),可以直接使用这个方法。具体代码是:

    [javascript] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. <script>  
    2.     var test = {name: "test"};  
    3.     var vm = new Vue({  
    4.         el: '#app',  
    5.         data: {  
    6.             items: [  
    7.                 {name: "a"},  
    8.                 {name: "b"},  
    9.                 {name: "c"}  
    10.             ]  
    11.         }  
    12.     })  
    13.     vm.items.push(test);  
    14.     function chagne() {  
    15.         vm.items.$remove(test);  
    16.         //vm.items.$remove({name: "test"}); //注意,这种写法是错误的  
    17.     }  
    18. </script>  

    他相当于先用indexOf找到该对象的索引,再用splice来从数组中移除该对象。

    Object.freeze(数组的对象元素)

    假如数组中某一个元素(他是个对象)被Object.freeze冻结了,需要明确指定track-by,这种情况下,如果Vuejs不能自动追踪对象,将给出一条警告。

    ——不懂!——

    反正被这样搞的对象,其值不能被修改,修改其值也没用(修改无效)

    ⑨$key用于获取被遍历对象的key值

    即js代码中,for(var i in items)中的i,记得,在v-for里,其是items[i]

    但仅对object对象生效,对数组无效(数组可以使用$index)

    如代码:

    [javascript] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. <div id="app">  
    2.     <ul>  
    3.         <li v-for="item in items" track-by="$index">{{$key}}: {{item}}</li>  
    4.     </ul>  
    5. </div>  
    6. <script>  
    7.     var test = {name: "test"};  
    8.     var vm = new Vue({  
    9.         el: '#app',  
    10.         data: {  
    11.             items: {  
    12.                 name: "wd",  
    13.                 age: "27",  
    14.                 sex: "man"  
    15.             }  
    16.         }  
    17.     })  
    18. </script>  

    显示内容为:

    • name: wd
    • age: 27
    • sex: man

    这个key也可以使用别名,方法很简单,标签如下写:

    [javascript] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. <li v-for="(a_key,item) in items" track-by="$index">{{a_key}}: {{item}}</li>  

    这里的a_key就相当于$key

    且他们之间不会互相冲突,并能同时使用。

    注意:别名对数组有效,$key对数组无效

    ⑩遍历顺序:

    按照Object.keys()的结果遍历

    例如:

    [javascript] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. var a = {a: 1, b: 2, c: 3};  
    2. Object.keys(a)  

    其返回结果是:

    [html] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. ["a", "b", "c"]  

    然后会按照这个顺序来遍历,但其结果可能会因为JavaScript引擎的不同而不同(受影响的是对象);

    ⑪v-for一个数字

    可以对一个数字使用v-for,例如:


    [html] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. <li v-for="(a_key,item) in 10" track-by="$index">{{a_key}}: {{item}}</li>  

    【1】这个数字可以是一个浮点数;

    【2】从0开始,到小于这个数字的最大整数(例如10那么则到9,10.1则到10);

    ⑫显示过滤、排序后的结果:

    【1】使用计算属性(computed),返回过滤、排序后的结果;

    优点:可自定义,功能更强大,更灵活;

    缺点:麻烦;

    【2】使用内置过滤器filterBy和orderBy

    链接:http://cn.vuejs.org/api/#filterBy

    【3】filterBy

    简单来说,如果没有被过滤的内容,则被过滤掉,

    如果是对象,则对key和val都有效(都会被检索),

    如代码:

    [html] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. <div id="app">  
    2.     <input v-model="input"/>  
    3.     <p>请在输入框内输入内容,只会将符合条件的内容显示出来</p>  
    4.     <ul>  
    5.         <li v-for="item in items|filterBy input">{{item}}</li>  
    6.     </ul>  
    7. </div>  
    8. <script>  
    9.     var test = {name: "test"};  
    10.     var vm = new Vue({  
    11.         el: '#app',  
    12.         data: {  
    13.             input: "",  
    14.             items: {  
    15.                 name: "wd",  
    16.                 age: "27",  
    17.                 sex: "man"  
    18.             }  
    19.         }  
    20.     })  
    21. </script>  


    注意:

    (1)假如输入‘a’,虽然name属性和age属性的值没有a,但是其key有,所以依然会显示;

    (2)不能只对其值(如果v-for的是一个对象的话)过滤生效,比如

    [html] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. <li v-for="item in items|filterBy input in 'item'">{{item}}</li>  

    是无效的写法!

    (3)如果要使用(2)中的方法,必须只能面对对象数组;

    如以下:

    [html] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. <div id="app">  
    2.     <input v-model="input"/>  
    3.     <p>请在输入框内输入内容,只会显示name符合的</p>  
    4.     <ul>  
    5.         <li v-for="(key,item) in items|filterBy input in 'name'">age:{{item.age}},name:{{item.name}}</li>  
    6.     </ul>  
    7. </div>  
    8. <script>  
    9.     var test = {name: "test"};  
    10.     var vm = new Vue({  
    11.         el: '#app',  
    12.         data: {  
    13.             input: "",  
    14.             items: [  
    15.                 {age: 1, name: "abc"},  
    16.                 {age: 2, name: "ab"},  
    17.                 {age: 3, name: "c"}  
    18.             ]  
    19.         }  
    20.     })  
    21. </script>  

    (4)多字段过滤

    如以下:

    [html] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. <li v-for="(key,item) in items|filterBy input in 'name''age'">age:{{item.age}},name:{{item.name}}</li>  

    无论是age符合或者是name符合,都可以正常显示。

    (5)动态多字段过滤

    [html] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. <div id="app">  
    2.     <input v-model="input"/>  
    3.     <p>请在输入框内输入内容,只会显示name符合的</p>  
    4.     <ul>  
    5.         <li v-for="(key,item) in items|filterBy input in List">age:{{item.age}},name:{{item.name}}</li>  
    6.     </ul>  
    7.     <button @click="change">点击搜索age</button>  
    8. </div>  
    9. <script>  
    10.     var test = {name: "test"};  
    11.     var vm = new Vue({  
    12.         el: '#app',  
    13.         data: {  
    14.             input: "",  
    15.             List: "name",  
    16.             items: [  
    17.                 {age: 1, name: "abc"},  
    18.                 {age: 2, name: "ab"},  
    19.                 {age: 3, name: "c"}  
    20.             ]  
    21.         },  
    22.         methods: {  
    23.             change: function () {  
    24.                 this.List = "age";  
    25.             }  
    26.         }  
    27.     })  
    28. </script>  

    (1)初始过滤name,点击按钮过滤age;

    (2)List可以是字符串,也可以是数组;

    (3)动态改变依然会生效;

    【4】orderBy

    用于排序的过滤,可以加参数,参数>=0则为正序排序,<0则为倒序排序

    普通写法:

    [html] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. <li v-for="(key,item) in items|orderBy 'age'">age:{{item.age}},name:{{item.name}}</li>  

    根据age值,正序排列,显示:

    • age:2,name:ab
    • age:3,name:c
    • age:4,name:abc
    [html] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. <li v-for="(key,item) in items|orderBy 'name' -1"> age:{{item.age}},name:{{item.name}}</li>  

    根据name,倒序排列(因为参数为-1,其<0),字符串的排列顺序为逐字母比较顺序。

    也可以使用函数作为排序条件,具体而言,如代码:

    [html] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. <div id="app">  
    2.     <input v-model="input"/>  
    3.     <p>请在输入框内输入内容,只会显示name符合的</p>  
    4.     <ul>  
    5.         <li v-for="(key,item) in items|orderBy test">age:{{item.age}},name:{{item.name}}</li>  
    6.     </ul>  
    7.     <button @click="test">点击搜索age</button>  
    8. </div>  
    9. <script>  
    10.     var test = {name: "test"};  
    11.     var vm = new Vue({  
    12.         el: '#app',  
    13.         data: {  
    14.             items: [  
    15.                 {age: 5, name: "abc"},  
    16.                 {age: 2, name: "ab"},  
    17.                 {age: 13, name: "c"},  
    18.                 {age: 33, name: "c"},  
    19.                 {age: 3, name: "c"}  
    20.             ]  
    21.         },  
    22.         methods: {  
    23.             test: function (a, b) {  
    24.                 return a.age - b.age;  
    25.             }  
    26.         }  
    27.     })  
    28. </script>  

    他会根据age的值差进行排序,简单来说,a-b则为从小到大(这里指的是被排序的属性)),b-a则为从大到小。

    如图结果为:

    • age:2,name:ab
    • age:3,name:c
    • age:5,name:abc
    • age:13,name:c
    • age:33,name:c
  • 相关阅读:
    【Redis】搭建主从复制
    【安装】Ubuntu之Docker
    【安装】Ubuntu之MySQL
    【Docker】Dockerfile构建指令
    【Docker】常用命令
    【14】Flask 请求上下文
    【13】Flask 上下文前夕
    【12】Flask 分析线程和协程
    【11】Flask 高级进阶
    【10】Flask 高级摘要
  • 原文地址:https://www.cnblogs.com/-ding/p/6339671.html
Copyright © 2011-2022 走看看