欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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>

2020-11-22

 

说完我啪的一声就站起来,很快啊,上面一个transition-group 下面一个transition-group,按传统点到为止,

2020-11-22

    <!--  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而来 。这个年轻人不讲武德,来,骗!来,偷袭!我十八岁的小码农。这好吗?这不好。我劝!这位年轻人耗子尾汁,不要耍这些小聪明啊。

2020-11-22

但是

2020-11-22

马老师掏出了

2020-11-22

拿错了,下面这个

2020-11-22

 

通过查看官方文档一看,好家伙

2020-11-22

这些元素内部有严格限制。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 里面加哦 

官方对此也给出了指导性的意见

需要注意的是如果我们从以下来源使用模板的话,这条限制是不存在

大家继续踩坑 继续学呀,如果对上面的官方解释有兴趣的话,可以点击看官方解释

对啦 完整代码

<!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>