Vue案例:图书管理

2022-04-19  本文已影响0人  Imkata

代码地址:Vue案例

1 - 案例步骤

1. 提供的静态数据

 var vm = new Vue({
      el: '#app',
      data: {
        books: [{
          id: 1,
          name: '三国演义',
          date: ''
        },{
          id: 2,
          name: '水浒传',
          date: ''
        },{
          id: 3,
          name: '红楼梦',
          date: ''
        },{
          id: 4,
          name: '西游记',
          date: ''
        }]
      }
    }); 

2. 把提供好的数据渲染到页面上

 <tbody>
    <tr :key='item.id' v-for='item in books'>
       <!-- 对应的id 渲染到页面上 -->
       <td>{{item.id}}</td>
        <!-- 对应的name 渲染到页面上 -->
       <td>{{item.name}}</td>
       <td>{{item.date}}</td>
       <td>
         <!-- 阻止 a 标签的默认跳转 -->
         <a href="" @click.prevent>修改</a>
         <span>|</span>
          <a href="" @click.prevent>删除</a>
       </td>
     </tr>
</tbody>

3. 添加图书

<div>
  <h1>图书管理</h1>
  <div class="book">
       <div>
         <label for="id"> 编号:</label>
         <!-- 3.1、通过双向绑定获取到输入框中的输入的 id  -->
         <input type="text" id="id" v-model='id'>
         <label for="name"> 名称:</label>
         <!-- 3.2、通过双向绑定获取到输入框中的输入的 name  -->
         <input type="text" id="name" v-model='name'>
         <!-- 3.3、给按钮添加点击事件  -->
         <button @click='handle'>提交</button>
       </div>
  </div>
</div>
  <script type="text/javascript">
    /*
      图书管理-添加图书
    */
    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(){
          // 3.4 定义一个新的对象book 存储 获取到输入框中 书 的id和名字 
          var book = {};
          book.id = this.id;
          book.name = this.name;
          book.date = '';
          // 3.5 把book通过数组的变异方法push放到books里面,this是vm
          this.books.push(book);
          // 3.6 清空输入框,this是vm
          this.id = '';
          this.name = '';
        }
      }
    });
  </script>

4. 修改图书-上

 <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>
              <!--- 
                4.1  给修改按钮添加点击事件,需要把当前的图书的id 传递过去 
                这样才知道需要修改的是哪一本书籍
                --->  
              <a href="" @click.prevent='toEdit(item.id)'>修改</a>
              <span>|</span>
              <a href="" @click.prevent>删除</a>
            </td>
          </tr>
        </tbody>
      </table>
    </div>
  </div>
 <script type="text/javascript">
    /*
      图书管理-添加图书
    */
    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(){
          // 3.4 定义一个新的对象book 存储 获取到输入框中 书 的id和名字 
          var book = {};
          book.id = this.id;
          book.name = this.name;
          book.date = '';
          // 3.5 把book  通过数组的变异方法 push 放到 books 里面
          this.books.push(book);
          // 3.6 清空输入框
          this.id = '';
          this.name = '';
        },
        toEdit: function(id){
          console.log(id)
          // 4.2  根据传递过来的id 查出books 中对应书籍的详细信息
          // 返回的是数组
          var book = this.books.filter(function(item){
            return item.id == id;
          });
          console.log(book)
          // 4.3 把获取到的信息填充到表单
          // this.id和this.name 通过双向绑定绑定到了表单中,一旦数据改变视图自动更新
          this.id = book[0].id;
          this.name = book[0].name;
        }
      }
    });
  </script>

5. 修改图书-下

<div id="app">
    <div class="grid">
      <div>
        <h1>图书管理</h1>
        <div class="book">
          <div>
            <label for="id">
              编号:
            </label>
              <!-- 5.2 通过属性绑定 绑定 disabled 的属性  flag 为 true 即为禁用      -->
            <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 type="text/javascript">
        /*图书管理-添加图书*/
        var vm = new Vue({
            el: '#app',
            data: {
                // 5.1  定义一个标识符,主要是控制编辑状态下当前编辑书籍的id不能被修改 
                // 即处于编辑状态下,当前控制书籍编号的输入框禁用 
                flag: false,
                id: '',
                name: '',
            },
            methods: {
                // 点击提交按钮,可能是编辑图书也可能是添加图书
                handle: function() {
                   /*
                     5.4  复用添加方法 用户点击提交的时候依然执行 handle 中的逻辑
                         如果 flag为true 即 表单处于不可输入状态 此时执行的用户编辑数据数据    
                   */ 
                    if (this.flag) { // 编辑图书
                        // 5.5  根据当前的ID去更新数组中对应的数据  
                        this.books.some((item) => {
                           // 如果是普通函数的this是指向window,所以这里我们使用箭头函数
                           // 箭头函数中 this 指向父级作用域的this,在这里就是vm
                            if (item.id == this.id) {
                                
                                // 更新编辑的数据
                                item.name = this.name;
                                // 完成更新操作之后,需要终止循环
                                return true;
                            }
                        });
                        // 5.6 编辑完数据后表单要处以可以输入的状态
                        this.flag = false;
                    //  5.7  如果 flag为false  表单处于输入状态 此时执行的用户添加数据    
                    } else { // 添加图书
                        var book = {};
                        book.id = this.id;
                        book.name = this.name;
                        book.date = '';
                        this.books.push(book);
                    }
                    // 清空表单
                    this.id = '';
                    this.name = '';
                },
                toEdit: function(id) {
                     /*
                     5.3  flag 默认值为false   处于编辑状态 要把 flag 改为true 即当前表单为禁                      用 
                     */ 
                    this.flag = true;
                    console.log(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>

6. 删除图书

<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>
             <!--  6.1 给删除按钮添加事件 把当前需要删除的书籍id 传递过来  --> 
            <a href="" @click.prevent='deleteBook(item.id)'>删除</a>
          </td>
        </tr>
</tbody>
<script type="text/javascript">
  /*
    图书管理-添加图书
  */
  var vm = new Vue({
    methods: {
      deleteBook: function(id){
        // 删除图书
        #// 方法一
        #// 6.2 根据id从数组中查找元素的索引
        // var index = this.books.findIndex(function(item){
        //   return item.id == id;
        // });
        #// 6.3 根据索引删除数组元素
        // this.books.splice(index, 1);
        // -------------------------
        
        #// 方法二:通过filter方法进行删除
        # 6.4  根据filter方法,将要删除的id过滤掉
        # 因为filter是替换数组,不会修改原始数据,所以需要把最后的结果赋值给books 
        this.books = this.books.filter(function(item){
          return item.id != id;
        });
      }
    }
  });
</script>

2 - 常用特性应用场景

1. 过滤器(格式化日期)

Vue.filter 定义一个全局过滤器,用于格式化日期。

 <tr :key='item.id' v-for='item in books'>
            <td>{{item.id}}</td>
            <td>{{item.name}}</td>
                <!-- 1.3  调用过滤器 -->
            <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>

<script>
        #1.1  Vue.filter  定义一个全局过滤器
        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);
            })
#1.2  提供的数据,包含一个时间戳为毫秒数
   [{
          id: 1,
          name: '三国演义',
          date: 2525609975000
        },{
          id: 2,
          name: '水浒传',
          date: 2525609975000
        },{
          id: 3,
          name: '红楼梦',
          date: 2525609975000
        },{
          id: 4,
          name: '西游记',
          date: 2525609975000
        }];
</script>

2. 自定义指令(表单自动获取焦点)

让表单自动获取焦点,通过Vue.directive 自定义指令。

<!-- 2.2  通过v-自定义属性名 调用自定义指令 -->
<input type="text" id="id" v-model='id' :disabled="flag" v-focus>

<script>
    # 2.1   通过Vue.directive 自定义指定
    Vue.directive('focus', {
      inserted: function (el) {
        el.focus();
      }
    });
</script>

3. 计算属性(统计图书数量)

通过计算属性计算图书的总数,图书的总数就是计算数组的长度。

 <div class="total">
        <span>图书总数:</span>
          <!-- 3.2 在页面上展示出来 -->
        <span>{{total}}</span>
</div>

  <script type="text/javascript">
    /*
      计算属性与方法的区别: 计算属性是基于依赖进行缓存的,而方法不缓存
    */
    var vm = new Vue({
      data: {
        flag: false,
        submitFlag: false,
        id: '',
        name: '',
        books: []
      },
      computed: {
        total: function(){
          // 3.1  计算图书的总数
          return this.books.length;
        }
      },
    });
  </script>

4. 侦听器(验证图书是否存在)

如果输入的图书名字是已经存在的,就把提交按钮禁用,不让用户提交。

// :disabled="submitFlag" 提交按钮是否禁用
<button @click='handle' :disabled="submitFlag">提交</button>

data: {
  flag: false, // id输入框是否禁用,如果是禁用就是编辑,否则就是添加
  submitFlag: false, // 提交按钮是否禁用
  id: '',
  name: '',
  books: []
},
  // 使用监听器监听name属性
watch: {
  name: function(val) { //val是监听到的值 
    // 验证图书名称是否已经存在
    var flag = this.books.some(function(item){
      return item.name == val;
    });
    if(flag) {
      // 图书名称存在
      this.submitFlag = true;
    } else {
      // 图书名称不存在
      this.submitFlag = false;
    }
  }
},

5. 生命周期(图书数据处理)

mounted方法:该生命周期钩子函数被触发的时候,模板已经可以使用,一般此时用于获取后台数据,然后把数据填充到模板。

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;
}
上一篇 下一篇

猜你喜欢

热点阅读