vue2.0笔记《一》列表渲染

列表渲染

内容:

1.v-for

    a.渲染数组

    b.渲染对象

    c.渲染一个整数

    d.利用v-for<template> 渲染多个元素

    e.v-for with v-if

    f.一个组件的 v-for

2.数组更新检测

    a.变异方法

         key

    b.替换数组

    c.注意事项

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

4.显示过滤/排序结果

1.v-for

    a.渲染数组

<template>
  <div id="app">
    <div class='vue-demo'>
      item in items形式
      <ul class="arry-v-for-1">
        <li v-for='list in arryList'>{{list.name}}: {{list.color}}</li>
      </ul>
      <hr>
      (item,index) in items形式
      <ul class="arry-v-for-2">
        <li v-for='(list,index) in arryList'>{{list.name}}: {{list.color}}-{{index}}</li>
      </ul>
      <hr>
      item of items形式
      <ul class="arry-v-for-4">
        <li v-for='list of arryList' :key="list.id">{{list.name}}: {{list.color}}</li>
      </ul>
    </div>
  </div>
</template>
<script>
export default {
  name: 'app',
  data() {
    return {
      arryList: [{
        id: 5,
        name: '苹果',
        color: '红色'
      }, {
        id: 1,
        name: '香蕉',
        color: '黄色'
      }, {
        id: 4,
        name: '葡萄',
        color: '紫色'
      }],
      objectList: {
        'name': '小颖',
        'age': 23,
        'sex': ''
      },
      arrrys: [1,4,5,6]
    }
  },
  mounted: function() {
    this.$nextTick(function() {});
  },
  methods: {}
}

</script>
<style>
* {
  margin: 0;
  padding: 0;
}

body {
  width: 100%;
  height: 100%;
  position: absolute;
}

#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  width: 100%;
  height: 100%;
}

</style>

页面效果:

    b.渲染对象

<template>
  <div id="app">
    <div class='vue-demo'>
      item in items形式
      <ul class="object-v-for-1">
        <li v-for='value in objectList'>{{value}}</li>
      </ul>
      <hr>(item,key) in items形式
      <ul class="object-v-for-2">
        <li v-for='(value, key) in objectList'>{{ key }}: {{ value }}</li>
      </ul>
      <hr>(item,key,index) in items形式
      <ul class="object-v-for-3">
        <li v-for='(value, key, index) in objectList'>{{ key }}: {{ value }}-{{ index }}</li>
      </ul>
    </div>
  </div>
</template>
<script>
export default {
  name: 'app',
  data() {
    return {
      arryList: [{
        id: 5,
        name: '苹果',
        color: '红色'
      }, {
        id: 1,
        name: '香蕉',
        color: '黄色'
      }, {
        id: 4,
        name: '葡萄',
        color: '紫色'
      }],
      objectList: {
        'name': '小颖',
        'age': 23,
        'sex': ''
      },
      arrrys: [1, 4, 5, 6]
    }
  },
  mounted: function() {
    this.$nextTick(function() {});
  },
  methods: {}
}

</script>
<style>
* {
  margin: 0;
  padding: 0;
}

body {
  width: 100%;
  height: 100%;
  position: absolute;
}

#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  width: 100%;
  height: 100%;
}

</style>

页面效果:

    c.渲染一个整数

<template>
  <div id="app">
    <div class='vue-demo'>
      <span v-for="n in 10">{{ n }} </span>
      <!-- <hr>负10以内的整数
      <span v-for="n in -10">{{ n }} </span> -->
    </div>
  </div>
</template>

页面效果:

因为vue说:v-for 也可以取整数。在这种情况下,它将重复多次模板。所以小颖在循环正10时,想着如果是负10,页面会是什么样子,然而当使用v-for循环负10的时候,页面报错,说是 “数组长度无效” 。

循环负10

    d.利用v-for<template> 渲染多个元素

<template>
  <div id="app">
    <div class='vue-demo'>
      <ul>
        <template v-for="item in arryList">
          <li>{{ item.name }}
            <span>{{item.color}}</span>
          </li>
        </template>
      </ul>
    </div>
  </div>
</template>
<script>
export default {
  name: 'app',
  data() {
    return {
      arryList: [{
        id: 5,
        name: '苹果',
        color: '红色'
      }, {
        id: 1,
        name: '香蕉',
        color: '黄色'
      }, {
        id: 4,
        name: '葡萄',
        color: '紫色'
      }],
      objectList: {
        'name': '小颖',
        'age': 23,
        'sex': ''
      },
      arrrys: [1, 4, 5, 6]
    }
  },
  mounted: function() {
    this.$nextTick(function() {});
  },
  methods: {}
}

</script>
<style>
* {
  margin: 0;
  padding: 0;
}

body {
  width: 100%;
  height: 100%;
  position: absolute;
}

#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  width: 100%;
  height: 100%;
}
span{
  color: pink;
}
</style>

页面效果:

    e.v-for with v-if

<template>
  <div id="app">
    <div class='vue-demo'>
      <ul>
          <li v-for="item in 20" v-if="5<item && item<15">{{item}}</li>
      </ul>
    </div>
  </div>
</template>

页面效果:

    f.一个组件的 v-for

app.vue

<template>
  <div id="app">
    <div id="todo-list-example">
      <input v-model="newTodoText" v-on:keyup.enter="addNewTodo" placeholder="Add a todo">
      <ul>
        <li is="todo-item" v-for="(todo, index) in todos" v-bind:key="todo.id" v-bind:title="todo.title" v-on:remove="todos.splice(index, 1)"></li>
      </ul>
    </div>
  </div>
</template>
<script>
export default {
  name: 'app',
  data() {
    return {
      newTodoText: '',
      todos: [{
          id: 1,
          title: 'Do the dishes',
        },
        {
          id: 2,
          title: 'Take out the trash',
        },
        {
          id: 3,
          title: 'Mow the lawn'
        }
      ],
      nextTodoId: 4
    }
  },
  mounted: function() {
    this.$nextTick(function() {});
  },
  methods: {
    addNewTodo: function() {
      this.todos.push({
        id: this.nextTodoId++,
        title: this.newTodoText
      })
      this.newTodoText = ''
    }
  }
}

</script>
<style>
* {
  margin: 0;
  padding: 0;
}

body {
  width: 100%;
  height: 100%;
  position: absolute;
}

#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  width: 100%;
  height: 100%;
}

</style>

main.js

// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'

Vue.config.productionTip = false
Vue.component('todo-item', {
  template: '\
    <li>\
      {{ title }}\
      <button v-on:click="$emit(\'remove\')">X</button>\
    </li>\
  ',
  props: ['title']
});

/* eslint-disable no-new */
new Vue({
  el: '#app',
  template: '<App/>',
  components: { App }
});

页面效果:

2.数组更新检测

    a.变异方法

Vue 包含一组观察数组的变异方法,所以它们也将会触发视图更新。

  • push()
  • pop()
  • shift()
  • unshift()
  • splice()
  • sort()
  • reverse()

       在说这些数组之前,小颖想把本来在v-for中要说的 key,拿到这里来说,其实当时小颖也不知道其作用的,也是后来在执行完unshiftFun里面的代码后,再执行spliceFun代码时报错了,看了报错后,小颖才理解了官网中说的:

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

<template>
  <div id="app">
    <div id="todo-list-example">
      <ul class="arry-v-for-2">
        <li v-for='(list,index) in arryList' :key="list.id">{{list.name}}: {{list.color}}-{{index}}</li>
      </ul>
      <button @click='pushFun'>pushToChange</button>
      <button @click='popFun'>popToChange</button>
      <button @click='shiftFun'>shiftToChange</button>
      <button @click='unshiftFun'>unshiftToChange</button>
      <button @click='spliceFun'>spliceToChange</button>
      <button @click='sortFun'>sortToChange</button>
      <button @click='reverseFun'>reverseToChange</button>
      <button @click='resetFun'>Reset</button>
    </div>
  </div>
</template>
<script>
export default {
  name: 'app',
  data() {
    return {
      arryList: [{
        id: 5,
        name: '苹果',
        color: '红色'
      }, {
        id: 1,
        name: '香蕉',
        color: '黄色'
      }, {
        id: 4,
        name: '葡萄',
        color: '紫色'
      }]
    }
  },
  mounted: function() {
    this.$nextTick(function() {});
  },
  methods: {
    resetFun() {
      this.arryList = [{
        id: 5,
        name: '苹果',
        color: '红色'
      }, {
        id: 1,
        name: '香蕉',
        color: '黄色'
      }, {
        id: 4,
        name: '葡萄',
        color: '紫色'
      }]
    },
    pushFun() {
      var _a = { id: 2, name: '芒果', color: '橘色' };
      this.arryList.push(_a);
      console.log('向数组的末尾添加一个或更多元素,并返回新的长度');
      console.log(this.arryList);
    },
    popFun() {
      var popValue = this.arryList.pop();
      console.log('删除并返回数组的最后一个元素');
      console.log(popValue);
      console.log(this.arryList);
    },
    shiftFun() {
      var shiftValue = this.arryList.shift();
      console.log('删除并返回数组的第一个元素');
      console.log(shiftValue);
      console.log(this.arryList);
    },
    unshiftFun() {
      var _a = { id: 2, name: '芒果', color: '橘色' };
      this.arryList.unshift(_a);
      console.log('向数组的开头添加一个或更多元素,并返回新的长度');
      console.log(this.arryList);
    },
    spliceFun() {
      var _a = { id: 2, name: '芒果', color: '橘色' };
      this.arryList.splice(1, 0, _a);
      console.log('删除元素,并向数组添加新元素');
      console.log(this.arryList);
    },
    sortFromId(a, b) {
      return a.id - b.id;
    },
    sortFun() {
      this.arryList.sort(this.sortFromId);
      console.log('对数组的元素进行排序');
      console.log(this.arryList);
    },
    reverseFun() {
      this.arryList.reverse();
      console.log('颠倒数组中元素的顺序');
      console.log(this.arryList);
    }
  }
}

</script>
<style>
* {
  margin: 0;
  padding: 0;
}

body {
  width: 100%;
  height: 100%;
  position: absolute;
}

#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  width: 100%;
  height: 100%;
}

</style>

页面效果:

但当将   :key="list.id"   删除后,就不会报错了。看提示可知,因为里面已经有id为2的值了,而key值绑定了id,为了给 Vue 一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为每项提供一个唯一 key 属性。而当我执行完unshiftFun里面的代码后,再执行spliceFun时,此时arryList中已经有了id为2的值,再调用spliceFun方法

      var _a = { id: 2, name: '芒果', color: '橘色' };
      this.arryList.splice(1, 0, _a);

 

时,则key属性就不唯一了,此时会有两个id为2的值。现在大家理解key了吗?

   b.替换数组

变异方法 (mutation method),顾名思义,会改变被这些方法调用的原始数组。相比之下,也有非变异 (non-mutating method) 方法,例如:filter(), concat()slice() 。这些不会改变原始数组,但总是返回一个新数组

<template>
  <div id="app">
    <div id="todo-list-example">
      <ul class="arry-v-for-2">
        <li v-for='(list,index) in arryList'>{{list.name}}: {{list.color}}-{{index}}</li>
      </ul>
      <button @click='filterFun'>filterBtn</button>
      <button @click='concatFun'>concatBtn</button>
      <button @click='sliceFun'>sliceBtn</button>
    </div>
  </div>
</template>
<script>
export default {
  name: 'app',
  data() {
    return {
      arryList: [{
        id: 5,
        name: '苹果',
        color: '红色'
      }, {
        id: 1,
        name: '香蕉',
        color: '黄色'
      }, {
        id: 4,
        name: '葡萄',
        color: '紫色'
      }]
    }
  },
  mounted: function() {
    this.$nextTick(function() {});
  },
  methods: {
    filterFun() {
      var _a = this.arryList.filter(function(item) {
        return item.id > 3;
      });
      console.log('检测数值元素,并返回符合条件所有元素的数组');
      console.log(_a);
      console.log(this.arryList);
    },
    concatFun() {
      var _a = { id: 2, name: '芒果', color: '橘色' };
      var concatA = this.arryList.concat(_a);
      console.log('连接两个或更多的数组,并返回结果');
      console.log(concatA);
      console.log(this.arryList); 
    },
    sliceFun() {
      var sliceA = this.arryList.slice(1, 2);
      console.log('选取数组的的一部分,并返回一个新数组');
      console.log(sliceA);
      console.log(this.arryList);
    }
  }
}

</script>
<style>
* {
  margin: 0;
  padding: 0;
}

body {
  width: 100%;
  height: 100%;
  position: absolute;
}

#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  width: 100%;
  height: 100%;
}

</style>

页面效果:

那有什么解决方法吗?

    filterFun() {
      var _a = this.arryList.filter(function(item) {
        return item.id > 3;
      });
      console.log('检测数值元素,并返回符合条件所有元素的数组');
      // console.log(_a);
      // console.log(this.arryList);
      //解决方法:
      this.arryList = _a;
      console.log(this.arryList);
    },
    concatFun() {
      var _a = { id: 2, name: '芒果', color: '橘色' };
      var concatA = this.arryList.concat(_a);
      console.log('连接两个或更多的数组,并返回结果');
      // console.log(concatA);
      // console.log(this.arryList); 
      //解决方法:
      this.arryList = concatA;
      console.log(this.arryList);
    },
    sliceFun() {
      var sliceA = this.arryList.slice(1, 2);
      console.log('选取数组的的一部分,并返回一个新数组');
      // console.log(sliceA);
      // console.log(this.arryList);
      //解决方法:
      this.arryList = sliceA;
      console.log(this.arryList);
    }

页面效果:

 

    c.注意事项

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

  1. 当你利用索引直接设置一个项时,例如:vm.items[indexOfItem] = newValue
  2. 当你修改数组的长度时,例如:vm.items.length = newLength
<template>
  <div id="app">
    <div id="todo-list-example">
      <ul class="arry-v-for-2">
        <li v-for='(list,index) in arryList'>{{list.name}}: {{list.color}}-{{index}}</li>
      </ul>
      <ul class="arry-v-for-3">
        <li v-for='list of arrrys'>{{list}}</li>
      </ul>
      <button @click="setFun">set</button>
    </div>
  </div>
</template>
<script>
export default {
  name: 'app',
  data() {
    return {
      arryList: [{
        id: 5,
        name: '苹果',
        color: '红色'
      }, {
        id: 1,
        name: '香蕉',
        color: '黄色'
      }, {
        id: 4,
        name: '葡萄',
        color: '紫色'
      }],
      arrrys: [1, 4, 5, 6]
    }
  },
  mounted: function() {
    this.$nextTick(function() {});
  },
  methods: {
    setFun() {
      this.arryList[1] = { id: 2, name: '芒果', color: '橘色' };
      console.log(this.arryList);
      this.arrrys.length = 8;
      console.log(this.arrrys);
    }
  }
}

</script>
<style>
* {
  margin: 0;
  padding: 0;
}

body {
  width: 100%;
  height: 100%;
  position: absolute;
}

#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  width: 100%;
  height: 100%;
}

</style>

页面效果:

解决方法:

    setFun() {
      // //解决方法:
      this.$set(this.arryList, 1, { id: 2, name: '芒果', color: '橘色' });
      console.log(this.arryList);
      //解决方法:
      this.arrrys.length=8;
      this.arrrys.splice(8);
      console.log(this.arrrys);
    }

页面效果:

 

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

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

<template>
  <div id="app">
    <div id="todo-list-example">
      <ul class="arry-v-for-2">
        <li v-for='(list,index) in arryList'>{{list.name}}-{{index}}
          <input type="text" v-if="list.color" v-model="list.color">
          <span v-if="list.color">{{list.color}}</span>
        </li>
      </ul>
      <button @click="addFun">addColorPro</button>
    </div>
  </div>
</template>
<script>
export default {
  name: 'app',
  data() {
    return {
      arryList: [{
        id: 5,
        name: '苹果'
      }, {
        id: 1,
        name: '香蕉'
      }, {
        id: 4,
        name: '葡萄'
      }]
    }
  },
  mounted: function() {
    this.$nextTick(function() {});
  },
  methods: {
    addFun() {
      this.arryList.forEach(function(item){
        item.color='红色';
      });
      console.log(this.arryList);
    }
  }
}

</script>
<style>
* {
  margin: 0;
  padding: 0;
}

body {
  width: 100%;
  height: 100%;
  position: absolute;
}

#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  width: 100%;
  height: 100%;
}

</style>

页面效果:

解决方法:

将原来的addFun改为:setFun

      <button @click="setFun">setColorPro</button>
    setFun(){
      var _this=this;
      this.arryList.forEach(function(item,index){
        _this.$set(_this.arryList[index],'color','红色');
      });
      console.log(this.arryList);
    }

页面效果:

4.显示过滤/排序结果

有时,我们想要显示一个数组的过滤或排序副本,而不实际改变或重置原始数据。在这种情况下,可以创建返回过滤或排序数组的计算属性。

<template>
  <div id="app">
    <div id="todo-list-example">
      <ul class="arry-v-for-2">
        <li v-for="n in evenNumbers">{{ n }}</li>
      </ul>
    </div>
  </div>
  </div>
</template>
<script>
export default {
  name: 'app',
  data() {
    return {
      numbers: [1, 2, 3, 4, 5,16,20]
    }
  },
  computed: {
    evenNumbers: function() {
      return this.numbers.filter(function(number) {
        return number % 2 === 0
      })
    }
  },
  mounted: function() {
    this.$nextTick(function() {});
  },
  methods: {
  }
}

</script>

在计算属性不适用的情况下 (例如,在嵌套 v-for 循环中) 你可以使用一个 method 方法:

<template>
  <div id="app">
    <div id="todo-list-example">
      <ul class="arry-v-for-2">
        <li v-for="n in even(numbers)">{{ n }}</li>
      </ul>
    </div>
  </div>
  </div>
</template>
<script>
export default {
  name: 'app',
  data() {
    return {
      numbers: [1, 2, 3, 4, 5,12, 16, 20,21]
    }
  },
  mounted: function() {
    this.$nextTick(function() {});
  },
  methods: {
    even: function(numbers) {
      return numbers.filter(function(number) {
        return number % 3 === 0
      })
    }
  }
}

</script>

 

posted @ 2018-01-04 23:08  爱喝酸奶的吃货  阅读(488)  评论(0)    收藏  举报