VUE基础 笔记贰章 常用特性

本文介绍了Vue的常用特性,包括表单操作、自定义指令、计算属性、过滤器、侦听器和生命周期等,还给出了验证用户名是否可用的案例。此外,通过图书管理综合案例,讲解了数组相关API的使用,以及图书列表、添加、修改、删除等功能的实现,展示了Vue特性的应用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

5. VUE常用特性

5.1 常用特性概述

表单操作、自定义指令、计算属性、过滤器、侦听器、生命周期。

5.2 表单操作

5.2.1 基于VUE的表单操作

input单行文本、textarea多行文本、select下拉多选、radio单选框、checkbox多选框。

<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <title>Document</title>
    <style type="text/css">
      form div {
        height: 40px;
        line-height: 40px;
      }
      form div:nth-child(4) {
        height: auto;
      }
      form div span:first-child {
        display: inline-block;
        width: 100px;
      }
    </style>
  </head>
  <body>
    <div id="app">
      <form action="http://itcast.cn">
        <div>
          <span>姓名:</span>
          <span>
            <input type="text" v-model="uname" />
          </span>
        </div>
        <div>
          <span>性别:</span>
          <span>
            <input type="radio" id="male" value="1" v-model="gender" />
            <label for="male"></label>
            <input type="radio" id="female" value="2" v-model="gender" />
            <label for="female"></label>
          </span>
        </div>
        <div>
          <span>爱好:</span>
          <input type="checkbox" id="ball" value="1" v-model="hobby" />
          <label for="ball">篮球</label>
          <input type="checkbox" id="sing" value="2" v-model="hobby" />
          <label for="sing">唱歌</label>
          <input type="checkbox" id="code" value="3" v-model="hobby" />
          <label for="code">写代码</label>
        </div>
        <div>
          <span>职业:</span>
          <select v-model="occupation" multiple>
            <option value="0">请选择职业...</option>
            <option value="1">教师</option>
            <option value="2">软件工程师</option>
            <option value="3">律师</option>
          </select>
        </div>
        <div>
          <span>个人简介:</span>
          <textarea v-model="desc"></textarea>
        </div>
        <div>
          <input type="submit" value="提交" @click.prevent="handle" />
        </div>
      </form>
    </div>
    <script type="text/javascript" src="js/vue.js"></script>
    <script type="text/javascript">
      /*
      表单基本操作
    */
      var vm = new Vue({
        el: "#app",
        data: {
          uname: "lisi",
          gender: 2,
          hobby: ["2", "3"],
          // occupation: 3
          occupation: ["2", "3"],
          desc: "nihao",
        },
        methods: {
          handle: function () {
            // console.log(this.uname)
            // console.log(this.gender)
            // console.log(this.hobby.toString())
            // console.log(this.occupation)
            console.log(this.desc);
          },
        },
      });
    </script>
  </body>
</html>
5.2.3 表单域修饰符
  • number: 转化为数组。
  • trim:去掉开始和结尾的空格。
  • lazy:将input事件切换为change事件,change只有在失去焦点的时候才会触发,input是只要输入内容就会触发。
<body>
  <div id="app">
    <input type="text" v-model.number='age'>
    <input type="text" v-model.trim='info'>
    <input type="text" v-model.lazy='msg'>
    <div>{{msg}}</div>
    <button @click='handle'>点击</button>
  </div>
  <script type="text/javascript" src="js/vue.js"></script>
  <script type="text/javascript">
    /*
      表单域修饰符
    */
    var vm = new Vue({
      el: '#app',
      data: {
        age: '',
        info: '',
        msg: ''
      },
      methods: {
        handle: function(){
          // console.log(this.age + 13)
          // console.log(this.info.length)
        }
      }
    });
  </script>
</body>

5.3 自定义指令

因为内置指令不能满足需求,所以需要自定义指令。

5.3.1 自定义指令的语法规则(获取元素焦点)

inserted为钩子函数,具体见官网。

    Vue.directive('focus', {
      inserted: function(el){
        // el表示指令所绑定的元素
        el.focus();
      }
    });
5.3.2 自定义指令的用法
<input type="text" v-focus>
5.3.3 带参数的自定义指令(改变元素背景色)
	Vue.directive(‘color', {
		inserted: function(el, binding) {
			el.style.backgroundColor = binding.value.color;
	}
})

在这里插入图片描述

5.3.4 指令的用法
	<input type="text" v-color='{color:"orange"}'>
<body>
  <div id="app">
    <input type="text" v-color='msg'>
  </div>
  <script type="text/javascript" src="js/vue.js"></script>
  <script type="text/javascript">
    /*
      自定义指令-带参数
    */
    Vue.directive('color', {
      bind: function(el, binding){
        // 根据指令的参数设置背景色
        // console.log(binding.value.color)
        el.style.backgroundColor = binding.value.color;
      }
    });
    var vm = new Vue({
      el: '#app',
      data: {
        msg: {
          color: 'blue'
        }
      },
      methods: {
        handle: function(){
          
        }
      }
    });
  </script>
</body>
5.3.5 局部指令
	directives: {
		focus: {
			// 指令的定义
			inserted: function (el) {
			el.focus()
			} 
		}
}
  <body>
    <div id="app">
      <input type="text" v-color="msg" />
      <input type="text" v-focus />
    </div>
    <script type="text/javascript" src="js/vue.js"></script>
    <script type="text/javascript">
      /*
      自定义指令-局部指令
    */
      var vm = new Vue({
        el: "#app",
        data: {
          msg: {
            color: "red",
          },
        },
        methods: {
          handle: function () {},
        },
        directives: {
          color: {
            bind: function (el, binding) {
              el.style.backgroundColor = binding.value.color;
            },
          },
          focus: {
            inserted: function (el) {
              el.focus();
            },
          },
        },
      });
    </script>
  </body>

5.4 计算属性

5.4.1 为何需要计算属性?

表达式的计算逻辑可能会比较复杂,使用计算属性可以使模板内容更加简洁。

5.4.2 计算属性的用法
computed: {
          reverseString: function () {
            return this.msg.split("").reverse().join("");
          },
        }
  <body>
    <div id="app">
      <div>{{msg}}</div>
      <div>{{reverseString}}</div>
    </div>
    <script type="text/javascript" src="js/vue.js"></script>
    <script type="text/javascript">
      /*
      计算属性
    */
      var vm = new Vue({
        el: "#app",
        data: {
          msg: "Nihao",
        },
        computed: {
          reverseString: function () {
            return this.msg.split("").reverse().join("");
          },
        },
      });
    </script>
  </body>

在这里插入图片描述

<body>
  <div id="app">
    <div>{{reverseString}}</div>
    <div>{{reverseString}}</div>
    <div>{{reverseMessage()}}</div>
    <div>{{reverseMessage()}}</div>
  </div>
  <script type="text/javascript" src="js/vue.js"></script>
  <script type="text/javascript">
    /*
      计算属性与方法的区别:计算属性是基于依赖进行缓存的,而方法不缓存
    */
    var vm = new Vue({
      el: '#app',
      data: {
        msg: 'Nihao',
        num: 100
      },
      methods: {
        reverseMessage: function(){
          console.log('methods')
          return this.msg.split('').reverse().join('');
        }
      },
      computed: {
        reverseString: function(){
          console.log('computed')
          // return this.msg.split('').reverse().join('');
          var total = 0;
          for(var i=0;i<=this.num;i++){
            total += i;
          }
          return total;
        }
      }
    });
  </script>
</body>

5.5 侦听器

在这里插入图片描述

5.5.1 侦听的应用场景

数据变化时执行异步或开销较大的操作。

5.5.2 侦听器的用法
watch: {
         firstName: function(val) {
           // value表示变化后的值
           this.fullName = val + ' ' + this.lastName;
         },
         lastName: function(val) {
           this.fullName = this.firstName + ' ' + val;
         }
      }
<body>
  <div id="app">
    <div>
      <span>名:</span>
      <span>
        <input type="text" v-model='firstName'>
      </span>
    </div>
    <div>
      <span>姓:</span>
      <span>
        <input type="text" v-model='lastName'>
      </span>
    </div>
    <div>{{fullName}}</div>
  </div>
  <script type="text/javascript" src="js/vue.js"></script>
  <script type="text/javascript">
    /*
      侦听器
    */
    var vm = new Vue({
      el: '#app',
      data: {
        firstName: 'Jim',
        lastName: 'Green',
        // fullName: 'Jim Green'
      },
      computed: {
        fullName: function(){
          return this.firstName + ' ' + this.lastName;
        }
      },
      watch: {
        // firstName: function(val) {
        //   this.fullName = val + ' ' + this.lastName;
        // },
        // lastName: function(val) {
        //   this.fullName = this.firstName + ' ' + val;
        // }
      }
    });
  </script>
</body>

案例:验证用户名是否可用

  1. 通过v-model实现数据绑定。
  2. 需要提供提示信息。
  3. 需要侦听器监听输入信息的变化。
  4. 需要修改出发的事件。
<body>
  <div id="app">
    <div>
      <span>用户名:</span>
      <span>
        <input type="text" v-model.lazy='uname'>
      </span>
      <span>{{tip}}</span>
    </div>
  </div>
  <script type="text/javascript" src="js/vue.js"></script>
  <script type="text/javascript">
    /*      
      侦听器
      1、采用侦听器监听用户名的变化
      2、调用后台接口进行验证
      3、根据验证的结果调整提示信息
    */
    var vm = new Vue({
      el: '#app',
      data: {
        uname: '',
        tip: ''
      },
      methods: {
        checkName: function(uname) {
          // 调用接口,但是可以使用定时任务的方式模拟接口调用
          var that = this;
          setTimeout(function(){
            // 模拟接口调用
            if(uname == 'admin') {
              that.tip = '用户名已经存在,请更换一个';
            }else{
              that.tip = '用户名可以使用';
            }
          }, 2000);
        }
      },
      watch: {
        uname: function(val){
          // 调用后台接口验证用户名的合法性
          this.checkName(val);
          // 修改提示信息
          this.tip = '正在验证...';
        }
      }
    });

  </script>
</body>

5.6 过滤器

5.6.1 过滤器的作用是什么?

格式化数据,比如将字符串格式化为首字母大写,将日期格式化为指定的格式等。

5.6.2 自定义过滤器 / 全局过滤器

全局过滤器在所有的地方都可以使用,局部过滤器只可以在本组件中使用。

Vue.filter('upper', function(val) {
      // 过滤器业务逻辑
      return val.charAt(0).toUpperCase() + val.slice(1);
    });
5.6.3 过滤器的使用
  • 过滤器可以进行级联使用。
	<div>{{msg | upper | lower}}</div> 
  • 使用场景:插值表达式和属性绑定。
	<!-- 过滤器可用于插值表达式 -->
    <div>{{msg | upper}}</div>
    <div>{{msg | upper | lower}}</div>
    <!-- 过滤器可用于属性绑定 -->
    <div v-bind:id="id | formatId"></div>
  <body>
    <div id="app">
      <input type="text" v-model="msg" />
      <div>{{msg | upper}}</div>
      <div>{{msg | upper | lower}}</div>
      <div :abc="msg | upper">测试数据</div>
    </div>
    <script type="text/javascript" src="js/vue.js"></script>
    <script type="text/javascript">
      /*
      过滤器
      1、可以用与插值表达式和属性绑定
      2、支持级联操作
    */
      // Vue.filter('upper', function(val) {
      //   return val.charAt(0).toUpperCase() + val.slice(1);
      // });
      Vue.filter("lower", function (val) {
        return val.charAt(0).toLowerCase() + val.slice(1);
      });
      var vm = new Vue({
        el: "#app",
        data: {
          msg: "",
        },
        filters: {
          upper: function (val) {
            return val.charAt(0).toUpperCase() + val.slice(1);
          },
        },
      });
    </script>
  </body>
5.6.4 局部过滤器
        filters: {
          upper: function (val) {
            return val.charAt(0).toUpperCase() + val.slice(1);
          },
        }
5.6.5 带参数的过滤器
<div>{{date | format('yyyy-MM-dd')}}</div>
    // arg1 就是上行代码的 yyyy-MM-dd
	Vue.filter('format', function(value, arg1){
		// value就是过滤器传递过来的参数
	})
案例:使用过滤器格式化日期
  <body>
    <div id="app">
      <div>{{date | format('yyyy-MM-dd hh:mm:ss')}}</div>
    </div>
    <script type="text/javascript" src="js/vue.js"></script>
    <script type="text/javascript">
      /*
      过滤器案例:格式化日期      
    */
      // Vue.filter('format', function(value, arg) {
      //   if(arg == 'yyyy-MM-dd') {
      //     var ret = '';
      //     ret += value.getFullYear() + '-' + (value.getMonth() + 1) + '-' + value.getDate();
      //     return ret;
      //   }
      //   return value;
      // })
      Vue.filter("format", function (value, arg) {
        function dateFormat(date, format) {
          if (typeof date === "string") {
            var mts = date.match(/(\/Date\((\d+)\)\/)/);
            if (mts && mts.length >= 3) {
              date = parseInt(mts[2]);
            }
          }
          date = new Date(date);
          if (!date || date.toUTCString() == "Invalid Date") {
            return "";
          }
          var map = {
            M: date.getMonth() + 1, //月份
            d: date.getDate(), //日
            h: date.getHours(), //小时
            m: date.getMinutes(), //分
            s: date.getSeconds(), //秒
            q: Math.floor((date.getMonth() + 3) / 3), //季度
            S: date.getMilliseconds(), //毫秒
          };

          format = format.replace(/([yMdhmsqS])+/g, function (all, t) {
            var v = map[t];
            if (v !== undefined) {
              if (all.length > 1) {
                v = "0" + v;
                v = v.substr(v.length - 2);
              }
              return v;
            } else if (t === "y") {
              return (date.getFullYear() + "").substr(4 - all.length);
            }
            return all;
          });
          return format;
        }
        return dateFormat(value, arg);
      });
      var vm = new Vue({
        el: "#app",
        data: {
          date: new Date(),
        },
      });
    </script>
  </body>

5.7 生命周期

VUE实例对象的生命周期。

5.7.1 主要阶段
  1. 挂载(初始化相关属性)
    beforeCreate、created、beforeMount、mounted。
  2. 更新(元素或组件的变更操作)
    beforeUpdate、updated。
  3. 销毁(销毁相关属性)
    beforeDestroy、destroyed。
    在这里插入图片描述
5.7.2 VUE实例的产生过程
  1. beforeCreate在实例初始化之后,数据观测和事件配置之前被调用。
  2. created在实例创建完成后被立即调用。
  3. beforeMount在挂载开始之前被调用。
  4. mounted el被新创建的vm.$el替换,并挂载到实例上去之后调用该钩子。
  5. beforeUpdate数据更新时调用,发生在虚拟DOM打补丁之前。
  6. updated由于数据更改导致的虚拟DOM重新渲染和打补丁,在这之后会调用该钩子。
  7. beforeDestroy实例销毁之前调用。
  8. destroyed实例销毁后调用。
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>

<body>
  <div id="app">
    <div>{{msg}}</div>
    <button @click='update'>更新</button>
    <button @click='destroy'>销毁</button>
  </div>
  <script type="text/javascript" src="js/vue.js"></script>
  <script type="text/javascript">
    /*
      Vue实例的生命周期
      
    */
    var vm = new Vue({
      el: '#app',
      data: {
        msg: '生命周期'
      },
      methods: {
        update: function () {
          this.msg = 'hello';
        },
        destroy: function () {
          this.$destroy();
        }
      },
      beforeCreate: function () {
        console.log('beforeCreate');
      },
      created: function () {
        console.log('created');
      },
      beforeMount: function () {
        console.log('beforeMount');
      },
      mounted: function () {
        console.log('mounted');
      },
      beforeUpdate: function () {
        console.log('beforeUpdate');
      },
      updated: function () {
        console.log('updated');
      },
      beforeDestroy: function () {
        console.log('beforeDestroy');
      },
      destroyed: function () {
        console.log('destroyed');
      }
    });
  </script>
</body>

</html>

6. 综合案例:图书管理

6.1 数组相关API

6.1.1 变异方法 修改原有数据

Vue包装了观察到的数组的变异方法,因此它们也将触发视图更新。包装的方法是:
push()
pop()
shift()
unshift()
splice()
sort()
reverse()
您可以打开控制台,并通过items调用它们的变异方法来使用前面的示例的数组。

6.1.2 替换数组 生成新的数组

顾名思义,变异方法会变异调用它们的原始数组。相比之下,也有非变异方法,例如filter()concat()并且slice(),不发生变异原数组,但总是返回一个新的数组。使用非变异方法时,可以将旧数组替换为新数组。

  <body>
    <div id="app">
      <div>
        <span>
          <input type="text" v-model="fname" />
          <button @click="add">添加</button>
          <button @click="del">删除</button>
          <button @click="change">替换</button>
        </span>
      </div>
      <ul>
        <li :key="index" v-for="(item,index) in list">{{item}}</li>
      </ul>
    </div>
    <script type="text/javascript" src="js/vue.js"></script>
    <script type="text/javascript">
      /*
      Vue数组操作
      1、变异方法:会影响数组的原始数据的变化。
      2、替换数组:不会影响原始的数组数据,而是形成一个新的数组。
    */
      var vm = new Vue({
        el: "#app",
        data: {
          fname: "",
          list: ["apple", "orange", "banana"],
        },
        methods: {
          add: function () {
            this.list.push(this.fname);
          },
          del: function () {
            this.list.pop();
          },
          change: function () {
            this.list = this.list.slice(0, 2);
          },
        },
      });
    </script>
  </body>
6.1.3 修改响应式数据
  • Vue.set(vm.items, indexOfItem, newValue);
  • vm.$set(vm.items, indexOfItem, newValue);
  • 第一个参数表示要处理的数组名称。
  • 第二个参数表示要处理的数组元素的索引。
  • 第三个参数表示要处理的数组元素的值。
  <body>
    <div id="app">
      <ul>
        <li v-for="item in list">{{item}}</li>
      </ul>
      <div>
        <div>{{info.name}}</div>
        <div>{{info.age}}</div>
        <div>{{info.gender}}</div>
      </div>
    </div>
    <script type="text/javascript" src="js/vue.js"></script>
    <script type="text/javascript">
      /*
      动态处理响应式数据    
    */
      var vm = new Vue({
        el: "#app",
        data: {
          list: ["apple", "orange", "banana"],
          info: {
            name: "lisi",
            age: 12,
          },
        },
      });
      // vm.list[1] = 'lemon'; // 非响应式方法
      // Vue.set(vm.list, 2, 'lemon');
      vm.$set(vm.list, 1, "lemon");

      // vm.info.gender = 'male'; // 非响应式方法
      vm.$set(vm.info, "gender", "female");
    </script>
  </body>

6.2 图书管理

6.2.1 图书列表
  • 实现静态列表效果
  • 基于数据实现模板效果
  • 处理每行的操作按钮
<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>图书管理列表</title>
    <style>
      .grid {
        margin: auto;
        width: 500px;
        text-align: center;
      }
      .grid table {
        width: 100%;
        border-collapse: collapse;
      }
      .grid th,
      td {
        padding: 10;
        border: 1px dashed orange;
        height: 35px;
        line-height: 35px;
      }
      .grid th {
        background-color: orange;
      }
    </style>
  </head>
  <body>
    <div id="app">
      <div class="grid">
        <table>
          <thead>
            <tr>
              <th>编号</th>
              <th>名称</th>
              <th>时间</th>
              <th>操作</th>
            </tr>
          </thead>
          <tbody>
            <tr :key="item.id" v-for="item in books">
              <td>{{item.id}}</td>
              <td>{{item.name}}</td>
              <td>{{item.date}}</td>
              <td>
                <a href="" @click.prevent> 修改 </a>
                <span></span>
                <a href="" @click.prevent> 删除 </a>
              </td>
            </tr>
          </tbody>
        </table>
      </div>
    </div>
    <script src="js/vue.js" type="text/javascript"></script>
    <script type="text/javascript">
      /*
          图书管理-图书列表展示功能
          注意事项:<a href="" @click.prevent>修改</a>
          事件绑定时,可以只添加修饰符,而不绑定事件函数
      */
      var vm = new Vue({
        el: "#app",
        data: {
          books: [
            {
              id: 1,
              name: "三国演义",
              date: "",
            },
            {
              id: 1,
              name: "水浒传",
              date: "",
            },
            {
              id: 1,
              name: "红楼梦",
              date: "",
            },
            {
              id: 1,
              name: "西游记",
              date: "",
            },
          ],
        },
      });
    </script>
  </body>
</html>

6.2.2 添加图书
  • 实现表单的静态效果
  • 添加图书表单域数据绑定
  • 添加按钮事件绑定
  • 实现添加业务逻辑
<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>图书管理列表</title>
    <style>
      .grid {
        margin: auto;
        width: 530px;
        text-align: center;
      }
      .grid table {
        border-top: 1px solid #c2d89a;
        width: 100%;
        border-collapse: collapse;
      }
      .grid th,
      td {
        padding: 10;
        border: 1px dashed orange;
        height: 35px;
        line-height: 35px;
      }
      .grid th {
        background-color: orange;
      }
      .grid .book {
        padding-bottom: 10px;
        padding-top: 5px;
        background-color: #f3dcab;
      }
    </style>
  </head>
  <body>
    <div id="app">
      <div class="grid">
        <div>
          <h1>图书管理</h1>
          <div class="book">
            <div>
              <label for="id">编号:</label>
              <input type="text" id="id" v-model="id" />
              <label for="name">名称:</label>
              <input type="text" id="name" v-model="name" />
              <button @click="handle">提交</button>
            </div>
          </div>
        </div>
        <table>
          <thead>
            <tr>
              <th>编号</th>
              <th>名称</th>
              <th>时间</th>
              <th>操作</th>
            </tr>
          </thead>
          <tbody>
            <tr :key="item.id" v-for="item in books">
              <td>{{item.id}}</td>
              <td>{{item.name}}</td>
              <td>{{item.date}}</td>
              <td>
                <a href="" @click.prevent> 修改 </a>
                <span></span>
                <a href="" @click.prevent> 删除 </a>
              </td>
            </tr>
          </tbody>
        </table>
      </div>
    </div>
    <script src="js/vue.js" type="text/javascript"></script>
    <script type="text/javascript">
      /*
          图书管理-图书列表展示功能
          注意事项:<a href="" @click.prevent>修改</a>
          事件绑定时,可以只添加修饰符,而不绑定事件函数
      */
      var vm = new Vue({
        el: "#app",
        data: {
          id: "",
          name: "",
          books: [
            {
              id: 1,
              name: "三国演义",
              date: "",
            },
            {
              id: 2,
              name: "水浒传",
              date: "",
            },
            {
              id: 3,
              name: "红楼梦",
              date: "",
            },
            {
              id: 4,
              name: "西游记",
              date: "",
            },
          ],
        },
        methods: {
          handle: function () {
            // 图书管理-添加图书
            var book = {};
            book.id = this.id;
            book.name = this.name;
            book.date = "";
            this.books.push(book);
            // 清空表单
            this.id = "";
            this.name = "";
          },
        },
      });
    </script>
  </body>
</html>

6.2.3 修改图书
  • 修改信息填充到表单
  • 修改后重新提交表单
  • 重用添加和修改的方法
<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>图书管理列表</title>
    <style>
      .grid {
        margin: auto;
        width: 530px;
        text-align: center;
      }
      .grid table {
        border-top: 1px solid #c2d89a;
        width: 100%;
        border-collapse: collapse;
      }
      .grid th,
      td {
        padding: 10;
        border: 1px dashed orange;
        height: 35px;
        line-height: 35px;
      }
      .grid th {
        background-color: orange;
      }
      .grid .book {
        padding-bottom: 10px;
        padding-top: 5px;
        background-color: #f3dcab;
      }
    </style>
  </head>
  <body>
    <div id="app">
      <div class="grid">
        <div>
          <h1>图书管理</h1>
          <div class="book">
            <div>
              <label for="id">编号:</label>
              <input type="text" id="id" v-model="id" :disabled="flag" />
              <label for="name">名称:</label>
              <input type="text" id="name" v-model="name" />
              <button @click="handle">提交</button>
            </div>
          </div>
        </div>
        <table>
          <thead>
            <tr>
              <th>编号</th>
              <th>名称</th>
              <th>时间</th>
              <th>操作</th>
            </tr>
          </thead>
          <tbody>
            <tr :key="item.id" v-for="item in books">
              <td>{{item.id}}</td>
              <td>{{item.name}}</td>
              <td>{{item.date}}</td>
              <td>
                <a href="" @click.prevent="toEdit(item.id)"> 修改 </a>
                <span></span>
                <a href="" @click.prevent> 删除 </a>
              </td>
            </tr>
          </tbody>
        </table>
      </div>
    </div>
    <script src="js/vue.js" type="text/javascript"></script>
    <script type="text/javascript">
      /*
          图书管理-图书列表展示功能
          注意事项:<a href="" @click.prevent>修改</a>
          事件绑定时,可以只添加修饰符,而不绑定事件函数
      */
      var vm = new Vue({
        el: "#app",
        data: {
          flag: false,
          id: "",
          name: "",
          books: [
            {
              id: 1,
              name: "三国演义",
              date: "",
            },
            {
              id: 2,
              name: "水浒传",
              date: "",
            },
            {
              id: 3,
              name: "红楼梦",
              date: "",
            },
            {
              id: 4,
              name: "西游记",
              date: "",
            },
          ],
        },
        methods: {
          handle: function () {
            if (this.flag) {
              // 修改操作
              // 根据当前的id更新数组中对应的数据
              this.books.some((item) => {
                if (item.id == this.id) {
                  item.name = this.name;
                  // 更新完成,终止循环
                  return true;
                }
              });
              this.flag = false;
            } else {
              // 图书管理-添加图书
              var book = {};
              book.id = this.id;
              book.name = this.name;
              book.date = "";
              this.books.push(book);
              // 清空表单
              this.id = "";
              this.name = "";
            }
            this.id = "";
            this.name = "";
          },
          toEdit: function (id) {
            // 禁止修改id
            this.flag = true;
            console.log(id);
            // 根据Id查询要编辑的数据
            var book = this.books.filter(function (item) {
              return item.id == id;
            });
            console.log(book);
            // 把获取到的信息填交到表单
            this.id = book[0].id;
            this.name = book[0].name;
          },
        },
      });
    </script>
  </body>
</html>

6.2.4 删除图书
  • 删除按钮绑定事件处理方法
  • 实现删除业务逻辑
<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>图书管理列表</title>
    <style>
      .grid {
        margin: auto;
        width: 530px;
        text-align: center;
      }
      .grid table {
        border-top: 1px solid #c2d89a;
        width: 100%;
        border-collapse: collapse;
      }
      .grid th,
      td {
        padding: 10;
        border: 1px dashed orange;
        height: 35px;
        line-height: 35px;
      }
      .grid th {
        background-color: orange;
      }
      .grid .book {
        padding-bottom: 10px;
        padding-top: 5px;
        background-color: #f3dcab;
      }
    </style>
  </head>
  <body>
    <div id="app">
      <div class="grid">
        <div>
          <h1>图书管理</h1>
          <div class="book">
            <div>
              <label for="id">编号:</label>
              <input type="text" id="id" v-model="id" :disabled="flag" />
              <label for="name">名称:</label>
              <input type="text" id="name" v-model="name" />
              <button @click="handle">提交</button>
            </div>
          </div>
        </div>
        <table>
          <thead>
            <tr>
              <th>编号</th>
              <th>名称</th>
              <th>时间</th>
              <th>操作</th>
            </tr>
          </thead>
          <tbody>
            <tr :key="item.id" v-for="item in books">
              <td>{{item.id}}</td>
              <td>{{item.name}}</td>
              <td>{{item.date}}</td>
              <td>
                <a href="" @click.prevent="toEdit(item.id)"> 修改 </a>
                <span></span>
                <a href="" @click.prevent="deleteBook(item.id)"> 删除 </a>
              </td>
            </tr>
          </tbody>
        </table>
      </div>
    </div>
    <script src="js/vue.js" type="text/javascript"></script>
    <script type="text/javascript">
      /*
          图书管理-图书列表展示功能
          注意事项:<a href="" @click.prevent>修改</a>
          事件绑定时,可以只添加修饰符,而不绑定事件函数
      */
      var vm = new Vue({
        el: "#app",
        data: {
          flag: false,
          id: "",
          name: "",
          books: [
            {
              id: 1,
              name: "三国演义",
              date: "",
            },
            {
              id: 2,
              name: "水浒传",
              date: "",
            },
            {
              id: 3,
              name: "红楼梦",
              date: "",
            },
            {
              id: 4,
              name: "西游记",
              date: "",
            },
          ],
        },
        methods: {
          handle: function () {
            if (this.flag) {
              // 修改操作
              // 根据当前的id更新数组中对应的数据
              this.books.some((item) => {
                if (item.id == this.id) {
                  item.name = this.name;
                  // 更新完成,终止循环
                  return true;
                }
              });
              this.flag = false;
            } else {
              // 图书管理-添加图书
              var book = {};
              book.id = this.id;
              book.name = this.name;
              book.date = "";
              this.books.push(book);
              // 清空表单
              this.id = "";
              this.name = "";
            }
            this.id = "";
            this.name = "";
          },
          toEdit: function (id) {
            // 禁止修改id
            this.flag = true;
            console.log(id);
            // 根据Id查询要编辑的数据
            var book = this.books.filter(function (item) {
              return item.id == id;
            });
            console.log(book);
            // 把获取到的信息填交到表单
            this.id = book[0].id;
            this.name = book[0].name;
          },
          deleteBook: function (id) {
            // 删除图书
            // 根据id查找元素的索引
            // var index = this.books.findIndex(function (item) {
            //   return item.id == id;
            // });
            // // 根据索引删除数组元素
            // this.books.splice(index, 1);
            // ----------------------------
            // 方法二:通过filter方法进行删除
            this.books = this.books.filter(function (item) {
              return item.id != id;
            });
          },
        },
      });
    </script>
  </body>
</html>

6.2.5 常用特性应用场景
  • 过滤器(格式化日期)
  • 自定义指令(获取表单焦点)
  • 计算属性(统计图书数量)
  • 侦听器(验证图书存在性)
  • 生命周期(图书数据处理)
<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>图书管理列表</title>
    <style>
      .grid {
        margin: auto;
        width: 530px;
        text-align: center;
      }
      .grid table {
        border-top: 1px solid #c2d89a;
        width: 100%;
        border-collapse: collapse;
      }
      .grid th,
      td {
        padding: 10;
        border: 1px dashed orange;
        height: 35px;
        line-height: 35px;
      }
      .grid th {
        background-color: orange;
      }
      .grid .book {
        padding-bottom: 10px;
        padding-top: 5px;
        background-color: #f3dcab;
      }
      .grid .total {
        height: 30px;
        line-height: 30px;
        background-color: #f3dcab;
        border-top: 1px solid #c2d89a;
      }
    </style>
  </head>
  <body>
    <div id="app">
      <div class="grid">
        <div>
          <h1>图书管理</h1>
          <div class="book">
            <div>
              <label for="id">编号:</label>
              <input
                type="text"
                id="id"
                v-model="id"
                :disabled="flag"
                v-focus
              />
              <label for="name">名称:</label>
              <input type="text" id="name" v-model="name" />
              <button @click="handle" :disabled="submitFlag">提交</button>
            </div>
          </div>
        </div>
        <div class="total">
          <span>图书总数:</span>
          <span> {{total}} </span>
        </div>
        <table>
          <thead>
            <tr>
              <th>编号</th>
              <th>名称</th>
              <th>时间</th>
              <th>操作</th>
            </tr>
          </thead>
          <tbody>
            <tr :key="item.id" v-for="item in books">
              <td>{{item.id}}</td>
              <td>{{item.name}}</td>
              <td>{{item.date | format('yyyy-MM-dd hh:mm:ss')}}</td>
              <td>
                <a href="" @click.prevent="toEdit(item.id)"> 修改 </a>
                <span></span>
                <a href="" @click.prevent="deleteBook(item.id)"> 删除 </a>
              </td>
            </tr>
          </tbody>
        </table>
      </div>
    </div>
    <script src="js/vue.js" type="text/javascript"></script>
    <script type="text/javascript">
      /*
          图书管理-图书列表展示功能
          注意事项:<a href="" @click.prevent>修改</a>
          事件绑定时,可以只添加修饰符,而不绑定事件函数
      */
      Vue.directive("focus", {
        inserted: function (el) {
          el.focus();
        },
      });
      Vue.filter("format", function (value, arg) {
        function dateFormat(date, format) {
          if (typeof date === "string") {
            var mts = date.match(/(\/Date\((\d+)\)\/)/);
            if (mts && mts.length >= 3) {
              date = parseInt(mts[2]);
            }
          }
          date = new Date(date);
          if (!date || date.toUTCString() == "Invalid Date") {
            return "";
          }
          var map = {
            M: date.getMonth() + 1, //月份
            d: date.getDate(), //日
            h: date.getHours(), //小时
            m: date.getMinutes(), //分
            s: date.getSeconds(), //秒
            q: Math.floor((date.getMonth() + 3) / 3), //季度
            S: date.getMilliseconds(), //毫秒
          };
          format = format.replace(/([yMdhmsqS])+/g, function (all, t) {
            var v = map[t];
            if (v !== undefined) {
              if (all.length > 1) {
                v = "0" + v;
                v = v.substr(v.length - 2);
              }
              return v;
            } else if (t === "y") {
              return (date.getFullYear() + "").substr(4 - all.length);
            }
            return all;
          });
          return format;
        }
        return dateFormat(value, arg);
      });

      var vm = new Vue({
        el: "#app",
        data: {
          flag: false,
          submitFlag: false,
          id: "",
          name: "",
          books: [],
        },
        methods: {
          handle: function () {
            if (this.flag) {
              // 修改操作
              // 根据当前的id更新数组中对应的数据
              this.books.some((item) => {
                if (item.id == this.id) {
                  item.name = this.name;
                  // 更新完成,终止循环
                  return true;
                }
              });
              this.flag = false;
            } else {
              // 图书管理-添加图书
              var book = {};
              book.id = this.id;
              book.name = this.name;
              book.date = "";
              this.books.push(book);
              // 清空表单
              this.id = "";
              this.name = "";
            }
            this.id = "";
            this.name = "";
          },
          toEdit: function (id) {
            // 禁止修改id
            this.flag = true;
            console.log(id);
            // 根据Id查询要编辑的数据
            var book = this.books.filter(function (item) {
              return item.id == id;
            });
            console.log(book);
            // 把获取到的信息填交到表单
            this.id = book[0].id;
            this.name = book[0].name;
          },
          deleteBook: function (id) {
            // 删除图书
            // 根据id查找元素的索引
            // var index = this.books.findIndex(function (item) {
            //   return item.id == id;
            // });
            // // 根据索引删除数组元素
            // this.books.splice(index, 1);
            // ----------------------------
            // 方法二:通过filter方法进行删除
            this.books = this.books.filter(function (item) {
              return item.id != id;
            });
          },
        },
        computed: {
          total: function () {
            // 计算图书的总数
            return this.books.length;
          },
        },
        watch: {
          // 验证图书名称是否已经存在
          name: function (val) {
            var flag = this.books.some(function (item) {
              return item.name == val;
            });
            if (flag) {
              // 图书名称存在
              this.submitFlag = true;
            } else {
              // 图书名称不存在
              this.submitFlag = false;
            }
          },
        },
        mounted: function () {
          // 该生命周期钩子函数被触发的时候,模板已经可以使用
          // 一般此时用于获取后台数据,然后把数据填充到模板
          var data = [
            {
              id: 1,
              name: "三国演义",
              date: 2525609975000,
            },
            {
              id: 2,
              name: "水浒传",
              date: 2525609975000,
            },
            {
              id: 3,
              name: "红楼梦",
              date: 2525609975000,
            },
            {
              id: 4,
              name: "西游记",
              date: 2525609975000,
            },
          ];
          this.books = data;
        },
      });
    </script>
  </body>
</html>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值