2020-11-22
程序员文章站
2022-03-22 16:45:15
...
马老师带你用vue2 实现 table 标签内元素删除动画效果
诶...朋友们好啊,刚才有个年轻人问我发生肾摸事了,我说怎么回事,给我发了几张截图。我一看!嗷!table 标签内元素删除动画效果。年轻人说马老师你能不能加个table标签内元素删除动画的效果,我说可以。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="https://cdn.bootcss.com/vue/2.5.2/vue.min.js"></script>
</head>
<body>
<div id ="app">
<div id="wraper">
<div>
<h3>添加书籍</h3>
</div>
<div>
<!-- labled的第一种使用方式 for属性和表单元素的id属性绑定到一起 -->
<label for="bId">ID:</label>
<input type="text" id="bId" v-model="bId">
<!-- lable的第二种使用方式 -->
<label>
书名: <input type="text" v-model="name">
</label>
<input type="button" value="新增" @click="add" >
<!-- 搜索框 -->
<label>
搜索关键字: <input type="text" v-model="keywords" v-focus>
</label>
</div>
</div>
<!-- 表格标签 -->
<table>
<thead>
<tr>
<th>ID</th>
<th v-color="'green'">书名</th>
<th>创建时间</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr v-for="item in search(keywords)" :key="item.id">
<td>{{ item.id }}</td>
<td v-text="item.name"></td>
<td v-cloak>{{ item.createTime | dateFormat("yyyy-mm-dd")}}</td>
<td>
<a href="" @click.prevent="del(item.id)">删除</a>
</td>
</tr>
</tbody>
</table>
</div>
<script>
// 定义全局过滤器 表示所有实例都可以使用
Vue.filter('dateFormat', function(dateStr, pattern) {
// 根据字符串 找到对应的时间
var date = new Date(dateStr)
// 得到年月日
var year = date.getFullYear();
var month = date.getMonth() + 1;
var day = date.getDate();
if (pattern == "yyyy-mm-dd") {
return year + "-" + month + "-" + day;
} else {
// 得到具体时间
var hour = date.getHours();
var minute = date.getMinutes();
var second = date.getSeconds();
// ES6 模板字符串 用``包裹 内部可以引入变量
return `${year}-${month}-${day} ${hour}:${minute}:${second}`;
}
})
// 自定义指令 - 字体颜色
/*
Vue.directive(参数一,参数二) 自定义指令
参数一 指令的名称
参数二 是一个对象, 对象中是指令的相关的钩子函数
*/
Vue.directive("color", { // v-text="msg" ==> v-color="red"
bind(el, binding) {
// 每当指令绑定到元素上时 调用这个函数 只执行一次
console.log(binding)
el.style.color = binding.value
},
inserted() {
// 当元素 插入到dom中 会执行inserted
},
updated() {
// 当节点更新时 回调用该函数
}
})
// 结论 如果指令实现样式的功能 那么 就 将代码写在bind 如果js相关的功能 那么就写在 inserted
Vue.directive("focus", {
bind(el, binding) {
// 此时 元素还未被插入dom文档树中 调用focus方法是不起作用的
el.focus();
},
inserted(el) {
console.log(el)
el.focus();
},
updated() {
}
})
var vm = new Vue({
el: '#app',
data: {
list: [
{id : 1, name: '三国演义', createTime: new Date()},
{id : 2, name: '红楼梦', createTime: new Date()},
{id : 3, name: '水浒传', createTime: new Date()},
{id : 4, name: '西游记', createTime: new Date()},
],
bId: "",
name: "",
keywords: ""
},
methods: {
add() {
var book = {id: this.bId, name: this.name, createTime: new Date() };
this.list.push(book);
this.bId = this.name = "";
},
del(id) {
var index = this.list.findIndex(item => {
if (item.id == id) {
return true;
}
})
this.list.splice(index, 1);
},
search(keywords) {
var newList = [];
this.list.forEach(item => {
if (item.name.indexOf(keywords) != -1) {
newList.push(item)
}
})
return newList
}
},
});
</script>
</body>
</html>
说完我啪的一声就站起来,很快啊,上面一个transition-group 下面一个transition-group,按传统点到为止,
<!-- 1. transition 给需要做动画元素包裹上该标签 -->
<!-- transition-group 用来包裹多个元素 默认使用 span渲染数据 所以可以指定一个属性 tag 指定渲染的标签 -->
<!-- appear 属性 实现页面入场时效果 -->
<transition-group tag="ul" appear>
<li v-for="(item, index) in list" :key="item.id" @click="del(index)">
{{ item.id }} --- {{ item.name }}
</li>
</transition-group>
嗯 一样的东西而已 很简单的
<tbody>
<tr v-for="item in search(keywords)" :key="item.id">
<transition-group>
<td>{{ item.id }}</td>
<td v-text="item.name"></td>
<td v-cloak>{{ item.createTime | dateFormat("yyyy-mm-dd")}}</td>
<td>
<a href="" @click.prevent="del(item.id)">删除</a>
</td>
</transition-group>
</tr>
</tbody>
但我大E了,没有闪。嗯?怎么多了一个span标签??? 我没有写过呀,看来他是有bear而来 。这个年轻人不讲武德,来,骗!来,偷袭!我十八岁的小码农。这好吗?这不好。我劝!这位年轻人耗子尾汁,不要耍这些小聪明啊。
但是
马老师掏出了
拿错了,下面这个
通过查看官方文档一看,好家伙
这些元素内部有严格限制。transition-group 标签不能直接出现在table标签里面。嗯,知道原因就很简单啦。官方也说可以通过is attribute属性来进行操作,那我们就小小修改一下代码吧。
<tbody is="transition-group" mode="out-in">
<tr v-for="item in search(keywords)" :key="item.id" v-if>
<td>{{ item.id }}</td>
<td v-text="item.name"></td>
<td v-cloak>{{ item.createTime|dateFormat()}}</td>
<td>
<a href="" @click.prevent="del(item.id)">删除</a>
</td>
</tr>
</tbody>
是在tbody 里面加哦 。
官方对此也给出了指导性的意见
需要注意的是如果我们从以下来源使用模板的话,这条限制是不存在的:
- 字符串 (例如:
template: '...'
) - 单文件组件 (
.vue
) <script type="text/x-template">
大家继续踩坑 继续学呀,如果对上面的官方解释有兴趣的话,可以点击看官方解释
对啦 完整代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="https://cdn.bootcss.com/vue/2.5.2/vue.min.js"></script>
<style>
.v-enter,
.v-leave-to {
opacity: 0;
transform: translateX(200px);
}
.v-enter-active,
.v-leave-active {
transition: all 1s cubic-bezier(0.075, 0.82, 0.165, 1);
}
</style>
</head>
<body>
<div id="app">
<div id="wraper">
<div>
<h3>添加书籍</h3>
</div>
<div>
<label for="bId">ID:</label>
<input type="text" id="bId" v-model="bId">
<label>
书名: <input type="text" v-model="name">
</label>
<input type="button" value="新增" @click="add">
<label>
搜索关键字: <input type="text" v-model="keywords">
</label>
</div>
</div>
<table>
<thead>
<tr>
<th>ID</th>
<th>书名</th>
<th>创建时间</th>
<th>操作</th>
</tr>
</thead>
<tbody is="transition-group" mode="out-in">
<tr v-for="item in search(keywords)" :key="item.id" v-if>
<td>{{ item.id }}</td>
<td v-text="item.name"></td>
<td v-cloak>{{ item.createTime|dateFormat()}}</td>
<td>
<a href="" @click.prevent="del(item.id)">删除</a>
</td>
</tr>
</tbody>
</table>
</div>
<script type="text/x-template" id="hello-world-template">
</script>
<script>
Vue.filter('dateFormat', function (dateStr, pattern) {
var date = new Date(dateStr)
var year = date.getFullYear();
var month = date.getMonth() + 1;
var day = date.getDate();
if (pattern == "yyyy-mm-dd") {
return year + "-" + month + "-" + day;
} else {
var hour = date.getHours();
var minute = date.getMinutes();
var second = date.getSeconds();
return `${year}-${month}-${day} ${hour}:${minute}:${second}`;
}
})
var vm = new Vue({
el: '#app',
data: {
list: [
{ id: 1, name: '三国演义', createTime: new Date() },
{ id: 2, name: '红楼梦', createTime: new Date() },
{ id: 3, name: '水浒传', createTime: new Date() },
{ id: 4, name: '西游记', createTime: new Date() },
],
bId: "",
name: "",
keywords: ""
},
template: "",
methods: {
add() {
var book = { id: this.bId, name: this.name, createTime: new Date() };
this.list.push(book);
this.bId = this.name = "";
},
del(id) {
var index = this.list.findIndex(item => {
if (item.id == id) {
return true;
}
})
this.list.splice(index, 1);
},
search(keywords) {
var newList = [];
this.list.forEach(item => {
if (item.name.indexOf(keywords) != -1) {
newList.push(item)
}
})
return newList
}
},
});
</script>
</body>
</html>