v-for%20%E5%92%8C%20%E4%BD%BF%E7%94%A8%E7%BB%84%E4%BB%B6%E7%9A%84%20v-for%20%E5%8C%BA%E5%88%AB%EF%BC%9A">不使用组件的v-for 和 使用组件的 v-for 区别:
1. 可重复使用性:
组件是可以重复使用模板;
2. 触发事件的方法:
3.访问数据:
- 组件要通过创建prop 来获取data的数据,原因:
1)组件模板中,无法直接访问vue 实例的 data 数据。可以通过在组件创建prop 属性,通过 html 层面把 这个prop 属性绑定vue实例数据,然后在组件中访问这个prop,最终获取vue 实例中的数据。
组件中创建prop属性 ==》 html 层面上再元素绑定 prop 到vue 实例数据 ==》 组建中 通过{{ prop }} 可访问 实例数据
2) 因为组件是可以重复使用的,每使用一次组件,就会创建独立一份专属的prop。以此来实现组件和数据的复用;
- 不使用组件,直接在html 层面使用 {{ }} 双括号访问实例的data数据
4. 使用组件时,<ul>、<ol>、<table>、<select> 特殊元素要用"is" 特性绑定内部元素 。
<li> 元素想要使用组件<todo-item>模板,需要用绑定:<li is="todo-item">。因为<ul>元素固定使用<li>元素,不能直接使用组件的自定义元素。因为DOM模板格式限制,<ul>、<ol>、<table>、<select> 这些元素内部只能使用<li>、<tr>、<option>元素。详见:ul、ol、table、select 元素使用"is"特性:约束元素不能直接使用组件
以下用两种方法写一个todolist
方法一:组件 和 v-for 一起使用
html 部分代码:
<div id="todo-list-example"> <!--v-model prevent 修饰符:阻止默认事件发生。这里阻止 submit 提交表单的动作--> <!--v-on 把 submit事件和实例方法“addNewTodo”绑定。"submit"事件属性只能用于 form 元素--> <form v-on:submit.prevent="addNewTodo" > <label for="new-todo">Add a todo</label> <!--v-model 绑定的是input 的value 值。"newTodoText" 是实例定义数据,为空,使 每次输入后文本框的值清空--> <input v-model="newTodoText" id="new-todo" placeholder="E.g. Feed the cat"> <button >Add</button> </form> <ul> <!--用绑定prop 的方式获取 data 数据 <!-- 绑定key,值为数据属性的 todo.id--> <!--用prop获取data数据:先创建组件的 prop:value,然后用v-for绑定data里面的 todo.title,来获取data数据--> <!--用"is"绑定 <li> 元素和组件<todo-item>, 因为<ul>元素固定使用<li>元素,不能直接使用组件的自定义元素--> <li is="todo-item" v-for="(todo, index) in todos" v-bind:key="todo.id" v-bind:value="todo.title" v-on:remove="todos.splice(index, 1)"> </li> </ul> </div>
Vue.component('todo-item', { //通过组件的 prop value 访问数据(html 层面已将prop 绑定到vue 实例的data数据,所以通过prop 可以访问到 vue实例的data数据) //用emit 绑定"remove" 自定义事件。 //emit 在模板中,把"remove" 事件发射到 html 层面。因为html 代码的 li 元素里用"remove" 绑定了一个函数,所以最后触发的是这个函数 "todos.splice(index, 1)" 删除相对应index 的todo 数据,也就是删除当前这条数据 template:` <li> {{ value }} <button v-on:click="$emit(\'remove\')">Remove</button> </li> `, //创建prop value 来储存数据 props: ['value'] }) //vue 实例部分代码 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: 'Mow the lawn' } ], nextTodoId: 4 }, methods: { addNewTodo: function () { //用push 方法把新的 id 和 title 添加进 todo 列表 //title: this.newTodoText 因为在上面的<input> 元素绑定了 v-model="newTodoText" 双向绑定了输入框的value,所以触发这个函数时,title 会获取这个input 输入框的value 值 this.todos.push({ id: this.nextTodoId++, title: this.newTodoText }) //提交新数据后,清空input 的value值(因为上面的<input> 元素双向绑定了 v-model="newTodoText") this.newTodoText = '' } } }) </script>
另一个例子:
在 html 层面上,用组件的props--"mans" 绑定数据 v-bind:mans="persons"(此时 data 里面的 persons 数据被传到这个 props--"mans" 里面了),
然后在组件模板中,"mans" 已经获得了父组件的数据,就可以直接使用了
<div id="app"> <ul> <li is="acomp" v-bind:mans="persons" > </li> </ul> </div> <script> Vue.component('acomp',{ props:["mans"], //html 层面上,把数据传给props--"mans"之后,在组件内就可以接收并使用了 template:` <ul> <li v-for="(man, index) in mans" v-bind:key="man.id">{{man.food}}</li> </ul> ` }) new Vue({ el: '#app', data:{ persons:[ { id:1, name:"ling", food:"chocolate"}, { id:2, name:"biao", food:"meat"} ] } }) </script>
方法二:不使用组件,使用v-for
html 部分代码:
<div id="todo-list-example"> <form v-on:submit.prevent="addNewTodo" > <label for="new-todo">Add a todo</label> <input v-model="newTodoText" id="new-todo" placeholder="E.g. Feed the cat"> <button >Add</button> </form> <ul> <li v-for="(todo, index) in todos" v-bind:key="todo.id"> {{todo.title}} <button v-on:click="todos.splice(index, 1)">Remove</button> </li> </ul> </div>
vue 实例部分代码:
//vue 实例 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: 'Mow the lawn' } ], nextTodoId: 4 }, methods: { addNewTodo: function () { this.todos.push({ id: this.nextTodoId++, title: this.newTodoText }) this.newTodoText = '' } } })
网页渲染效果:
issolve/70" width="419" />
issolve/70" width="376" />
issolve/70" width="356" />
issolve/70" width="353" />