• bjday2——vue过滤器、计算和监听属性、阻止事件冒泡


    一、Vue对象提供的属性功能

    1. 过滤器

    过滤器,就是Vue允许开发者自定义文本格式化函数, 可以使用在两个地方:

    输出内容和操作数据。

    自定义过滤器的两种方法:

    1.1 使用Vue.filter()进行全局定义

    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <script src="vue.js"></script>
        <style>
            #goods table {
                 600px;
                border: 1px solid #000;
                border-collapse: collapse;
            }
    
            #goods td, #goods th {
                border: 1px solid #000;
            }
    
            #goods .box {
                position: fixed;
                top: 0;
                left: 0;
                right: 0;
                bottom: 0;
                margin: auto;
                background-color: #eee;
                 280px;
                height: 160px;
                padding: 40px 80px;
            }
        </style>
    </head>
    <body>
    <div id="goods">
        <button @click="change">添加商品</button>
        <div class="box" v-show="show">
            商品标题: <input type="text" v-model="goods_info.name"><br><br>
            商品数量: <input type="text" v-model="goods_info.num"><br><br>
            商品价格: <input type="text" v-model="goods_info.price"><br><br>
            <button @click="add_goods">保存</button>
            <button @click="change">取消</button>
        </div>
        <table>
            <tr>
                <th>商品id</th>
                <th>商品标题</th>
                <th>商品数量</th>
                <th>商品价格</th>
            </tr>
            <tr :bgcolor="index%2==0?color.even:color.odd" v-for="(book,index) in goods_list">
                <td>{{index}}</td>
                <td>{{book.name}}</td>
                <td>{{book.num}}</td>
                <td>{{book.price}}</td>
            </tr>
        </table>
    </div>
    <script>
        let vm = new Vue({
            el: '#goods',
            data: {
                color: {
                    odd: '#ffaaaa',
                    even: '#aaaaff',
                },
                show: false,
                goods_info: {'name': '', 'num': 0, 'price': 0},
                goods_list: [
                    {'name': 'python入门', 'num': 11, 'price': 11.11},
                    {'name': 'python进阶', 'num': 22, 'price': 22.22},
                    {'name': 'python高级', 'num': 33, 'price': 33.33},
                    {'name': 'python放弃', 'num': 44, 'price': 44.44},
                ]
            },
            methods: {
                change() {
                    // 点击之后切换show的布尔值,默认为false隐藏添加窗口,点击保存或取消时,切换为false从而将商品隐藏
                    this.show = this.show != true
                },
                add_goods() {
                    // &&与关系同真才为真,输入框都输入数据的时候才能进行保存
                    if (this.goods_info.name && this.goods_info.num && this.goods_info.price) {
                        // 将用户输入数据组成的对象插入到商品列表中
                        this.goods_list.push(this.goods_info);
                        // 将添加商品窗口隐藏
                        this.show = this.show != true
                    } else {
                        // 将添加商品窗口隐藏
                        this.show = this.show != true
                        return false;
                    }
                },
            }
        })
    </script>
    

    image-20200617155022354

    1.2 . 在vue对象中通过filters属性来定义

    <div id="app">
        <div>{{money}}</div>
        <div>{{money|format}}</div>
    </div>
    <script>
        let vm = new Vue({
            el:'#app',
            data:{
                money:6.666
            },
            filters:{
                format(money){
                    return money.toFixed(2)
        }
            }
        })
    </script>
    

    局部过滤器只能在当前vm对象中使用

    2. 计算和监听属性

    2.1 计算属性

    我们之前学习过字符串反转,如果直接把反转的代码写在元素中,则会使得其他同事在开发时时不易发现数据被调整了,所以vue提供了一个计算属性(computed),可以让我们把调整data数据的代码存在在该属性中。

    <div id="app">
        <p>{{str1}}</p>
        <p>{{str1Rvs}}</p>
    </div>
    <script>
        let vm = new Vue({
            el:'#app',
            data:{
                str1:'ABCDEF'
            },
            computed:{  //计算属性:里面的函数都必须有返回值
                str1Rvs:function(){
                    return this.str1.split("").reverse().join("")
                }
            }
        })
    </script>
    

    再举个小例子,页面有两个input框和一个span标签,可以用计算属性实现将两个框子动态输入的值求和后展示到span标签内。

    <div id="app">
        <input type="text" v-model="num1">+
        <input type="text" v-model="num2">=
        <span>{{sum}}</span>
    </div>
    <script>
        let vm = new Vue({
            el: '#app',
            data: {
                num1: 0,
                num2: 0,
            },
            computed: {
                sum() {
                    // 前端页面输入的内容全都是字符,需要转成数据类型
                    // ( parseFloat/parseInt/number:浮点/整型)
                    let num3 = parseFloat(this.num1) + parseFloat(this.num2)
                    // let num3 = parseInt(this.num1) + parseInt(this.num2)
                    return num3
                }
            }
        })
    </script>
    

    小数可以相加:

    image-20200617163719174

    小数部分忽略:

    image-20200617163339381

    2.2 监听属性

    监听属性可以帮助我们监听vm对象data内的某个数据的变化,从而做出相应的自定义操作。

    监听属性是一个对象,他的键是data内要监听的对象或者是变量,值一般是函数,当监听的数据发生变换是,会触发对应自定义函数的执行。这个函数被调用时,vue会传入两个形参,第一个是变化后的数据值,第二个是变化前的数据值

    <div id="app">
        <button @click="num++">赞{{num}}</button>
    
    </div>
    <script>
        let vm = new Vue({
            el: '#app',
            data: {
                num: 0
            },
            watch: {
                num(new_v, old_v) {
                    if (this.num >= 5) {
                        this.num = 5
                    }
                    console.log('修改之后的值:' + new_v, '修改之前的值:' + old_v)
                }
            }
        })
    </script>
    

    image-20200617165509947

    3. vue对象的生命周期

    3.1 钩子函数

    每个Vue对象载创建是都要经过一系列的初始化过程。在这个过程中Vue.js会自动运行生命周期提供的钩子函数,我们可以使用这些函数,在对象创建的不同阶段加上我们需要的代码,实现特定的功能。

    vue对象的生命周期流程图

    • beforeCreate:vm对象尚未创建
    • created:created:vm对象创建完成,设置好了要控制的元素范围
    • beforeMount:vm对象尚未把data数据显示到页面中
    • mounted:vm对象已经把data数据显示到页面中
    • beforeUpdate:vm对象尚未把更新后的data数据显示到页面中
    • updated:vm对象已经把更新后的data数据显示到页面中
    • beforeDestroy:vm对象销毁回收前
    • destoryed:vm对象销毁回收之后
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <script src="js/vue.min.js"></script>
        <script>
        window.onload = function(){
            var vm = new Vue({
                el:"#app",
                data:{
                    num:0
                },
                beforeCreate:function(){
                    console.log("beforeCreate,vm对象尚未创建,num="+ this.num);  //undefined
                    this.name=10; // 此时没有this对象呢,所以设置的name无效,被在创建对象的时候被覆盖为0
                },
                created:function(){
                    console.log("created,vm对象创建完成,设置好了要控制的元素范围,num="+this.num );  // 0
                    this.num = 20;
                },
                beforeMount:function(){
                    console.log( this.$el.innerHTML ); // <p>{{num}}</p>
                    console.log("beforeMount,vm对象尚未把data数据显示到页面中,num="+this.num ); // 20
                    this.num = 30;
                },
                mounted:function(){
                    console.log( this.$el.innerHTML ); // <p>30</p>
                    console.log("mounted,vm对象已经把data数据显示到页面中,num="+this.num); // 30
                },
                beforeUpdate:function(){
                    // this.$el 就是我们上面的el属性了,$el表示当前vue.js所控制的元素#app
                    console.log( this.$el.innerHTML );  // <p>30</p>
                    console.log("beforeUpdate,vm对象尚未把更新后的data数据显示到页面中,num="+this.num); // beforeUpdate----31
                    
                },
                updated:function(){
                    console.log( this.$el.innerHTML ); // <p>31</p>
                    console.log("updated,vm对象已经把过呢更新后的data数据显示到页面中,num=" + this.num ); // updated----31
                },
            });
        }
        </script>
    </head>
    <body>
        <div id="app">
            <p>{{num}}</p>
            <button @click="num++">按钮</button>
        </div>
    </body>
    </html>
    

    最常用的是created和mounded,vue对象创建以后,把ajax请求后端数据的代码放进 created,在vue使用的过程中,如果要初始化操作,把初始化操作的代码放在 mounted 中执行。

    4. 阻止时间冒泡阻止页面刷新

    事件冒泡:指代js中内层的子元素的事件触发以后,如果外层的父级元素具有该类事件,会导致父级元素的该类事件一并被触发到。

    好处:如果能正确利用这种现象,可以实现事件委托,提升特效的性能

    坏处:如果没有正确使用,则会导致不必要的bug出现。

    4.1 js中阻止事件冒泡:

    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>事件冒泡</title>
        <style>
            .box1 {
                 400px;
                height: 300px;
                background-color: orange;
                padding-top: 100px;
            }
    
            .box2 {
                 200px;
                height: 200px;
                background-color: #000;
                margin: auto;
            }
        </style>
    </head>
    <body onclick="alert('点击了body')">
    <div class="box1">
        <div class="box2"></div>
        <script>
            let box1 = document.getElementsByClassName("box1")[0];
            let box2 = document.getElementsByClassName("box2")[0];
            box1.onclick = function (event) {
                alert('点了box1')
                // event.stopPropagation();
            }
            box2.onclick = function (event) {
                alert('点了box2');
                event.stopPropagation();
            }
        </script>
    </div>
    </body>
    </html>
    

    给需要阻止冒泡的事件内加上event.stopPropagation()

    4.2 vue阻止事件冒泡

    事件后加.top,如:

    @click=""——>@click.stop=""

    <div id="app" class="box1" @click="show('点击了box1')">
        <div class="box2" @click.stop="show('点击了box2')"></div>
    </div>
    <script>
        let vm = new Vue({
            el:'#app',
            data:{},
            methods:{
                show(message){
                    alert(message)
                }
            }
        })
    </script>
    

    4.3 阻止页面刷新

    可用于表单submit按钮,点击后提交数据阻止页面的刷新。

    事件后加.prevent,如:

    @click=""——>@click.stop.prevent=""

    <div id="app">
        <a href="https://www.baidu.com" @click.prevent="show">百度</a>  <!--点击后不在跳转到百度-->
    </div>
    <script>
        let vm = new Vue({
            el:'#app',
            data:{},
            methods:{
                show(){}
            }
        })
    </script>
    

    4.4 事件委托

    事件委托就是利用事件冒泡的原理,将多个子元素的事件交给父元素去绑定执行,提升事件的 效率,并且通过event.target,还能找到目标子元素。

    <body>
        <ul id="app">
            <li>1111111111111111</li>
            <li>2222222222222222</li>
            <li>3333333333333333</li>
            <li>4444444444444444</li>
            <li>5555555555555555</li>
        </ul>
    <script>
        var ul = document.getElementById('app')
        ul.onclick = function (event) {
            let self = event.target
            console.log(self.innerHTML)
        }
    </script>
    

    5. 综合案例-todolist

    学习计划表

    5.1 展示也有计划

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>todolist</title>
        <style type="text/css">
            .list_con {
                 600px;
                margin: 50px auto 0;
            }
    
            .inputtxt {
                 550px;
                height: 30px;
                border: 1px solid #ccc;
                padding: 0px;
                text-indent: 10px;
            }
    
            .inputbtn {
                 40px;
                height: 32px;
                padding: 0px;
                border: 1px solid #ccc;
            }
    
            .list {
                margin: 0;
                padding: 0;
                list-style: none;
                margin-top: 20px;
            }
    
            .list li {
                height: 40px;
                line-height: 40px;
                border-bottom: 1px solid #ccc;
            }
    
            .list li span {
                float: left;
            }
    
            .list li a {
                float: right;
                text-decoration: none;
                margin: 0 10px;
            }
        </style>
        <script src="vue.js"></script>
    </head>
    <body>
    <div id="app">
        <input type="text" class="inputtxt">
        <input type="button" class="inputbtn" value="增加">
        <ul class="list">
            <li v-for="items in todolist" id="list">
                <span>{{items}}</span>&nbsp;&nbsp;
                <!--javascript:阻止a标签跳转-->
                <a href="javascript:;" class="up">↑</a>&nbsp;&nbsp;
                <a href="javascript:;" class="down">↓</a>&nbsp;&nbsp;
                <a href="javascript:;" class="del">删除</a>
            </li>
        </ul>
    
    </div>
    <script>
        let vm = new Vue({
            el: '#app',
            data: {
                todolist: ["学习html", "学习css", "学习javascript", "学习语文"]
            },
        })
    </script>
    </body>
    </html>
    

    5.2 添加新的学习计划及修改计划顺序

    <body>
    <div id="app" class="list_con">
        <input type="text" class="inputtxt" v-model="message">
        <input type="button" class="inputbtn" value="增加" @click="add">
        <ul class="list">
            <li v-for="items,index in todolist" id="list">
                <span>{{items}}</span>&nbsp;&nbsp;
                <!--javascript:阻止a标签跳转-->
                <a href="javascript:;" class="up" @click="up(index)">↑</a>&nbsp;&nbsp;
                <a href="javascript:;" class="down" @click="down(index)">↓</a>&nbsp;&nbsp;
                <a href="javascript:;" class="del" @click="delItem(index)">删除</a>
            </li>
        </ul>
    
    </div>
    <script>
        let vm = new Vue({
            el: '#app',
            data: {
                message: '',
                todolist: ["学习html", "学习css", "学习javascript", "学习语文"]
            },
            methods: {
                // 添加计划
                add() {
                    if (this.message == "") {
                        return false
                    } else {
                        let item = this.message;
                        this.todolist.push(item)
                        this.message="";
                    }
                },
                // 上移计划
                up(index) {
                    // splice() 从数组中添加/删除项目,然后返回被删除的项目,
                    // 参数1/参数2/参数3:删除的起始索引/删除的个数,0则不删/删除后替补的值,不删时为添加。
                    let current = this.todolist.splice(index, 1)[0];  // 获取当前删除的索引对应的值
                    console.log(current)
                    this.todolist.splice(index - 1, 0, current)
                },
                // 下移计划
                down(index) {
                    let current = this.todolist.splice(index, 1)[0];
                    console.log(current)
                    this.todolist.splice(index + 1, 0, current)
                },
                // 删除计划
                del(index) {
                    this.todolist.splice(index, 1)
                }
            }
        })
    </script>
    </body>
    

    效果:

    展示计划:

    image-20200617210641570

    添加计划:

    image-20200617210819123

    删除计划:

    image-20200617210949734

    上移计划:

    image-20200617211233347

    下移计划:

    image-20200617211934357

    补充:事件的函数名千万不要和data里面的数据变量名相同,会冲突。

    作业

    一、完成todolist的案例,在todolist中实现隔行换色效果奇数行的计划, 背景色为"blue"偶数行的计划,背景色为"orange"

     # 修改背景颜色
    # ccs样式
    <style>
            .odd{
                background-color: blue;
            }
            .even{
                background-color: orange;
            }
    </style> 
    # 其他代码和上面综合例子相同,不同的就是下面一行用于修改背景颜色。
    <li :class="index%2==0?'even':'odd'" v-for="(items,index) in todolist" id="list">
    

    效果:

    image-20200617234012076

    二、使用vue.js完成表格的管理功能[添加数据,取消添加、展示商品列表,编辑商品信息,取消编辑,删除商品]
    商品id默认使用下标作为值

    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <script src="vue.js"></script>
        <style>
            #goods table {
                 600px;
                border: 1px solid #000;
                border-collapse: collapse;
            }
    
            #goods td, #goods th {
                border: 1px solid #000;
            }
    
            #goods .box {
                position: fixed;
                top: 0;
                left: 0;
                right: 0;
                bottom: 0;
                margin: auto;
                background-color: #eee;
                 280px;
                height: 160px;
                padding: 40px 80px;
            }
        </style>
    </head>
    <body>
    <div id="goods">
        <button @click="change">添加商品</button>
        <div class="box" v-show="show">
            商品标题: <input type="text" v-model="goods_info.name"><br><br>
            商品数量: <input type="text" v-model="goods_info.num"><br><br>
            商品价格: <input type="text" v-model="goods_info.price"><br><br>
            <button @click="add_goods">保存</button>
            <button @click="change">取消</button>
        </div>
        <table>
            <tr>
                <th>商品id</th>
                <th>商品标题</th>
                <th>商品数量</th>
                <th>商品价格</th>
            </tr>
            <tr :bgcolor="index%2==0?color.even:color.odd" v-for="(book,index) in goods_list">
                <td>{{index}}</td>
                <td>{{book.name}}</td>
                <td>{{book.num}}</td>
                <td>{{book.price}}</td>
            </tr>
        </table>
    </div>
    <script>
        let vm = new Vue({
            el: '#goods',
            data: {
                color: {
                    odd: '#ffaaaa',
                    even: '#aaaaff',
                },
                show: false,
                goods_info: {'name': '', 'num': 0, 'price': 0},
                goods_list: [
                    {'name': 'python入门', 'num': 11, 'price': 11.11},
                    {'name': 'python进阶', 'num': 22, 'price': 22.22},
                    {'name': 'python高级', 'num': 33, 'price': 33.33},
                    {'name': 'python放弃', 'num': 44, 'price': 44.44},
                ]
            },
            methods: {
                change() {
                    // 点击之后切换show的布尔值,默认为false隐藏添加窗口,点击保存或取消时,切换为false从而将商品隐藏
                    this.show = this.show != true
                },
                add_goods() {
                    // &&与关系同真才为真,输入框都输入数据的时候才能进行保存
                    if (this.goods_info.name && this.goods_info.num && this.goods_info.price) {
                        // 将用户输入数据组成的对象插入到商品列表中
                        this.goods_list.push(this.goods_info);
                        // 将添加商品窗口隐藏
                        this.show = this.show != true
                    } else {
                        // 将添加商品窗口隐藏
                        this.show = this.show != true
                        return false;
                    }
                },
            }
        })
    </script>
    

    效果:

    1:

    image-20200617234300765

    2:

    image-20200617234410622

    3:

    image-20200617234439668

  • 相关阅读:
    4.Linux的目录结构
    使用idea创建spring mvc项目图文教程
    传统的Servlet在spring boot中怎么实现的?
    springboot系列教程导学篇
    记录一次序列化引起的问题解决办法 查看已编译类序列化值
    springboot支付项目之springboot集成jpa
    springboot支付项目之日志配置
    设计模式之状态模式总结篇
    看了这个Java实习生入职测试题后,幸亏我不是实习生
    幂等性学习及接口的幂等性
  • 原文地址:https://www.cnblogs.com/zhangtieshan/p/13155385.html
Copyright © 2020-2023  润新知