簡體   English   中英

v -for 循環中每個元素的動畫(Vue.JS)

[英]Animation of each element separately in the v -for loop (Vue.JS)

我使用 VueJS 制作了一個簡單的待辦事項應用程序。 我還添加了 vue2-animate(Animate.css 的 Vue.js 2.0 端口。用於 Vue 的內置過渡。)添加一個元素的動畫工作正常。

但是有兩個問題我想在沒有不必要編碼的情況下解決:

  1. 從本地存儲下載列表的動畫顯示同時適用於所有項目。 我需要動畫分別為每個項目按順序工作。
  2. 刪除項目的動畫無法正常工作 - 最后一個項目總是被刪除,然后隨之而來。

PS:在 JSFiddle 中查看演示,因為 localstorage 在 SO 片段中不起作用。

 Vue.component("adder", { data: function() { return { task: "" }; }, template: ` <div class="input-group mb-3"> <input type="text" class="form-control" placeholder="New task..." aria-label="New task..." aria-describedby="" v-model="task" v-on:keyup.enter="add"> <div class="input-group-append"> <button class="btn btn-primary" id="" v-on:click="add" >+</button> </div> </div> `, methods: { add: function() { this.$emit("addtodo", { title: this.task, done: false }); this.task = ""; } } }); Vue.component("todo", { props: ["item"], template: ` <a href="#" class="list-group-item list-group-item-action task" v-bind:class="{'disabled done' : item.done==true}"> <label class="form-check-label"> <input class="form-check-input" type="checkbox" name="" id="" value="checkedValue" v-model="item.done"> {{item.title}} </label> <button type="button" class="close" aria-label="Close" v-on:click="del"> <span aria-hidden="true">&times;</span> </button> </a> `, methods: { del: function() { this.$emit("deletetodo"); } } }); Vue.component("todos", { props: ["items"], template: ` <div class="list-group"> <transition-group name="bounceLeft" tag="a"> <todo v-for="(item, index) in items" :key="index" :item.sync="item" v-on:deletetodo="delTodo(item)"></todo> </transition-group> </div> `, methods: { delTodo: function(i) { this.$emit("deletetodo", i); } } }); Vue.config.devtools = true; let app = new Vue({ el: ".todoapp", data: { title: "Todo App", items: [] }, methods: { addTodo: function(e) { this.items.push(e); }, delTodo: function(i) { this.items = this.items.filter(e => e != i); } }, mounted() { if (localStorage.items) { this.items = JSON.parse(localStorage.getItem("items")); } }, watch: { items: { handler(val) { localStorage.setItem("items", JSON.stringify(this.items)); }, deep: true } } });
 .done>label { text-decoration: line-through; } .task { padding-left: 36px; }
 <!DOCTYPE html> <html lang="en"> <head> <title>Todo App</title> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" /> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous" /> <link rel="stylesheet" href="https://unpkg.com/vue2-animate/dist/vue2-animate.min.css" /> <link rel="stylesheet" href="style.css" /> </head> <body> <div class="container todoapp"> <div class="row"> <br /> </div> <div class="card"> <div class="card-header"> {{ title }} </div> <div class="card-body"> <adder v-on:addtodo="addTodo"></adder> <todos :items.sync="items" v-on:deletetodo="delTodo"></todos> </div> </div> </div> <script src="https://cdn.jsdelivr.net/npm/vue"></script> <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script> <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script> <script src="script.js"></script> </body> </html>

JSFiddle 演示

可以一次服用:

刪除任務

它似乎總是被刪除的最后一個任務的原因是因為您要按index鍵入列表項。 當您在delTodo方法中替換整個items數組時, delTodo方法又為您提供了一個新數組,其中包含列表中每個項目的新鍵。 item關鍵字,您將獲得正確的結果:

<todo v-for="(item, index) in items" :key="item" :item.sync="item" v-on:deletetodo="delTodo(item)"></todo>

一次顯示一個任務

我的建議是使用計算的屬性來顯示/隱藏任務:

computed: {
    tasks: function(){
        return this.items.filter(item => item.isVisible);
    }
}

在這里,我們將通過在每個任務上切換isVisible來顯示/隱藏。

這意味着當您最初從本地存儲加載任務時,可以將它們全部設置為isVisible: false ,然后在for循環中使用setTimeout一次顯示所有任務:

mounted() {
    // Get your items and set all to hidden
    if (localStorage.items) {
        this.items = JSON.parse(localStorage.getItem("items"))
                     .map(item => item.isVisible = false);
    }

    // Loop through and show the tasks
    for(let i=1; i<=this.items.length; i++){
        // Where 300 is milliseconds to delay
        let delay = i * 300;

        setTimeout(function(){
            this.items[i].isVisible = true;
        }.bind(this), delay);
    }
},

最好的是,對items數組進行分階段添加的方法很有效:

  mounted() {
    let items = [];
    if (localStorage.items) {
      items = JSON.parse(localStorage.getItem("items"))
    }
    for (let i = 0; i < items.length; i++) {
      let delay = i * 1000;
      setTimeout(
        function() {
          this.items.push(items[i])
        }.bind(this),
        delay
      )
    }
  }

只是為了添加到對話中,以下內容在 Vuex 的 Action 中實現了驚人的效果並使用了粗箭頭語法:

async fetchRepositories( {commit} ){
  const response = await gitHubApi.get<Repository[]>('/users/rodolphocastro/repos') // Calling API with Axios
  const staggered: Repository[] = []
  response.data.forEach((r, i) => {
    const delay = i * 300 // 300m -> Time to wait for each item in the array
    setTimeout(() => {
      staggered.push(r)
      commit('setRepositories', staggered)
    }, delay)
  })
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM