【问题标题】:How to animate todo moving from one list to another with Vue.js?如何使用 Vue.js 动画 todo 从一个列表移动到另一个列表?
【发布时间】:2020-01-02 17:15:33
【问题描述】:

我正在尝试用 Vue.js 做 this svelte example todo 移动动画。

您可以在下面找到我到目前为止所做的事情。只需点击待办事项即可查看。

new Vue({
  el: "#app",
  data: {
    items: [
    	{ id: 1, name: 'John', done: false },
      { id: 2, name: 'Jane', done: false },
      { id: 3, name: 'Jade', done: true },
      { id: 4, name: 'George', done: true },
    ]
  },
  
  computed: {
  	done () {
    	return this.items.filter(i => i.done)
    },
    
    undone () {
    	return this.items.filter(i => !i.done)
    }
  },
  
  methods: {
  	toggle: function(todo){
    	todo.done = !todo.done
    }
  }
})
body {
  background: #20262E;
  padding: 20px;
  font-family: Helvetica;
}

#app {
  background: #fff;
  border-radius: 4px;
  padding: 20px;
  height: 500px;
  transition: all 0.2s;
}

.todos {
  display: grid;
  grid-template-columns: 1fr 1fr;
}

.todo {
  border: 1px solid #ccc;
}

.todo.undone {
  grid-column: 2 /span 1;
}

.todo.done {
  grid-column: 1 /span 1;
  background: blue;
  color: white;
}

.flip-list-move {
  transition: all 1s ease-in-out;
}

.header-wrapper {
  display: grid;
  grid-auto-flow: column;
  
}

.header, .todo {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  padding: 5px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>

<div id="app">


  <div class="header-wrapper">
   <div class="header">
    <span>Name</span>
    <span>Age</span>
    <span>Gender</span>
  </div>
  
    <div class="header">
    <span>Name</span>
    <span>Age</span>
    <span>Gender</span>
  </div>
  </div>

  <transition-group name="flip-list" tag="div" class="todos">

    <div class="todo done" v-for="item of done" :key="item.id" @click="toggle(item)">
      <span>{{item.name}}</span>
      <span>26</span>
      <span>Male</span>
    </div>

    <div class="todo undone" v-for="item of undone" :key="item.id" @click="toggle(item)">
      <span>{{item.name}}</span>
      <span>20</span>
      <span>Male</span>
    </div> 

   
  </transition-group>
</div>

为了使待办事项从一个列表移动到另一个列表,我使用了 CSS 网格,但如果没有一个空的网格单元格,我找不到一种方法来区分待办事项(左右)。

如果有更好的方法来实现 svelte docs 中的示例或省略空单元格的方法,我将不胜感激。

虽然一开始看起来很容易,但有点棘手。

【问题讨论】:

    标签: vue.js animation vuejs2 css-grid


    【解决方案1】:

    您可以通过跟踪v-for 循环中的index 来定位第一个元素。索引0 始终是第一个元素。并赋予它以下样式:

    grid-row-start: 1;

    编辑演示:

    new Vue({
      el: "#app",
      data: {
        items: [
        	{ id: 1, name: 'John', done: false },
          { id: 2, name: 'Jane', done: false },
          { id: 3, name: 'Jade', done: true },
          { id: 4, name: 'George', done: true },
        ]
      },
      
      computed: {
      	done () {
        	return this.items.filter(i => i.done)
        },
        
        undone () {
        	return this.items.filter(i => !i.done)
        }
      },
      
      methods: {
      	toggle: function(todo){
        	todo.done = !todo.done
        }
      }
    })
    body {
      background: #20262E;
      padding: 20px;
      font-family: Helvetica;
    }
    
    #app {
      background: #fff;
      border-radius: 4px;
      padding: 20px;
      height: 500px;
      transition: all 0.2s;
    }
    
    .todos {
      display: grid;
      grid-template-columns: 1fr 1fr;
    }
    
    .todo {
      border: 1px solid #ccc;
    }
    
    .todo.undone {
      grid-column: 2 /span 1;
    }
    
    .todo.done {
      grid-column: 1 /span 1;
      background: blue;
      color: white;
    }
    
    .first-right {
        grid-row-start: 1;
    }
    
    .flip-list-move {
      transition: all 1s ease-in-out;
    }
    
    .header-wrapper {
      display: grid;
      grid-auto-flow: column;
      
    }
    
    .header, .todo {
      display: grid;
      grid-template-columns: repeat(3, 1fr);
      padding: 5px;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
    
    <div id="app">
    
    
      <div class="header-wrapper">
       <div class="header">
        <span>Name</span>
        <span>Age</span>
        <span>Gender</span>
      </div>
      
        <div class="header">
        <span>Name</span>
        <span>Age</span>
        <span>Gender</span>
      </div>
      </div>
    
      <transition-group name="flip-list" tag="div" class="todos">
    
        <div class="todo done" v-for="item of done" :key="item.id" @click="toggle(item)">
          <span>{{item.name}}</span>
          <span>26</span>
          <span>Male</span>
        </div>
    
        <div :class="['todo', 'undone', { 'first-right': index === 0 }]" v-for="(item, index) of undone" :key="item.id" @click="toggle(item)">
          <span>{{item.name}}</span>
          <span>20</span>
          <span>Male</span>
        </div> 
    
       
      </transition-group>
    </div>

    【讨论】:

    • 我试过了,但它不起作用。您无法定位第一个撤消的操作,因为您看不到它。您定位的第一个撤消是空行。即使你再次抓住第二个,它也不会起作用
    • 好的,我开始工作了,检查一下我添加到帖子中的代码 sn-p...
    • 正如我在针对第一个撤消的第一条评论中提到的那样,它不起作用。在您的示例中,如果您在数组中添加 6 个项目,您会发现它不起作用。但是,我为我的问题添加了一个答案,效果很好。
    【解决方案2】:

    如果数组中的项目超过 6 个,则将 grid-row-start 添加到第一个 undo 元素不起作用。

    作为一种解决方案,我使用v-forindex 循环将相应的grid-row-start 添加到每个撤消 待办事项中。

    index 从 0 开始,所以我们必须使 index + 1

      <div
        class="todo undone"
        v-for="(item, index) of undone"
        :key="item.id"
        :style="{'grid-row': index + 1}" // => HERE we guarantee no gaps are present in undone list`
        @click="toggle(item)"
      >
        <span>{{item.name}}</span>
        <span>20</span>
        <span>Male</span>
      </div>
    

    您可以找到工作示例on this codesandbox

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多