Vue watch监听器 computed计算属性 filter过滤器 过渡动画
1-watch侦听器(监听器)
- 
本质: 一个特殊的函数
 - 
作用: 监视data中任意一个数据的改变, 从而实现一些特殊的业务处理
 - 
注意:
- 监视器函数的名字必须和要被监视的数据名称保持一致
 - 无需手动调用
 
 - 
语法
const vm = new Vue({ el: '#app', data: { msg:'hello', user:{ name:'zs', age:20, sex:'男' } }, methods: { updateMsg(){ this.msg='你好'; }, updateUser(){ this.user.name='张三'; // this.user={name:'张三'}; } }, // watch监听器 watch:{ // 监视器函数的名字必须和监视的数据名保持一致 msg(newVal,oldVal){ console.log(newVal,oldVal); }, // 更新对象中某一个属性的时候, 普通的监视器监听不到属性更新, 必须使用深度监听 // 深度监听 user:{ // 监听方法 handler(newVal,oldVal){ console.log(newVal,oldVal); }, // true表示要开启深度监听 deep:true } } }); 
2-computed计算属性
- 
本质: 一种特殊的函数(当做数据调用)
 - 
作用: 可以根据已经存在的数据, 计算出来一个不存在的数据
 - 
注意:
- computed计算属性函数必须有返回值
 - 计算属性函数名不能和data中的数据同名
 - 调用的时候, 当做变量直接调用, 无需带
() 
 - 
特点: 计算属性内部会有一些缓存机制
 - 
语法
<!--调用计算属性--> <h1>{{fullName}}</h1>const vm = new Vue({ el: '#app', data: { firstName: '', lastName: '', }, methods: { // 根据fistname和lastname计算一个fullname fname(){ console.log('普通方法'); return this.firstName+this.lastName; } }, // computed计算属性 computed:{ // 定义计算属性 fullName:function(){ console.log('计算属性方法'); return this.firstName+this.lastName; } } }); 
3-filter过滤器
- 
本质: 一种特殊的方法
 - 
作用: 对数据进行预处理
 - 
注意
- 过滤器处理函数必须至少有一个参数, 第一个参数永远是待处理的数据, 由系统自动注入
 - 过滤器处理函数必须有返回值
 - 过滤器只能在插值表达式和v-bind指令中使用(其他指令中使用会报错)
 
 - 
调用格式: 数据输出的位置
{{msg | fn}} 
3.1-全局过滤器
- 
特点: 在所有的vue实例中都可以调用
 - 
语法格式
Vue.filter('过滤器的名称',functoin(){ //进行数据预处理的函数 }); - 
调用全局过滤器
<div id="app"> <!-- 调用过滤器 --> <h1>{{msg | append}}</h1> <hr> <h1>{{msg | append1('***')}}</h1> <hr> <!-- 调用多个过滤器 --> <h1>{{msg | append | append1('####')}}</h1> </div> - 
定义全局过滤器
// params:系统自动注入的, input代表即将被处理的数据; params额外参数 Vue.filter('append', function (input) { // 必须有返回值 return input+'~~~'; }); Vue.filter('append1', function (input,params) { // 必须有返回值 return input + params; }); 
  ### 3.2-私有过滤器
- 特点: 只能在当前vue实例中调用
- 书写位置
  ```js
  new Vue({
      el:'#app',
      // 私有过滤器
      filters:{
          // input:系统自动注入, 代表待处理的数据
          fn(input){
          	// 必须有返回值 
          	return ''
      	}
      }
  });
- 
调用私有过滤器
<div id="app"> <!-- 调用私有过滤器 --> <h1>{{msg | append}}</h1> <hr> <h1>{{msg | append('***')}}</h1> <hr> <h1>{{createTime | dateFmt}}</h1> <h1>{{createTime | dateFmt('/')}}</h1> <h1>{{createTime | dateFmt('.')}}</h1> <h1>{{createTime | dateFmt('~')}}</h1> </div> - 
定义私有过滤器
const vm = new Vue({ el: '#app', data: { msg: 'hello', createTime:Date.now() }, // 私有过滤器 filters:{ append(input,params='~~~'){ return `${input}${params}` }, // 13位毫秒值=>yyyy-mm-dd HH:mm:ss dateFmt(input,divider='-'){ // input: 时间戳: 13毫秒值 // 创建对应的日期对象 const date=new Date(input); // 获取年份 const y=date.getFullYear(); const m=date.getMonth()+1; const d=date.getDate(); const h=date.getHours(); const mm=date.getMinutes(); const s=date.getSeconds(); return `${y}${divider}${m}${divider}${d} ${h}:${mm}:${s}`; } } }); 
4-单元素过渡动画
4.1-自定义过渡动画类名

4.1.1-实现步骤
- 
使用
<transition></transition>标签包裹目标元素<!-- 第一步: --> <transition> <h1 v-show="isShow">{{msg}}</h1> </transition> - 
自定义过渡动画类名的属性
/* 第二步: 定义过渡动画类名对应的属性 */ /* 进入阶段,离开阶段 */ /* 进入前,离开后 */ .v-enter,.v-leave-to{ left:-400px; } /* 进入中,离开中 */ .v-enter-active,.v-leave-active{ position: relative; transition: left 1s; } /* 进入后,离开前 */ .v-enter-to,.v-leave{ left:0; } 
4.1.2-自定义过渡类名前缀
- appear: 控制元素以过渡动画的效果入场
 
- 
第一步
/* 进入前,离开后 */ .slide-enter,.slide-leave-to{ left:-400px; } /* 进入中,离开中 */ .slide-enter-active,.slide-leave-active{ position: relative; transition: left 1s; } /* 进入后,离开前 */ .slide-enter-to,.slide-leave{ left:0; } - 
第二步
<!-- appear: 以过渡动画的方式入场 --> <transition appear name="slide"> <h1 v-show="isShow">{{msg}}</h1> </transition> 
4.2-使用第三方动画类库
- 
下载并引入animate.css
<!-- 第一步: 引入动画类库 --> <link rel="stylesheet" href="./libs/animate.css@3.5.1.css"> - 
通过属性引用动画类名
- enter-active-class: 指定进入过程中的动画类名
 - leave-active-class: 指定离开过程中的动画类名
 
<div id="app"> <!-- 第二步: 通过属性引用动画类名; animated是基础动画类名, tada是决定动画方式的类名 --> <transition appear enter-active-class="animated tada" leave-active-class="animated bounceOutRight"> <h1 v-show="isShow">{{msg}}</h1> </transition> <hr> <transition appear enter-active-class="animated swing" leave-active-class="animated wobble"> <h1 v-show="isShow">{{msg}}</h1> </transition> <hr> <button @click="toggle">切换显示状态</button> </div> 
5-列表过渡动画
5.1-自定义动画类名
- 
使用
transition-group标签包裹目标元素(列表元素)- tag: 指定最终渲染的标签名称
 
<!-- tag: 指定transition-group解析时候的标签 --> <transition-group tag="ul" name="slide" appear> <li v-for="item in list" :key="item.id">{{item.id}}-{{item.name}}</li> </transition-group> - 
自定义过渡动画类名
.slide-enter,.slide-leave-to{ top:-400px; } .slide-enter-active,.slide-leave-active{ position: relative; transition: all 1s; } .slide-enter-to,.slide-leave{ top:0; } 
5.2-使用第三方动画类库
- 
下载并引入animate动画类库
<!-- 1-引入animate.css --> <link rel="stylesheet" href="./libs/animate.css@3.5.1.css"> - 
通过属性引用动画类名
<!-- tag: 指定transition-group解析时候的标签 --> <transition-group tag="ul" appear enter-active-class="animated tada" leave-active-class="animated wodder" > <li v-for="item in list" :key="item.id">{{item.id}}-{{item.name}}</li> </transition-group> 
5-本地存储localStorage复习
- 什么是localStorage: 浏览器端一种数据存储方案
 - 数据存储位置: 电脑的磁盘上
 - 存储数据量: 相对比较大
 - 特点: localStorage中只能存储字符串, 不能直接存储数组和对象
 
相关的方法
- 
读取数据:
// 读取出来的数据类型是字符串 localStorage.getItem('key') - 
写入数据
localStorage.setItem('key','value'); - 
删除数据
localStorage.removeItem('key'); 
6-品牌管理案例
6.1-静态模板
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="./libs/vue.js"></script>
    <style>
        *{
            padding:0;
            margin:0;
            box-sizing: border-box;
        }
        #app{
            width: 800px;
            margin:20px auto;
        }
        tr{
            height: 50px;
            text-align: center;
        }
        .form-control{
            height: 40px;
            padding:10px;
            width: 100%;
            border:1px solid #DDD;
            border-radius: 4px;
        }
        .btn{
            border:1px solid #DDD;
            width: 60px;
            line-height: 30px;
            text-align: center;
            color:#555;
            background: #EEE;
            border-radius:6px;
            cursor: pointer;
            font-weight: 700;
            outline: 0;
        }
        .active{
            background-color: #EEE;
        }
        table,td{
            border:1px solid #CCC;
            /* 合并边框 */
            border-collapse: collapse;
        }
        .btn.danger{
            background-color: #D9534F;
            color:#FFF;
        }
        .btn.success{
            background-color:#337AB7;
            color:#FFF;
        }
        .line{
            border-bottom:1px solid #DDD;
            margin:10px 0;
        }
    </style>
</head>
<body>
    <div id="app">
        <h1>品牌管理</h1>
        <div class="line"></div>
        <div>
            <input class="form-control" type="text" placeholder="请输入品牌名称">
        </div>
        <div class="line"></div>
        <table cellpadding="0" cellspacing="0" width="100%">
            <thead>
                <tr class="active">
                    <td width="120">id</td>
                    <td>品牌名称</td>
                    <td>添加时间</td>
                    <td>操作</td>
                </tr>
            </thead>
            <tbody>
                <tr v-for="item in 10" :key="item">
                    <td>id</td>
                    <td>品牌名称-{{item}}</td>
                    <td>2020-11-18 16:23</td>
                    <td>
                        <button class="btn danger">删除</button>
                        <button class="btn success">编辑</button>
                    </td>
                </tr>
            </tbody>
        </table>
    </div>
</body>
<script>
new  Vue({
    el:'#app',
    data:{
    },
    methods:{
    },
    computed:{
    }
});
</script>
</html>
6.2-已实现功能
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="./libs/vue.js"></script>
    <style>
        *{
            padding:0;
            margin:0;
            box-sizing: border-box;
        }
        #app{
            width: 800px;
            margin:20px auto;
        }
        tr{
            height: 50px;
            text-align: center;
        }
        .form-control{
            height: 40px;
            padding:10px;
            width: 100%;
            border:1px solid #DDD;
            border-radius: 4px;
        }
        .btn{
            border:1px solid #DDD;
            width: 60px;
            line-height: 30px;
            text-align: center;
            color:#555;
            background: #EEE;
            border-radius:6px;
            cursor: pointer;
            font-weight: 700;
            outline: 0;
        }
        .active{
            background-color: #EEE;
        }
        table,td{
            border:1px solid #CCC;
            /* 合并边框 */
            border-collapse: collapse;
        }
        .btn.danger{
            background-color: #D9534F;
            color:#FFF;
        }
        .btn.success{
            background-color:#337AB7;
            color:#FFF;
        }
        .line{
            border-bottom:1px solid #DDD;
            margin:10px 0;
        }
    </style>
</head>
<body>
    <div id="app">
        <h1>品牌管理</h1>
        <div class="line"></div>
        <h3>品牌数量:{{brandCount}}</h3>
        <div class="line"></div>
        <div>
            <input @keyup.enter="add" v-model="brandName" class="form-control" type="text" placeholder="请输入品牌名称">
        </div>
        <div class="line"></div>
        <table cellpadding="0" cellspacing="0" width="100%">
            <thead>
                <tr class="active">
                    <td width="120">id</td>
                    <td>品牌名称</td>
                    <td>添加时间</td>
                    <td>操作</td>
                </tr>
            </thead>
            <tbody>
                <tr v-for="item in list" :key="item.id">
                    <td>{{item.id}}</td>
                    <td>{{item.name}}</td>
                    <td>{{item.ctime|dateFmt}}</td>
                    <td>
                        <button class="btn danger" @click="del(item.id)">删除</button>
                        <button class="btn success">编辑</button>
                    </td>
                </tr>
            </tbody>
        </table>
    </div>
</body>
<script>
new  Vue({
    el:'#app',
    data:{
        // 和输入框进行绑定的数据
        brandName:'',
        // 品牌列表数组
        list:[]
    },
    methods:{
        // 实现品牌添加
        add(){
            // 1-将新增的品牌添加到品牌列表数组中
            // 1.1-构造品牌对象
            const obj={
                id:this.list.length>0?this.list[0].id+1:1,
                name:this.brandName,
                ctime:Date.now()
            }
            // 1.2-将品牌对象, 添加到数组中
            this.list.unshift(obj);
            // 1.3-重置表单
            this.brandName='';
            // 2-将品牌列表数组存储本地存储localStorage中
            localStorage.setItem('brandlist',JSON.stringify(this.list));
        },
        // 品牌删除
        del(id){
            if(!confirm('确认删除?')){
                return false;
            }
            // 1-删除页存内存中的数据
            // 通过id查找index索引
            const index=this.list.findIndex(item=>item.id===id);
            this.list.splice(index,1);
            // 2-删除本地存储中的品牌数据
            // 读取本地存储中的品牌列表
            // const list=JSON.parse(localStorage.getItem('brandlist')||'[]');
            const list=this.getBrandList();
            // 删除对应品牌
            list.splice(index,1);
            // 重新写入
            localStorage.setItem('brandlist',JSON.stringify(list));
        },
        // 从本地存储中读取品牌列表
        getBrandList(){
            const list=JSON.parse(localStorage.getItem('brandlist')||'[]');
            return list;
        }
    },
    computed:{
        brandCount(){
            return this.list.length;
        }
    },
    created(){
        // 1-读取本地存储中的品牌列表信息
        // const list=JSON.parse(localStorage.getItem('brandlist')||'[]');
        const list=this.getBrandList();
        // 2-更新数据list
        this.list=list;
    },
    filters:{
        dateFmt(input){
            const date=new Date(input);
            const y=date.getFullYear();
            const m=date.getMonth()+1;
            const d=date.getDate();
            const h=date.getHours();
            const mm=date.getMinutes();
            const s=date.getSeconds();
            return `${y}-${m}-${d} ${h}:${mm}:${s}`;
        }
    }
});
</script>
</html>

                
            
        
浙公网安备 33010602011771号