这是我参与8月更文挑战的第9天,活动详情查看:8月更文挑战
前言
终于来到了这一天了啊!期待不期待呢?前面搞完了事件、渲染指令、过渡。那么今天就来搞个基础版的Todos啊。后面会讲到计算属性这一知识点。我们再搞个升级版的吧!
介绍
今天我们利用transitoin-group实现一个简单的todos啊。
主要功能
- 新增
- 删除
- 切换todo的状态
实现步骤
- 布局
- 过渡动画
- 逻辑
实现步骤
1、简单布局
en,首先这里的话呢我是没有写任何的样式的啊。样式自己私下画画,主要在于实现功能。
其次有三点:
- 新增用的是回车事件(修饰符) --- @keyup.enter.exact
- transition-group实现过渡动画
- 通过动态绑定class进行状态的切换
<div id="app">
<input type="text" @keyup.enter.exact="addTodo">
<ul>
<transition-group name="move">
<li v-for="t in todos" :key="t.id" @click.self="toggleTodo(t.id)" :class="{completed: t.completed}">
{{t.text}}
<button @click="removeTodo(t.id)">删除</button>
</li>
</transition-group>
</ul>
</div>
2、书写过渡动画
<style>
/* 已完成todo的样式 */
.completed {
color: #777;
text-decoration: line-through;
}
.move-leave,
.move-enter-to {
transform: translateX(0);
opacity: 1;
}
.move-leave-active,
.move-enter-active
{
transition: all .5s linear;
}
.move-leave-to,
.move-enter {
/* 从右边进入,从右到左的一个过渡,负数就与之相反 */
transform: translateX(200px);
opacity: 0;
}
</style>
我们来看看官网是怎么描述的呢? 在
进入/离开的过渡
中,会有 6 个 class 切换。
-
v-enter
:定义进入
过渡的开始状态
。在元素被插入之前生效,在元素被插入之后的下一帧移除。 -
v-enter-active
:定义进入过渡生效时
的状态。在整个进入过渡的阶段中应用,在元素被插入之前生效,在过渡/动画完成之后移除。这个类可以被用来定义进入过渡的过程时间,延迟和曲线函数。 -
v-enter-to
:2.1.8 版及以上定义进入过渡的结束状态
。在元素被插入之后下一帧生效 (与此同时v-enter
被移除),在过渡/动画完成之后移除。 -
v-leave
:定义离开
过渡的开始状态
。在离开过渡被触发时立刻生效,下一帧被移除。 -
v-leave-active
:定义离开过渡生效时
的状态。在整个离开过渡的阶段中应用,在离开过渡被触发时立刻生效,在过渡/动画完成之后移除。这个类可以被用来定义离开过渡的过程时间,延迟和曲线函数。 -
v-leave-to
:2.1.8 版及以上定义离开过渡的结束状态
。在离开过渡被触发之后下一帧生效 (与此同时v-leave
被删除),在过渡/动画完成之后移除。
这里看下来可能有的复杂啊,其实我们只需记住
enter是进入,leave是离开,active是生效时,to代表就是结束
疑问: 那为什么不是v-
,而是move-
呢?
答: 在过渡中切换的类名来说,如果你使用的是一个没有名字(name
)的 <transition>
,v-
就是这些类名的默认前缀,那么一旦你使用了name
,那么 v-
就会被替换成 name-
。就比如我们上面用的是<transition-group name="move">
,就会变成 move-enter
。
3、方法逻辑
根据开头我们说的todo有啥功能啊,我们就知道要写什么样的方法,从哪入手。一个是新增,切换状态,删除。
那就从最简单的新增开始吧,有了新增才能搞其他的对吧!这里我们把切换状态的放最后吧!
新增
这里我们通过事件对象来拿到我们input中输入的值,然后使用push改变原数组进行新增一条数据。
addTodo(evt) {
console.log(evt.target.value)
// 去除首尾空格
let text = evt.target.value.trim()
// 删除字符串首尾连续空白
if (!text) {
return
}
// 添加一条新的todo
this.todos.push({
id: new Date().getTime(),
text,
completed: false
})
// 清除输入框文本内容
evt.target.value = ""
},
删除
这还不简单嘛,直接filter搞起就完事了。
removeTodo(id) {
this.todos = this.todos.filter(t => t.id !== id)
}
切换状态
这里我们使用map对todos原数组进行操作,判断id是否相等,如果当前点击todo的id相等,那我们直接改变当前状态不就完事了么,其他的不变给他return回去。
toggleTodo(id) {
this.todos = this.todos.map(t => {
if (t.id === id) {
return {
...t,
completed: !t.completed
}
}
return t
})
},
效果
完整代码
这里把代码整理到一起,方便大家进行测试,也可以点击在线测试查看效果。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
/* 已完成todo的样式 */
.completed {
color: #777;
text-decoration: line-through;
}
.move-leave,
.move-enter-to {
transform: translateX(0);
opacity: 1;
}
.move-leave-active,
.move-enter-active
{
transition: all .5s linear;
}
.move-leave-to,
.move-enter {
/* 从右边进入,从右到左的一个过渡,负数就与之相反 */
transform: translateX(200px);
opacity: 0;
}
</style>
</head>
<body>
// 引入vue
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
<input type="text" @keyup.enter.exact="addTodo">
<ul>
<transition-group name="move">
<li v-for="t in todos" :key="t.id" @click.self="toggleTodo(t.id)" :class="{completed: t.completed}">
{{t.text}}
<button @click="removeTodo(t.id)">删除</button>
</li>
</transition-group>
</ul>
</div>
<script>
new Vue({
el: '#app',
data: {
// 定义默认的todos数据
todos: [{
id: 1,
text: '学习vue',
completed: false,
},
{
id: 2,
text: '学习webpack',
completed: true,
},
{
id: 3,
text: '学习ES6',
completed: true,
}
]
},
methods: {
// 新增
addTodo(evt) {
console.log(evt.target.value)
// 去除首尾空格
let text = evt.target.value.trim()
// 删除字符串首尾连续空白
if (!text) {
return
}
// 添加一条新的todo
this.todos.push({
id: new Date().getTime(),
text,
completed: false
})
// 清除输入框文本内容
evt.target.value = ""
},
// 切换状态
// 这里我们使用map对todos原数组进行操作,如果当前点击todo的id相等,那我们改变状态不就完事了么,其他的不变给他返回去。
toggleTodo(id) {
this.todos = this.todos.map(t => {
if (t.id === id) {
return {
...t,
completed: !t.completed
}
}
return t
})
},
// 删除
removeTodo(id) {
this.todos = this.todos.filter(t => t.id !== id)
}
}
})
</script>
</body>
</html>
结尾
今天就先到这里啦!我们下期再见!码字不易,觉得不错的可以动动小指头点点赞啥的哟~