Vue基础篇--5列表渲染v-for

Vue基础篇--5列表渲染v-for

1.用v-for把一个数组对弈为一组元素

  • 我们用v-for指令根据一组数组选项列表进行渲染。
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<script src="./vue.js"></script>
<body>
    <ul id="exp1">
        <li v-for="item in items">
            {{item.message}}
        </li>
    </ul>
</body>
<script>
    var vm =new Vue({
        el:"#exp1",
        data:{
            items:[
                {message:"Foo"},
                {message:"Bar"},
            ]
        }
    })
</script>
</html>
  • 当然v-for中,我们可以访问父作用域属性
<ul id="exp2">
        <li v-for="(item,index) in items">
            {{parentMsg}}-{{item.message}}-{{index}}
        </li>
</ul>
    var vm =new Vue({
        el:"#exp2",
        data:{
            parentMsg:"parent",
            items:[
                {message:"Foo"},
                {message:"Bar"},
                {message:"Der"},
            ]
        }
    })
  • 也可以用of代替in做为分隔符,因为它是接近JavaScript迭代器的语法:
<div v-for="item of items"></div>

2.一个对象v-for

  • 你也可以用v-for通过一个对象的属性来迭代
<ul id="exp1">
    <li v-for="value in object">
        {{value}}
    </li>
</ul>
var vm = new Vue({
    el:"#exp1",
    data:{
        object:{
            firstName:"Xu",
            lastName:"Junkai",
            age:20
        }
    }
})
  • 可以提供2个参数:键、值
<ul id="exp1">
        <li v-for="(value,key) in object">
            {{key}}:{{value}}
        </li>
    </ul>
  • 提供三个参数:键、值、索引
<ul id="exp1">
    <li v-for="(value,key,index) in object">
    {{index}}-{{key}}:{{value}}
    </li>
</ul>

3.key

  • 当Vue.js用v-for更新已渲染元素列表时,它默认用就地复用策略。如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序, 而是简单复用此处每个元素 ,并且确保它在特定索引下显示已被渲染过的每个元素。

    这个默认的模式是高效的,但是只适用于不依赖子组件状态或临时 DOM 状态

    为了给 Vue 一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为每项提供一个唯一 key 属性。理想的 key 值是每项都有的唯一 id。这个特殊的属性相当于 Vue 1.x 的 track-by ,但它的工作方式类似于一个属性,所以你需要用 v-bind 来绑定动态值 (在这里使用简写):

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

    建议尽可能在使用 v-for 时提供 key,除非遍历输出的 DOM 内容非常简单,或者是刻意依赖默认行为以获取性能上的提升。

    因为它是 Vue 识别节点的一个通用机制,key 并不与 v-for 特别关联,key 还具有其他用途,我们将在后面的指南中看到其他用途。

4.数组更新检测

变异方法

  • Vue包含一组观察数组变异方法, 所以它们也将会触发视图更新。这些方法如下:

    push()
    pop()
    shift()
    unshift()
    splice()
    sort()
    reverse()
  • 控制台输入:
    vm.items.push({message:"Dem"})

替换数组

  • 变异方法顾名思义,会改变被这些方法调用的原始数组。相比也有非编译方法,如:filter(),concat()slice(),这些不会改变原始数组,但 总是返回一个新数组。当使用非变异方法时,可以用新数组替换旧数组:
var vm =new Vue({
        el:"#exp2",
        data:{
            parentMsg:"parent",
            items:[
                {message:"Foo"},
                {message:"Foo"},
                {message:"Der"},
            ]
        }
    });
    var tm = vm.items.filter(function (item) {
        return item.message.match(/Foo/)
    });

你可能认为这将导致 Vue 丢弃现有 DOM 并重新渲染整个列表。幸运的是,事实并非如此。Vue 为了使得 DOM 元素得到最大范围的重用而实现了一些智能的、启发式的方法,所以用一个含有相同元素的数组去替换原来的数组是非常高效的操作。

注意事项

  • 由于JavaScript的限制,Vue不能检测以下变动的数组:

    1.当你利用所以直接设置一个项:例如:
      vm.items[indexOfItem] = newValue
    2.当你修改数组的长度时,例如:
      vm.items.length = newLength
  • 一个例子:
        <ul id="exp">
            <li v-for="item in items">
                {{item}}
            </li>
        </ul>
    var vm = new Vue({
        el:"#exp",
        data:{
            items:['a','b','c']
        }
    });
    vm.items[1] = "X";//不是响应性的
    vm.items.length = 2;//不是响应性的
  • 为解决第一类问题,通过以下2种方式可以实现和 vm.items[indexOfItem] = newValue 相同的效果,同时也将触发状态更新:
    //1. Vue.set
    Vue.set(vm.items, indexOfItem, newValue)
    e.g.:
    Vue.set(vm.items,1,"x");
    
    //2. Array.prototype.splice
    vm.items.splice(indexOfItem, 1, newValue)
    e.g.:
    //替换起始下标为1,长度为1的值为“xxx”
        vm.items.splice(1,1,"xxx");
  • 也可以使用vm.$set实例方法
    e.g.:
      vm.$set(vm.items,1,"x");
  • 第二类问题,可以使用splice:
    vm.items.splice(newLength)
    • 注意:目前splice只能把数组变小

5.对象更改检测注意事项

  • 由于JavaScript的限制,Vue不能检测对象属性的添加或删除。

    var vm = new Vue({
        data:{
            a:1
        }
    });
    // vm.a 响应式的
    // vm.b = 2 不是响应式的
  • 对于已经创建的实例,Vue 不能动态添加根级别的响应式属性。但是,可以使用 Vue.set(object, key, value) 方法向嵌套对象添加响应式属性。例如,对于:
<ul id="exp">
    <li v-for="value in userProfile">
        {{value}}
    </li>
</ul>
var vm = new Vue({
    el:"#exp",
    data:{
        userProfile:{
            name:"Anika",
        }
    }
});
Vue.set(vm.userProfile,"age",27)
  • 你还可以使用 vm.$set 实例方法,它只是全局 Vue.set 的别名:
// 比如在Console输入
vm.$set(vm.userProfile,"addr","beijing")
  • 有时你可能需要为已有对象赋予多个新属性,比如使用 Object.assign()_.extend()。在这种情况下,你应该用两个对象的属性创建一个新的对象。所以,如果你想添加新的响应式属性,不要像这样:
Object.assign(vm.userProfile,{hobby:'sleep',gender:'male'})
//没有响应变化
  • 而是应该这样
vm.userProfile = Object.assign({},vm.userProfile,{hobby:'sleep',gender:'male'})

6.显示过滤、排序结果

  • 有时,我们想要显示一个数组的过滤或排序副本,而不实际改变或重置原始数据。在这种情况下,可以创建返回过滤或排序数组的计算属性。
<ul id="exp">
    <li v-for="n in evenNumbers">
        {{n}}
    </li>
</ul>
// 筛选 除2 余数 为0
var vm = new Vue({
    el:"#exp",
    data:{
        numbers:[1,2,3,4,5]
    },
    computed:{
        evenNumbers:function () {
            return this.numbers.filter(function(number){
                return number % 2 === 0
            })
        }
    }
})
  • 在计算属性不适用的情况下 (例如,在嵌套 v-for 循环中) 你可以使用一个 method 方法:
data: {
  numbers: [ 1, 2, 3, 4, 5 ]
},
methods: {
  even: function (numbers) {
    return numbers.filter(function (number) {
      return number % 2 === 0
    })
  }
}

7.一段取值范围的v-for

  • v-for 也可以取整数。在这种情况下,它将重复多次模板。
<div id="exp">
    <span v-for="n in 10">{{n}}</span>
</div>
new Vue({
    el:"#exp"
})

8.v-for on a <template>

  • 类似于 v-if,你也可以利用带有 v-for 的 ` 渲染多个元素。比如:
<ul id="exp">
    <template v-for="item in items">
        <li>{{item.msg}}</li>
        <li class="divier" role="presentation"></li>
    </template>
</ul>
new Vue({
    el:"#exp",
    data:{
        items:[
            {msg:"one"},
            {msg:"two"},
            {msg:"three"},
        ]
    }
})

9.v-for with v-if

  • 当它们处于同一节点,v-for 的优先级比 v-if 更高,这意味着 v-if 将分别重复运行于每个 v-for 循环中。当你想为仅有的一些项渲染节点时,这种优先级的机制会十分有用,如下:
<ul id="exp">
    <li v-for="todo in todos" v-if="!todo.isComplete">
        {{todo.msg}}
    </li>
</ul>
new Vue({
    el:"#exp",
    data:{
        todos:[
            {isComplete:true,msg:1},
            {isComplete:false,msg:2},
            {isComplete:true,msg:3},
        ]
    }
})
  • 而如果你的目的是有条件地跳过循环的执行,那么可以将 v-if 置于外层元素 (或 <template>)上。如:
<div id="exp2">
    <ul v-if="todos.length">
        <li v-for="todo in todos">{{todo}}</li>
    </ul>
    <p v-else>No todos left!</p>
</div>
new Vue({
    el:"#exp2",
    data:{
        todos:[1,2,3]
    }
});

10.一个组件的v-for

  • 任何数据都不会被自动传递到组件里,因为组件有自己独立的作用域。为了把迭代数据传递到组件里,我们要用 props
<my-component
  v-for="(item, index) in items"
  v-bind:item="item"
  v-bind:index="index"
  v-bind:key="item.id"
></my-component>
  • 不自动将 item 注入到组件里的原因是,这会使得组件与 v-for 的运作紧密耦合。明确组件数据的来源能够使组件在其他场合重复使用。
<div id="todo-list-example">
    <!-- 提交事件不再重载页面 -->
    <form v-on:submit.prevent="addNewTodo">
        <label for="new-todo">Add a todo</label>
        <input type="text" v-model="newTodoText" id="new-todo" placeholder="E.g.">
        <button>Add</button>
    </form>
    <ul>

        <li is="todo-item" v-for="(todo,index) in todos"
            v-bind:key="todo.id"
            v-bind:title="todo.title"
            <!-- 这里定义remove事件 -->
            v-on:remove="todos.splice(index,1)"></li>
    </ul>
</div>
// props 用来接收父组件传递给子组件的数据。
//  子组件通过$emit 触发父组件remove事件。
Vue.component('todo-item',{
    template:`
    <li>
        {{ title }}
        <button v-on:click="$emit('remove')">Remove</button>
    </li>`,
    props:['title']
});
new Vue({
    el:"#todo-list-example",
    data:{
        newTodoText:"",
        todos:[
            { id:1,title:"Do the dishes"},
            { id:2,title:"Take out the trash"},
            { id:3,title:"Now the lawn"},
        ],
        nextTodoId:4
    },
    methods:{
        addNewTodo:function () {
            console.log(this);
            this.todos.push({
                id:this.nextTodoId++,
                title:this.newTodoText
            });
            this.newTodoText = ''
        }
    }
})
  • 注意这里的 is="todo-item" 属性。这种做法在使用 DOM 模板时是十分必要的,因为在 元素内只有 元素会被看作有效内容。这样做实现的效果与 `` 相同,但是可以避开一些潜在的浏览器解析错误。查看 DOM 模板解析说明 来了解更多信息。

参照文献:Vue.js列表渲染

原文地址:https://www.cnblogs.com/xujunkai/p/12215949.html

时间: 2024-10-11 01:46:30

Vue基础篇--5列表渲染v-for的相关文章

Vue基础篇--8组件基础 component

Vue基础篇--8组件基础 component 1.简单示例 <div id='components1'> <button-conter></button-conter> </div> <script> // 定义一个名为button-conter组件 Vue.component("button-conter",{ data:function () { return { count:0 } }, template:`<b

Vue 基础篇

Vue 基础篇 一.框架与库的区别 JQ库->DOM(DOM操作) + Ajax请求 art-template库->模板引擎 框架 -> 全方位.功能齐全 简易的DOM体验 + 发请求 + 模板引擎 + 路由功能 + ... 代码上的不同: 一般使用库:调用某个函数,自己可以把控库的代码 一般使用框架:其框架在帮我们运行已编写好的代码 框架:初始化自身的一些行为 执行你所编写的代码 施放一些资源 库:小而精 框架:大而全 ( 框架包含了各种库 ) 二.起步 引包 直接用 <scri

Vue基础篇--7表单输入绑定input

Vue基础篇--7表单输入绑定input 1.基础语法 你可以用 v-model 指令在表单 . 及 `元素上创建双向数据绑定.它会根据控件类型自动选取正确的方法来更新元素.尽管有些神奇,但v-model` 本质上不过是语法糖.它负责监听用户的输入事件以更新数据,并对一些极端场景进行一些特殊处理. 注意: v-model 会忽略所有表单元素的 value.checked.selected 特性的初始值而总是将 Vue 实例的数据作为数据来源.你应该通过 JavaScript 在组件的 data

Vue基础篇--6事件处理

Vue基础篇--6事件处理 1.监听事件 可以用 v-on 指令监听 DOM 事件,并在触发时运行一些 JavaScript 代码. 示例 <div id="exp"> <button v-on:click="count +=1">add 1</button> <p>The button above has been clicked {{count}} times.</p> </div> new

Bootstrap框架(基础篇)之列表,表格,表单

继续上篇的基础部分延伸,主要说一下列表,表格,表单相关Bootstrap框架变化以及基础知识. 1.列表篇 除了HTML提供的三种基本列表样式: 无序列表 <ul> <li>…</li> </ul> 有序列表 <ol> <li>…</li> </ol> 定义列表 <dl> <dt>…</dt> <dd>…</dd> </dl> Bootst

小程序基础12:列表渲染

1.列表渲染 wx:for 在组件上使用wx:for控制属性绑定一个数组,即可使用数组中各项的数据重复渲染该组件. 默认数组的当前项的下标变量名默认为index,数组当前项的变量名默认为item <view wx:for="{{array}}"> {{index}}: {{item.message}} </view> Page({ data: { array: [{ message: 'foo', }, { message: 'bar' }] } }) 使用 w

HTML5基础篇之列表相关标签和特殊字符实体

HTML字符实体 常用的字符实体: 实体字符 字符实体 大于号 (>) > 小于号 (<) < 引号 (") " 注册商标(®) ® 版权(© ) © & 号 & 空格符:&nbsp:这个空格在不同浏览器下空的距离也不同:还有一个空格符它的空格显示在各个浏览器都是一个字符的空格  一个&emsp:为空一个两个就两格依次类推. 列表的相关标签 无序列表:<ul> <li>新闻一</li> <

vue基础篇---生命周期

每个钩子函数都在啥时间触发 beforeCreate 在实例初始化之后,数据观测(data observer) 和 event/watcher 事件配置之前被调用. created 实例已经创建完成之后被调用.在这一步,实例已完成以下的配置:数据观测(data observer),属性和方法的运算, watch/event 事件回调.然而,挂载阶段还没开始,$el 属性目前不可见. beforeMount 在挂载开始之前被调用:相关的 render 函数首次被调用. mounted el 被新创

vue基础篇---vue组件《2》

定义全局组件 我们通过Vue的component方法来定义一个全局组件. <div id="app"> <!--使用定义好的全局组件--> <counter></counter> </div> <script src="./node_modules/vue/dist/vue.js"></script> <script type="text/javascript&quo