List Rendering

v-forwith an Array

重複< li >。所以將v-for寫在< li >上面。

印出一個array,所以將array丟進for-in

HTML
< ul id="v-for-array">
  < li v-for="item in items">
    {{ item.message }}
  < /li >
< /ul >
Javascript
var example1 = new Vue({
  el: '#v-for-array',
  data: {
    items: [
      { message: 'Foo' },
      { message: 'Bar' }
    ]
  }
})
Result:

其中,in可以換成of

< li v-for="item in items"> 也可以用 < li v-for="item of items">

v-for with an Object

印出一個object成員變數,所以將object丟進for-in

HTML
< ul id="v-for-object" class="demo">
  < li v-for="value in object">
    {{ value }}
  < /li >
< /ul >
Javascript
new Vue({
  el: '#v-for-object',
  data: {
    object: {
      firstName: 'John',
      lastName: 'Doe',
      age: 30
    }
  }
})
Result:

印出key-value

HTML
< div v-for="(value, key) in object">
  {{ key }}: {{ value }}
< /div >
Result:
{{ key }}: {{ value }}

印出index

0起始計數。

HTML
< div v-for="(value, key) in object">
   {{ index }}. {{ key }}: {{ value }}
< /div >
Result:
{{ index }}. {{ key }}: {{ value }}
不保證順序每次都相同。

key的用法!!

目前對這個功能還不了解!!!有找到一篇文章可以參考
{{ index }}. {{ key }}: {{ value }}

Array Change Detection

陣列經過這些function都會觸發更新畫面

修改元素,修改原陣列

修改元素, 回傳新陣列

example
< ul id="example-1" >
  < li v-for="item in items" >
    {{ item.message }}
  < /li >
< /ul >

在這個例子可以打開console輸入array_methods.items.push({ message: 'Baz' })可以立即新增元素到畫面上

Replacing an Array

無論js是回傳新的array,還是修改原本的array,vue在渲染DOM的行為,都是高效能的。

Caveats

因為javascript的限制,Array有些操作方式無法觸發「Vue重新渲染」,不過在此也提供了一些解決方式。

  1. 當你利用索引直接設置一個項時,例如: vm.items[indexOfItem] = newValue
  2. 當你修改數組的長度時,例如: vm.items.length = newLength
1. 的解決方式

Vue.set()

// Vue.set
Vue.set(example1.items, indexOfItem, newValue)

Array.prototype.splice

// Array.prototype.splice
example1.items.splice(indexOfItem, 1 , newValue)
2. 的解決方式

Array.prototype.splice

// Array.prototype.splice
example1.items.splice(newLength)

Object Change Detection Caveats

在此官方中文版文件....換章節!!

有時,我們想要添加新屬性到已存在的物件上,好讓物件可以渲染到畫面上。(也許就是call兩支api的情況??)

因為javascript的限制,Object有些操作方式無法觸發「Vue重新渲染」,不過在此也提供了一些解決方式。

var vm = new Vue({
  data: {
    a: 1
  }
})
// 賦值`vm.a`有反應
vm.b = 2
// 新增`vm.b`無反應

Vue不允許動態地向已創建的實例添加新的根級別的反應屬性。
但是,可以使用Vue.set(object, key, value)方法向嵌套對象添加反應屬性。
例如,給出:

var obj_update = new Vue({
    data: {
        el: '#obj-update'
        userProfile: {
            name: 'Anika'
        }
    }
})
example
{{index}}, {{key}}, {{property}}
然後,想要在obj_update.userProfile裡加入新的變數,打開console輸入:
Vue.set(obj_update.userProfile, 'age', 27)
或者在Vue物件內的methods時,用vm.$set取代全域的Vue.set
methods: {
    add: function (key, value) {
        this.$set(this.userProfile, key, value);
    }
}
console可以這樣輸入,新增元素到畫面。
obj_update.add('age', 27)

有時,如果你想要添加數個變數,例如使用Object.assign()_.extend()進行物件屬性的合併。
但是,這樣添加的話是不會觸發更新畫面的。

Object.assign(obj_update.userProfile, {
  age: 27,
  favoriteColor: 'Vue Green'
})

要解決這個問題,要用一個新的物件賦值

可以直接在console貼上這一段。上面的資料會動態渲染唷。

const newUserProfile = Object.assign({}, obj_update.userProfile, {
  age: 27,
  favoriteColor: 'Vue Green'
})
obj_update.userProfile = newUserProfile;

Displaying Filtered/Sorted Results

有時,我們想要顯示 過濾/排序 的資料副本。

這裡有一個「顯示偶數」的例子

HTML
< li  v-for = "n in evenNumbers" > {{ n }} < /li >
Javascrit
data: {
  numbers : [ 1 , 2 , 3 , 4 , 5 ]
},
computed : {
  evenNumbers : function () {
    return  this .nu​​mbers.filter( function ( number ) {
      return number % 2 === 0
    })
  }
}
Result
  • {{ n }}
  • 可以用一個取偶數Method HTML
    < li v-for="n in even(numbers)">{{ n }}< /li >
    Javascript
    data: {
      numbers: [ 1, 2, 3, 4, 5 ]
    },
    methods: {
      even: function (numbers) {
        return numbers.filter(function (number) {
          return number % 2 === 0
        })
      }
    }
    Result
  • {{ n }}
  • v-for with a Range

    v-for 可以計數整數。在此例,它可以重複tag
    < div >
      < span v-for="n in 10">{{ n }} < /span >
    < /div >
    渲染成
    < div id="vfor-range" >
        < span >1 < /span >
        < span >2 < /span >
        < span >3 < /span >
        < span >4 < /span >
        < span >5 < /span >
        < span >6 < /span >
        < span >7 < /span >
        < span >8 < /span >
        < span >9 < /span >
        < span >10 < /span >
    < /div >
    Result
    {{ n }}

    v-for on a < template >
    一次渲染多個HTMLtag

    重複多個HTMLtag。所以將v-for寫在< template >上面。

    < ul >
      < template v-for="item in items" >
        < li >{{ item.msg }}< /li >
        < li class="divider">< /li >
      < /template >
    < /ul >
    Result(用template)

    不可行的寫法

    < ul v-for="item in items" >  -->不會重複
        < li >{{ item.msg }}< /li >  --->消失
        < li class="divider">< /li >  --->消失
    < /ul >
    < ul >
        < li v-for="item in items" >{{ item.msg }}< /li >  -->只會重複它
        < li class="divider">< /li >  --->只有一個
    < /ul >

    v-for with v-if

    可以條件式渲染v-for的內容,用起來像for loop一樣。
    < li  v-for = "todo in todos"  v-if = "!todo.isComplete" >
      {{ todo }}
    < /li >
    Result
  • {{todo.msg}}
  • 也可以條件渲染是否要loop,可以將v-if置於外部的元素,或者新加一個< template >v-if
    < ul  v-if = "shouldRenderTodos" >
      < li  v-for = "todo in todos" >
        {{ todo }}
      < /li >
    < /ul >
    

    v-for with a Component

    你可以直接在component自訂的tag上放置v-for,像下面這樣

    < my-component  v-for="item in items" :key="item.id">< /my-component >

    在v2.2.0+ 之後,component上的v-for都要加上key

    component有自己獨立的scop,要將變數傳入component使用,要透過props

    < my-component
      v-for="(item, index) in items"
      v-bind:item="item"
      v-bind:index="index"
      v-bind:key="item.id"
    >< /my-component >

    下面提供一個實例來看看,這是一個什麼樣的機制

    HTML
    < div id="todo-list-example">
          < input
            v-model="newTodoText"
            v-on:keyup.enter="addNewTodo"
            placeholder="Add a todo"
          >
          < ul>
            < li is="todo-item"               ---------> component
              v-for="(todo, index) in todos"  --> todos is data of vue object
              v-bind:key="todo.id"
              v-bind:name="todo.title"        ---------> v-bind:"name" is prop of component
              v-on:remove="todos.splice(index, 1)">
            < /li>                            ---------> component
          < /ul>
        < /div>
    Javascript
    Vue.component('todo-item', {
      props: ['name'],
      template: `
        < li>
          {{ name }}
          < button v-on:click="$emit('remove')">X< /button>
        < /li>`
    })
    
    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 = ''
        }
      }
    })
    Result