第三节:Vuejs常用特性2和图书案例

一. 常用特性2

1. 监听器

  用watch来响应数据的变化, 一般用于异步或者开销较大的操作, watch 中的属性 一定是data 中 已经存在的数据!!! 当需要监听一个对象的改变时,普通的watch方法无法监听到对象内部属性的改变,只有data中的数据才能够监听到变化,此时就需要deep属性对对象进行深度监听.

案例1:监听firstName和lastName,当他们发生变化的时候,fullName也发生变化; 该需求也可也把fullName声明成一个计算属性,同样可以达到这个效果。

案例2:输入用户名,当光标离开input标签的时候,进行验证该用户名是否存在。

2. 过滤器

  过滤器可以全局注册Vue.filter,也可以局部注册filters。过滤器可以用在两个地方:双花括号插值和v-bind属性表达式。过滤器不改变真正的 data ,而只是改变渲染的结果,并返回过滤后的版本.

  (1).第一个参数表示管道符前面的数据,而且过滤器支持级联操作。

  比如:{{msg | glq1 | glq2}} 支持多个过滤器

  (2).带参数的过滤器: 第一个参数不需要传递,默认就是要过滤的数据,后面可以继续写参数进行传递。

  (3).补充一个日期过滤器

3. 实例的生命周期(常用的8个)

  (1) beforeCreate: 在实例初始化之后,数据观测和事件配置之前被调用 此时data 和 methods 以及页面的DOM结构都没有初始化 什么都做不了

  (2) created: 在实例创建完成后被立即调用此时data 和 methods已经可以使用 但是页面还没有渲染出来

  (3) beforeMount: 在挂载开始之前被调用 此时页面上还看不到真实数据 只是一个模板页面而已

  (4) mounted: el被新创建的vm.$el替换,并挂载到实例上去之后调用该钩子。 数据已经真实渲染到页面上在这个钩子函数里面我们可以使用一些第三方的插件,数据的初始化可以放在这里

  (5) beforeUpdate: 数据更新时调用,发生在虚拟DOM打补丁之前。 页面上数据还是旧的

  (6) updated: 由于数据更改导致的虚拟DOM重新渲染和打补丁,在这之后会调用该钩子。 页面上数据已经替换成最新的

  (7) beforeDestroy: 实例销毁之前调用

  (8) destroyed: 实例销毁后调用

4. 变异方法和替换数组、动态响应数据处理

(1).变异方法:

  背景:在 Vue 中,直接修改对象属性的值无法触发响应式。当你直接修改了对象属性的值,你会发现,只有数据改了,但是页面内容并没有改变。所以:Vue中引入变异数组方法,即保持数组方法原有功能不变的前提下对其进行功能拓展,使其支持响应式。

常用方法如下:

  a. push: 往数组最后面添加一个元素,成功返回当前数组的长度。

  b. pop: 删除数组的最后一个元素,成功返回删除元素的值

  c. shift: 删除数组的第一个元素,成功返回删除元素的值

  d. unshift: 往数组最前面添加一个元素,成功返回当前数组的长度

  e. splice: 有三个参数,第一个要删除元素的下标(必选),第二个要删除元素的个数(必选),第三个删除后想在原位置替换的值

  f. sort: 将数组按照字符编码从小到大排序,成功返回排序后的数组

  g. reverse: 将数组倒序排列,并返回倒叙后的数组

(2).替换数组

  含义: 不会影响原始的数组数据,而是形成一个新的数组.

常用方法:

  a. filter: 创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素。

  b. concat: 用于连接两个或多个数组,该方法不会改变现有的数组。

  c. slice: 从已有的数组中返回选定的元素。该方法并不会修改数组,而是返回一个子数组

  eg:从第0个开始,获取两个元素 this.list = this.list.slice(0, 2);

(3).动态响应数据的处理

A. 操作数组

  Vue.set(vm.list, 1, 'ypf');

  vm.$set(vm.list, 1, 'ypf');

以上两句话是等效的,都表示把list数组中的第二个元素改为ypf。

B. 操作对象

  Vue.set(vm.info, 'sex', '女');

  vm.$set(vm.info, 'sex', '女');

以上两句话等效,表示给info对象增加一个属性sex,值为‘女’,如果info对象里已经有了sex属性,则执行的是修改操作

 代码分享:

  1 <!DOCTYPE html>
  2 <html>
  3     <head>
  4         <meta charset="utf-8">
  5         <title>04-常用特性2</title>
  6         <style type="text/css">
  7             p {
  8                 color: #0000FF;
  9                 font-size: 18px;
 10             }
 11 
 12             div {
 13                 margin-bottom: 10px;
 14             }
 15         </style>
 16     </head>
 17     <body>
 18         <div id="myApp">
 19             <p>1.监听器的使用</p>
 20             <div>
 21                 <div>
 22                     <input type="text" v-model="firstName" placeholder="请输入firstName">
 23                     <input type="text" v-model="lastName" placeholder="请输入lastName">
 24                 </div>
 25                 <div>我的全名为:{{fullName}}</div>
 26             </div>
 27             <div>
 28                 验证用户名是否存在:<input type="text" v-model.lazy="userName"><span>{{tip}}</span>
 29             </div>
 30             <p>2.过滤器的使用</p>
 31             <div>
 32                 <input type="text" v-model="msg">
 33                 <div>我是大写过滤器:{{msg|higher}}</div>
 34                 <div>我是小写过滤器:{{msg|lower}}</div>
 35                 <div :myClass="msg | higher">过滤器加在属性上</div>
 36                 <span>多参数过滤器</span>
 37                 <input type="text" v-model.number="myNum">
 38                 <div>结果为:{{myNum|myadd(10,20)}}</div>
 39                 <div>日期过滤器:{{myDate|format('yyyy-MM-dd hh:mm:ss')}}</div>
 40             </div>
 41             <p>4.变异方法和替换数组</p>
 42             <div>
 43                 <ul>
 44                     <li :key="index" v-for="(item,index) in list">{{item}}</li>
 45                 </ul>
 46                 <input type="text" v-model='fname'>
 47                 <button @click='add'>添加</button>
 48                 <button @click='del'>删除</button>
 49                 <button @click='change'>替换</button>
 50             </div>
 51             <p>5.动态响应处理</p>
 52             <div>
 53                 <button @click='handle1'>响应处理1</button>
 54                 <div>
 55                     <div>{{info.name}}</div>
 56                     <div>{{info.age}}</div>
 57                     <div>{{info.sex}}</div>
 58                 </div>
 59                 <button @click='handle2'>响应处理2</button>
 60             </div>
 61         </div>
 62         <script src="./js/vue.min.js" type="text/javascript" charset="utf-8"></script>
 63         <script type="text/javascript">
 64             //全局过滤器(小写过滤器)
 65             Vue.filter('lower', function(val) {
 66                 return val.toLowerCase();
 67             });
 68             //多参数过滤器
 69             //val表示要过滤的值,m,n 分别对应传递进来的两个值,对应上面的10和20
 70             Vue.filter('myadd', function(val, m, n) {
 71                 if (val < 10) {
 72                     return val + m;
 73                 } else {
 74                     return val + n;
 75                 }
 76             });
 77             //补充一个日期过滤器
 78             Vue.filter('format', function(value, arg) {
 79                 function dateFormat(date, format) {
 80                     if (typeof date === "string") {
 81                         var mts = date.match(/(/Date((d+))/)/);
 82                         if (mts && mts.length >= 3) {
 83                             date = parseInt(mts[2]);
 84                         }
 85                     }
 86                     date = new Date(date);
 87                     if (!date || date.toUTCString() == "Invalid Date") {
 88                         return "";
 89                     }
 90                     var map = {
 91                         "M": date.getMonth() + 1, //月份 
 92                         "d": date.getDate(), //
 93                         "h": date.getHours(), //小时 
 94                         "m": date.getMinutes(), //
 95                         "s": date.getSeconds(), //
 96                         "q": Math.floor((date.getMonth() + 3) / 3), //季度 
 97                         "S": date.getMilliseconds() //毫秒 
 98                     };
 99 
100                     format = format.replace(/([yMdhmsqS])+/g, function(all, t) {
101                         var v = map[t];
102                         if (v !== undefined) {
103                             if (all.length > 1) {
104                                 v = '0' + v;
105                                 v = v.substr(v.length - 2);
106                             }
107                             return v;
108                         } else if (t === 'y') {
109                             return (date.getFullYear() + '').substr(4 - all.length);
110                         }
111                         return all;
112                     });
113                     return format;
114                 }
115                 return dateFormat(value, arg);
116             })
117 
118             var vm = new Vue({
119                 el: '#myApp',
120                 data: {
121                     firstName: '',
122                     lastName: '',
123                     fullName: '',
124                     userName:'',
125                     tip:'',
126                     msg: '',
127                     myNum: '',
128                     myDate: new Date(),
129                     list: ['apple', 'orange', 'banana'],
130                     fname: '',
131                     info: {
132                         name: 'lmr',
133                         age: 20
134                     }
135                 },
136                 methods: {
137                     //验证用户名
138                     checkUserName:function(uname){
139                         var that=this;
140                         //模拟调用后台
141                         setTimeout(function(){
142                             if (uname=='admin') {
143                                 that.tip='存在';
144                             } else{
145                                 that.tip='不存在';
146                             }
147                         },1500);
148                     },
149                     //增加
150                     add: function() {
151                         this.list.push(this.fname);
152                     },
153                     //删除最后一个
154                     del: function() {
155                         this.list.pop();
156                     },
157                     //替换
158                     change: function() {
159                         //从第0个开始,获取两个元素
160                         this.list = this.list.slice(0, 2);
161                     },
162                     handle1: function() {
163                         //下面两句话等效,把list数组中的第二个元素改为ypf
164                         Vue.set(vm.list, 1, 'ypf');
165                         // vm.$set(vm.list, 1, 'ypf');
166                     },
167                     handle2: function() {
168                         //下面两句话等效,表示给info对象增加一个属性sex,值为‘女’
169                         // Vue.set(vm.info, 'sex', '女');
170                         vm.$set(vm.info, 'sex', '');
171                     }
172                 },
173                 computed: {
174                     //这里使用计算属性,也可以达到下面监听器的效果
175                     // fullName:function(){
176                     //     return this.firstName+' '+this.lastName;
177                     // }
178                 },
179                 //监听器
180                 watch: {
181                     //val代表该值
182                     firstName: function(val) {
183                         this.fullName = val + ' ' + this.lastName;
184                     },
185                     lastName: function(val) {
186                         this.fullName = this.firstName + ' ' + val;
187                     },
188                     userName:function(val){
189                         this.tip='正在校验中...';
190                         this.checkUserName(val);
191                     }
192                 },
193                 filters: {
194                     //大写过滤器
195                     higher: function(val) {
196                         return val.toUpperCase();
197                     }
198                 }
199 
200 
201 
202             });
203         </script>
204     </body>
205 </html>
View Code

运行结果:

 

二. 图书案例

 1. 需求

  实现图书系统的显示,删除、修改、增加。

2. 用到的几个数组的技术点:

  (1). filter: 根据条件过滤返回一个新数组,function(item){}; item为遍历数组中的元素

  (2). some: 用于遍历数组 (item)=>{}, return true; 则结束遍历

  (3). findIndex: 查找索引,function(item){}; item为遍历数组中的元素

最终运行效果:

 

 代码分享:

  1 <!DOCTYPE html>
  2 <html>
  3     <head>
  4         <meta charset="utf-8">
  5         <title>图书系统</title>
  6         <style type="text/css">
  7             .grid {
  8                 margin: auto;
  9                 width: 530px;
 10                 text-align: center;
 11             }
 12 
 13             .grid table {
 14                 border-top: 1px solid #C2D89A;
 15                 width: 100%;
 16                 border-collapse: collapse;
 17             }
 18 
 19             .grid th,
 20             td {
 21                 padding: 10;
 22                 border: 1px dashed #F3DCAB;
 23                 height: 35px;
 24                 line-height: 35px;
 25             }
 26 
 27             .grid th {
 28                 background-color: #F3DCAB;
 29             }
 30 
 31             .grid .book {
 32                 padding-bottom: 10px;
 33                 padding-top: 5px;
 34                 background-color: #F3DCAB;
 35             }
 36         </style>
 37     </head>
 38     <body>
 39         <div id="myApp">
 40             <div class="grid">
 41                 <div>
 42                     <h1>图书管理</h1>
 43                     <div class="book">
 44                         <div>
 45                             <label for="id">
 46                                 编号:
 47                             </label>
 48                             <input type="text" id="id" v-model='id' :disabled="isEdit">
 49                             <label for="name">
 50                                 名称:
 51                             </label>
 52                             <input type="text" id="name" v-model='name' @keyup.enter="handle">
 53                             <button @click='handle'>提交</button>
 54                         </div>
 55                     </div>
 56                 </div>
 57                 <table>
 58                     <thead>
 59                         <tr>
 60                             <th>编号</th>
 61                             <th>名称</th>
 62                             <th>时间</th>
 63                             <th>操作</th>
 64                         </tr>
 65                     </thead>
 66                     <tbody>
 67                         <tr :key='item.id' v-for='item in books'>
 68                             <td>{{item.id}}</td>
 69                             <td>{{item.name}}</td>
 70                             <td>{{item.date | format('yyyy-MM-dd hh:mm:ss')}}</td>
 71                             <td>
 72                                 <a href="" @click.prevent="editShow(item.id)">修改</a>
 73                                 <span>|</span>
 74                                 <a href="" @click.prevent="delBook(item.id)">删除</a>
 75                             </td>
 76                         </tr>
 77                     </tbody>
 78                 </table>
 79             </div>
 80         </div>
 81 
 82         <script src="./js/vue.min.js" type="text/javascript" charset="utf-8"></script>
 83         <script type="text/javascript">
 84             //日期格式化过滤器
 85             Vue.filter('format', function(value, arg) {
 86                 function dateFormat(date, format) {
 87                     if (typeof date === "string") {
 88                         var mts = date.match(/(/Date((d+))/)/);
 89                         if (mts && mts.length >= 3) {
 90                             date = parseInt(mts[2]);
 91                         }
 92                     }
 93                     date = new Date(date);
 94                     if (!date || date.toUTCString() == "Invalid Date") {
 95                         return "";
 96                     }
 97                     var map = {
 98                         "M": date.getMonth() + 1, //月份 
 99                         "d": date.getDate(), //
100                         "h": date.getHours(), //小时 
101                         "m": date.getMinutes(), //
102                         "s": date.getSeconds(), //
103                         "q": Math.floor((date.getMonth() + 3) / 3), //季度 
104                         "S": date.getMilliseconds() //毫秒 
105                     };
106                     format = format.replace(/([yMdhmsqS])+/g, function(all, t) {
107                         var v = map[t];
108                         if (v !== undefined) {
109                             if (all.length > 1) {
110                                 v = '0' + v;
111                                 v = v.substr(v.length - 2);
112                             }
113                             return v;
114                         } else if (t === 'y') {
115                             return (date.getFullYear() + '').substr(4 - all.length);
116                         }
117                         return all;
118                     });
119                     return format;
120                 }
121                 return dateFormat(value, arg);
122             })
123 
124             var vm = new Vue({
125                 el: '#myApp',
126                 data: {
127                     books: [{
128                         id: 1,
129                         name: '三国演义',
130                         date: 2525609975000
131                     }, {
132                         id: 2,
133                         name: '水浒传',
134                         date: 2525609975000
135                     }, {
136                         id: 3,
137                         name: '红楼梦',
138                         date: 2525609975000
139                     }, {
140                         id: 4,
141                         name: '西游记',
142                         date: 2525609975000
143                     }],
144                     id: '',
145                     name: '',
146                     isEdit: false,
147                 },
148                 methods: {
149                     //增加 或 修改
150                     handle: function() {
151                         if (this.isEdit == false) {
152                             //表示增加
153                             var obj = {};
154                             obj.id = this.id;
155                             obj.name = this.name;
156                             obj.date = 2525609975000;
157                             this.books.push(obj);
158                             // 清空表单
159                             this.id = '';
160                             this.name = '';
161                         } else {
162                             //表示修改
163                             //根据id查找出来book,然后进行修改,可以用filter,这里用另外一种方式 Some,查找出来的同时直接修改
164                             this.books.some((item) => {
165                                 if (item.id == this.id) {
166                                     item.name = this.name;
167                                     //返回true,表示终止循环
168                                     return true;
169                                 }
170                             });
171                             //清空表单,并恢复可编辑状态
172                             this.id = '';
173                             this.name = '';
174                             this.isEdit = false;
175                         }
176                     },
177                     //把要修改的内容显示在标签内
178                     editShow: function(id) {
179                         //根据id查找符合条件的book信息
180                         var theEditBook = this.books.filter(function(item) {
181                             return item.id == id;
182                         });
183                         //给标签赋值
184                         this.id = theEditBook[0].id;
185                         this.name = theEditBook[0].name;
186                         //id标签位置不可改
187                         this.isEdit = true;
188                     },
189                     //删除图书
190                     delBook: function(id) {
191                         //方案一
192                         // //查找索引
193                         // var index=this.books.findIndex(function(item){
194                         //     return item.id==id;
195                         // });
196                         // //第一个参数表示索引,第二个参数表示删除的个数
197                         // this.books.splice(index,1); 
198                         // 方案二 利用filter
199                         this.books = this.books.filter(function(item) {
200                             return item.id != id;
201                         });
202                     }
203                 }
204             });
205         </script>
206     </body>
207 </html>
View Code

!

  • 作       者 : Yaopengfei(姚鹏飞)
  • 博客地址 : http://www.cnblogs.com/yaopengfei/
  • 声     明1 : 如有错误,欢迎讨论,请勿谩骂^_^。
  • 声     明2 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。
 
原文地址:https://www.cnblogs.com/yaopengfei/p/12315704.html