Vue 生命周期 侦听器 计算属性 (百度搜索,购物车案例) 过滤器

1.生命周期

表示的是一个vue实例对象的一个轮回。

人的生命周期。一个月内要办理出生证明以及去派出所办户口、打疫苗

从技术上来考虑,这8个生命周期就是8个函数,也叫生命周期钩子函数 。不需要自己手动调用,它是在相应的时机上自动触发的,语法上这8个函数不在methods中。

  • beforeCreate 创建之前

  • created 创建完成 : 最早发送ajax的地址在这里

  • beforeMount 挂载之前

  • mounted 挂载完成 : 有些项目中,一些开发者也在这里发送ajax。 绑定window事件scroll/ 获取页面的高 / 开启定时器

  • beforeUpdate 更新之前

  • updated 更新完成

  • beforeDestroy 销毁之前 解除window事件scroll/关闭启定时器

  • destroyed 销毁完成

​
<body>
    <div id="app">
        {{username}}
        <h2>我是h2</h2>
        <button @click="username='ls'">更改username</button>
        <button @click="kill">销毁实例</button>
    </div>
</body>
<script src="vue.js"></script>
<script>
    new Vue({
        el: '#app',
        data: {
            username:'zs'
        },
        methods: {
            kill(){
                this.$destroy()
                //console.log( this );
            }
        },
        //$el指的是 #app元素整体
        //$data 初始化的数据
        //vue实例创建之前
        beforeCreate(){
            //console.log( this );
            console.group('-----beforeCreate------------')
            console.log( this.$el,'----this.$el----' ) //undefined
            console.log( this.$data,'----this.data----' ) //undefined
            console.groupEnd()
        },
        //vue实例创建完成 : 最早发送ajax的地址在这里
        created(){
            console.group('-----created------------')
            console.log( this.$el,'----this.$el----' ) //undefined
            console.log( this.$data,'----this.data----' ) //存在 :最早能访问数据的地方
            console.groupEnd()
        },
​
        //数据挂载之前 , 挂载(指的是把data中的数据渲染在页面上)
        beforeMount(){
            console.group('-----beforeMount------------')
            console.log( this.$el,'----this.$el----' ) //存在:还没有解析数据呢
            console.log( this.$data,'----this.data----' ) //存在
            console.groupEnd()
        },
        //数据挂载完成 : 绑定window事件scroll/ 获取页面的高 / 开启定时器
        mounted(){
            console.group('-----mounted------------')
            console.log( this.$el,'----this.$el----' ) //存在:解析模板成功,数据也挂载了
            console.log( this.$data,'----this.data----' ) //存在
            console.groupEnd()
        },
​
        //视图更新之前: 数据已经是最新的
        beforeUpdate(){
            console.group('-----beforeUpdate------------')
            console.log( this.$el,'----this.$el----' ) //
            console.log( this.$data,'----this.data----' ) //存在
            console.groupEnd()
        },
​
        //视图更新完成: 数据已经是最新的
        updated(){
            console.group('-----updated------------')
            console.log( this.$el,'----this.$el----' ) //
            console.log( this.$data,'----this.data----' ) //存在
            console.groupEnd()
        },
​
        //vue实例销毁之前  : 解决window事件scroll/关闭启定时器
        beforeDestroy(){ 
            console.group('-----beforeDestroy------------')
            console.log( this.$el,'----this.$el----' ) //
            console.log( this.$data,'----this.data----' ) //存在
            console.groupEnd()
        },
        destroyed(){
            console.group('-----destroyed------------')
            console.log( this.$el,'----this.$el----' ) //
            console.log( this.$data,'----this.data----' ) //存在
            console.groupEnd()
        }
    })
</script>

2.侦听器watch

2.1 定义

侦听器又名监听器
侦听器是属于vue中一个特殊的对象,对象上都是方法,和el、data平级,用来监听data数据的改变,从而做出及时的响应.
​
应用:
    百度搜索  百度翻译 淘宝搜索...

2.2-1 普通监听

* 普通监听: 除对象以下的数据(数组)
* 监听器中方法名是其data中对应的属性名
* 系统自动注入的参数,有两个 newVal: 更新后的新值   oldVal:更新前的旧值
* 监听器中的所有方法:无需调用,当被监听的数据发生改变时,自动被执行

2.2-2 深度监听

对象数据的监听需要使用深度监听,虽然也可以兼听普通数据但是没有必要使用尝试监听
* 深度监听需要使用固定方法handler和deep属性
* 系统自动注入一个参数: newVal,在深度监听中无法获取更新之前的旧值,因为使用深度监听中没有保存更新之前的旧值,这也和引用类型特点有关系
​
<body>
    <div id="app">
        <h2>1. 普通兼听</h2>
        <input type="text" placeholder="用户名" v-model="username">
        <input type="text" placeholder="年龄" v-model="age"><hr>
        <input type="text" v-model="arr[1]">
        <hr>
        <h2>深度兼听-对象</h2>
        <input type="text" v-model="person.username">
    </div>
</body>
<script src="vue.js"></script>
<script>
    new Vue({
        el: '#app',
        data: {
            username:'',
            age:'',
            arr:[ 11,22,33 ],
            person:{
                username:'zs',
                age:20
            }
        },
        methods: {
        },
        watch:{
            //一个一个的兼听器。需要定义函数,函数名就是你要兼听数据的名称
            //1. 普通兼听 
            username( newValue,oldValue ){ //第1个参数是新值,第2个旧值
                // console.log( 'username变化 了' );
                //当数据变化 了,要做的事情就写在此兼听器中。
                // console.log( this.username );
                console.log( newValue,oldValue );
            },
            age(newValue,oldValue){
                // console.log( 'age变化 了' );
                console.log( newValue,oldValue );
            },
            //兼听数组也可以使用普通兼听
            arr( newValue,oldValue ){ //数组是引用类型,新值和旧值是一致的
                console.log( newValue,oldValue );
            },
            //对象使用普通兼听-兼听不到
            // person(){
            //     console.log( '12345' );
            // },
            //2. 深度兼听-兼听对象
            person:{
                deep:true,//true深度兼听,默认为false普通兼听
                handler( newValue,oldValue ){  //对象是引用类型,新值和旧值是一致的
                    // console.log( 'person变化 了' );
                    console.log( newValue,oldValue );
                }
            }
        }
    })
</script>

2.3 百度搜索

jsonp跨域
步骤:
1.创建script标签
2.为script标签增加src属性,并且是不是要传递一个cb或callback的参数给后端
3.将script追加到文档中,才会发请求
4.返回的格式是jsonp的格式: 函数名( {} )
​
百度建议搜索的接口地址
https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd=web&cb=fn
 
<body>
    <div id="app">
        <!-- 
            使用到的知识点:
                1. watch
                2. 请求百度的数据
                    cors/jsonp
                3. 回忆jsonp原理
                    3.1 创建;script 标签
                    3.2 script的src去请求一个jsonp的地址 并且是不是要传递一个cb或callback的参数给后端
                    3.3 把script放在页面中才会真正的去请求
                    3.4 返回jsonp格式   函数名( json数据 )
​
                    https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd=web&cb=fn
         -->
         <input type="text" placeholder="输入搜索关键字" v-model="keyword">
         <ul>
             <li v-for="item in suggests">{{item}}</li>
         </ul>
    </div>
</body>
<script src="vue.js"></script>
<script>
    let vm = new Vue({
        el: '#app',
        data: {
            keyword:'',
            suggests:[]
        },
        methods: {
        },
        watch:{
            keyword(newValue,oldValue){
                    //['web','web开发','web前端']
                    //1. ;keyword,发送请求
                // this.suggests = ['web','web开发','web前端']
                if( !newValue ){ //如果未输入关键字,则无需发送请求
                    this.suggests = []
                    return
                }
                let oScript = document.createElement('script')
                oScript.src = `https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd=${newValue}&cb=fn`
                document.body.appendChild( oScript )
​
            }
        }
    })
​
​
​
    function fn( res ){
        console.log( res.s,'结果') //res.s 才是建议搜索列表
        vm.suggests = res.s
    }
​
</script>

3.计算属性

computed

3.1 作用

1. 使用计算属性可以处理一些复杂的特殊的业务逻辑
2. 一行代码无法实现的逻辑时,需要使用计算属性
特点:可能需要很变量数据,最后计算出一个结果

购物车(总价格、数量、是否全选)、学生的总成绩、评分

3.2 使用

* 方法名自定义
* 在计算属性方法中必须要有return
* return的结果被其方法名所接受
* data中的属性名不能和computed中的方法名相同
<body>
    <div id="app">

        <input type="text" v-model="lastname">
        <input type="text" v-model="firstname">

        {{getFullName}}
    </div>
</body>
<script src="vue.js"></script>
<script>
    new Vue({
        el: '#app',
        data: {
            lastname:'james',
            firstname:'lebron',
            a:'my is a'
        },
        computed:{
            // 计算属性中依赖的变量发生改变,则计算属性的值自动变化
            getFullName(){
                return (this.firstname + ' ' + this.lastname).toUpperCase()
            },
            // a(){ //* data中的属性名不能和computed中的方法名相同

            // }
        }
    })
</script>

3.3 计算属性和methods的区别

* 区别:
        1.computed中方法名直接书写, methods方法名需要调用
        2.computed中有缓存数据,在计算属性中他的数据依赖于data数据,无论被调用了几次,
         始终都会显示第一次调用的结果.只有当data中的数据发生改变时,才会被再次执行.优势:提高运行效率
        3.methods中的方法,调用几次就执行几次.
 * 相同:
        1.执行结果都一样
        2.都是采用function进行声明
* 应用场景:
        1.处理一些复杂的业务逻辑时,需要产生结果时,使用计算属性
        2.一般用来处理事件函数时,使用methods
 new Vue({
        el: '#app',
        data: {
            lastname:'james',
            firstname:'lebron',
            a:'my is a'
        },
        methods:{
            getFullName2(){
                //console.log( '----getFullName2-----' );
                return (this.firstname + ' ' + this.lastname).toUpperCase()
            }
        },
        computed:{
            // 计算属性中依赖的变量发生改变,则计算属性的值自动变化
            getFullName(){
                console.log( '----getFullName-----' );//计算属性有缓存的作用
                return (this.firstname + ' ' + this.lastname).toUpperCase()
            },
            // a(){ //* data中的属性名不能和computed中的方法名相同

            // }
        }
    })

3.4 计算属性的get和set方法:完整写法(了解)

<body>
    <div id="app">
        <input type="text" v-model="code">
        <hr>
        {{ getCode }}
    </div>
</body>
<script src="vue.js"></script>
<script>
    new Vue({
        el: '#app',
        data: {
            code:'abc'
        },
        computed:{
            //把code变为大写,还倒序
            getCode:{
                get(){
                    return this.code.toUpperCase().split('') .reverse().join('')
                },
                set(val){
                    //不是改变getCode值,而是改变getCode中某个依赖值
                    this.code = val
                }
            },
            //
        }
    })
</script>

一些优化

1.一般情况下不要将v-for和v-if一起使用, 因为v-for的优先级高于v-if:指的是不要放在一个标签上
2.使用无意义标签包裹div  template(模板标签,不会被浏览器所解析)
3. v-cloak 指令:优化我们的闪屏
<style>
    [v-cloak]{
        display: none;
    }
    /* [id='btn']{
        background-color: red;
    } */
    /* [id]{
        background-color: red;
    } */
    /* .aa{

    }
    #aaa{

    } */
</style>
<body>
    <div id="app" v-cloak>
        <button id="btn">asdf</button>
        <button id="btn1">asdf</button>
        <table border="1" style="border-collapse: collapse;" width="300">
            <tr>
                <th>id</th>
                <th>姓名</th>
                <th>数学</th>
            </tr>
            <!-- 
                1.一般情况下不要将v-for和v-if一起使用, 因为v-for的优先级高于v-if:指的是不要放在一个标签上 
                2.使用无意义标签包裹div  template(模板标签,不会被浏览器所解析)
            -->
            <template v-if="filterStudents.length > 0">
                <tr v-for="(item,index) in filterStudents" :key="item.id">
                    <td>{{item.id}}</td>
                    <td>{{item.name}}</td>
                    <td>{{item.shuxue}}</td>
                </tr>
            </template>
            <tr v-else>
                <td colspan="3">暂无数据</td>
            </tr>

            <tr>
                <td colspan="3">数学总成绩:{{getTotalShuXue}},数学平均成绩,{{getAvgShuXue}} 最高分:{{getMaxShuXue}}</td>
            </tr>
        </table>
    </div>
</body>
<script src="vue.js"></script>
<script>
    new Vue({
        el: '#app',
        data: {
            students:[
                { id:'001',name:'zs',shuxue:88 },
                { id:'003',name:'ls',shuxue:78 },
                { id:'006',name:'ww',shuxue:69 },
                { id:'009',name:'ql',shuxue:88 },
            ]
        },
        computed: {
            filterStudents(){
                return this.students.filter( (item)=>{
                    return item.shuxue > 90
                } )
            },
            getTotalShuXue(){
                let t = 0 //存放总成绩的变量: 累加
                this.students.forEach( item=>{
                    t += item.shuxue
                } )
                return t
            },
            getAvgShuXue(){
                let t = 0 //存放总成绩的变量: 累加
                this.students.forEach( item=>{
                    t += item.shuxue
                } )
                return t/this.students.length
            },
            getMaxShuXue(){
                
                let stus = [...this.students] //需要拷贝 一份,否则影响原数据 。
                // stus.sort( (stu1,stu2)=>{
                //    return stu2.shuxue - stu1.shuxue
                // } )
                stus.sort( (stu1,stu2)=>stu2.shuxue - stu1.shuxue )

                return stus[0].shuxue
            }
        }
    })
</script>

3.5 购物车案例

 

4.过滤器

处理数据,把数据整理成符合要求的格式。字符串|数值

4.1 局部过滤器

1.方法名自定义
2.系统自动传递形参:e
3.过滤器方法中必须有return,return的结果被其方法名所接受

应用场景 :
格式化时间、价格保留小数等
<body>
    <div id="app">
        <!-- | 管道符 -->
        {{ 'hello' | word2FirstUpperCase }}
        <hr>
        {{ 'world' | word2FirstUpperCase  }}
        <hr>
        <!-- 过滤器传参 -->
        {{ 'hello' | word2FirstUpperCase2(1) }}
        <hr>
        {{ 'world' | word2FirstUpperCase2(2)  }}
    </div>
</body>
<script src="vue.js"></script>
<script>
    new Vue({
        el: '#app',
        data: {
        },
        //过滤器:本质上还是函数
        filters:{
            // 英文单词首字母大写
            word2FirstUpperCase( e ){
                //必须有return返回值
                //console.log( e,'在你哪个数据后面使用了过滤器就会自动传递过来当前数据' );
                return e.substring(0,1).toUpperCase() + e.substring(1)
            },
            //
            word2FirstUpperCase2( e,num ){
                //必须有return返回值
                //console.log( e,'在你哪个数据后面使用了过滤器就会自动传递过来当前数据' );
                console.log( num );
                return e.substring(0,num).toUpperCase() + e.substring(num)
            }
        }
    })
</script>

4.2 全局过滤器

<body>
    <div id="app">
        {{ 20 | priceToFixed }}
        <hr>
        {{ 20 | priceToFixed(2) }}
    </div>
</body>
<script src="vue.js"></script>
<script>

    //在实例化之前注册全局过滤器.  Vue.filter( 名称,函数 ) 注册过滤器
    Vue.filter( 'priceToFixed',(e,num = 2)=>{
        console.log(e);
        //如果不传num默认为2
        return e.toFixed(num)
    } )

    new Vue({
        el: '#app',
        data: {
        },
        methods: {
        }
    })

</script>

4.3全局过滤器和局部过滤器的区别

全局过滤器:在任何vue实例上都可以使用
局部过滤:只在当前vue实例上使用

实际应用:
	项目中:对某一个数据频繁使用,并且是要实现过滤时,使用全局过滤器即可
		  对一写数据只在某几个功能中使用,建议使用局部过滤器.
​
<body>
    <div id="app">
        {{ 20 | priceToFixed }}
        <hr>
        {{ 20 | priceToFixed(2) }}
        <hr>
        <h2>首字母大写</h2>
        {{'aabc'|word2FirstUpperCase2}}
    </div>
​
    <hr>
    <div id="root1">
        <h2>root</h2>
        {{ 20 | priceToFixed(2) }}
        <hr>
        {{'aabc'|word2FirstUpperCase2}}
    </div>
</body>
<script src="vue.js"></script>
<script>
​
    //在实例化之前注册全局过滤器.  Vue.filter( 名称,函数 ) 注册过滤器
    Vue.filter('priceToFixed', (e, num = 2) => {
        console.log(e);
        //如果不传num默认为2
        return e.toFixed(num)
    })
​
    new Vue({
        el: '#app',
        data: {
        },
        filters: {
            word2FirstUpperCase2(e, num=1) {
                //必须有return返回值
                //console.log( e,'在你哪个数据后面使用了过滤器就会自动传递过来当前数据' );
                console.log(num);
                return e.substring(0, num).toUpperCase() + e.substring(num)
            }
        }
    })
​
​
​
​
    new Vue({
        el:'#root1'
    })
</script>

4.4 封装时间过滤器

Vue.filter('formateTime', (e, type = 'yyyy-mm-dd h:m:s') => {

               let t = new Date(e)

              let year = t.getFullYear()

                let month = t.getMonth() + 1 + ''

              month = month.padStart(2, 0)

               let day = t.getDate() + ''

            day = day.padStart(2, 0)

         let h = t.getHours() + ''

          h = h.padStart(2, 0)

         let m = t.getMinutes() + ''

           m = m.padStart(2, 0)

          let s = t.getSeconds() + ''

          s = s.padStart(2, 0)

if (type == 'yyyy-mm-dd h:m:s') {

              return `${year}-${month}-${day} ${h}:${m}:${s}`

} else if (type == 'yyyy-mm-dd') {

                return `${year}-${month}-${day}`

} else if (type == 'h:m:s') {

            return `${h}:${m}:${s}`

} else {

           return `${year}/${month}/${day}`

}

})

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值