2-Vue- vue对象提供的属性功能

今日内容

  • 3. Vue对象提供的属性功能
    • 3.1 过滤器
      • 3.1.1 使用Vue.filter()进行全局定义
      • 3.1.2 在vue对象中通过filters属性来定义
    • 3.2 计算和侦听属性
      • 3.2.1 计算属性
      • 3.2.2 监听属性
    • 3.3 vue对象的生命周期
    • 3.4 阻止事件冒泡和刷新页面
    • 3.5 综合案例-todolist

3. Vue对象提供的属性功能

3.1 过滤器

过滤器,就是vue允许开发者自定义的文本格式化函数,可以使用在两个地方:输出内容和操作数据中。

定义过滤器的方式有两种。

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

    // 全局过滤器
    Vue.filter("format",function(money){
        return money.toFixed(2)+"元"; // js中提供了一个toFixed方法可以保留2位小鼠
    });

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

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>局部过滤器</title>
    <script src="vue.js"></script>
</head>
<body>
    <div id="app">
        <p>{{price}}</p>
        <p>{{price|format}}</p>
    </div>
    <script>
        var vm = new Vue({
            el:"#app",  // vm的模板对象
            data:{      // vm的数据
                price: 8.156333,
            },
            methods:{}, // vm的方法

            // 局部过滤器只能在当前vm对象中使用
            filters:{
                format(money){
                    return money.toFixed(2)+"";
                }
            }
        });
    </script>
</body>
</html>

3.2 计算和侦听属性

3.2.1 计算属性

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

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>局部过滤器</title>
    <script src="vue.js"></script>
</head>
<body>
    <div id="app">
        <input type="text" v-model="num1">+
        <input type="text" v-model="num2">=<span>{{total}}</span>
    </div>
    <script>
        var vm = new Vue({
            el:"#app",  // vm的模板对象
            data:{      // vm的数据
                num1: 0,
                num2: 0,
            },
            methods:{}, // vm的方法
            computed:{  // 计算属性,相当于创建一个新的变量保存数据计算的结果
                total(){
                    // parseFloat 把数据转换成浮点数
                    // parseInt   把数据转换成整数
                    return parseFloat(this.num1)+parseFloat(this.num2);
                }
            }
        });
    </script>
</body>
</html>

3.2.2 监听属性

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

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

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>局部过滤器</title>
    <script src="vue.js"></script>
</head>
<body>
    <div id="app">
        <button @click="num++">赞({{num}})</button>
    </div>
    <script>
        var vm = new Vue({
            el:"#app",  // vm的模板对象
            data:{      // vm的数据
                num: 0,
            },
            watch:{ // 侦听属性,监听指定变量的值是否发生变化,当发生变化时调用对应的方法
                num(v1,v2){
                    if(this.num>=5){
                        this.num=5;
                    }
                    console.log(this.num,"修改后num="+v1,"修改前num="+v2);
                }
            }
        });
    </script>
</body>
</html>

3.3 vue对象的生命周期

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

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>局部过滤器</title>
    <script src="vue.js"></script>
</head>
<body>
    <div id="app">
        <p @click="num++">{{num}}</p>
    </div>
    <script>
        var vm = new Vue({
            el:"#app",
            data:{
                num: 10,
            },
            // beforeCreate(){
            //     console.log("----vm对象初始化完成之前自动执行的代码----");
            //     console.log(this.$el);
            //     console.log(this.$data);
            // },
            created(){ // 这里主要实现到服务端获取页面数据[ajax]
                console.log("----vm对象初始化完成以后自动执行的代码----");
                console.log(this.$el); // 没有查找到vm需要控制的元素
                console.log(this.$data); // 已经把data模型中的数据注入到vm对象里面作为属性了
            },
            // beforeMount(){
            //     console.log("----vm数据渲染到html模板之前执行的代码----");
            //     console.log(this.$el); // 没有查找到vm需要控制的元素
            // },
            mounted(){ // 修改页面的内容[页面特效]
                console.log("----vm数据渲染到html模板之后执行的代码----");
                console.log(this.$el); // 没有查找到vm需要控制的元素
            },
            // beforeUpdate(){
            //     console.log("----数据更新了,渲染之前执行的代码------");
            //     console.log(this.num);
            //     console.log(this.$el.innerHTML);
            // },
            // updated(){
            //     console.log("----数据更新了,渲染之后执行的代码------");
            //     console.log(this.num);
            //     console.log(this.$el.innerHTML);
            // },
            // 销毁vm对象 vm.$destroy()
            beforeDestroy(){
                console.log("--- 当vm对象被销毁之前,会自动执行这里的代码 ---");
                console.log( this );
            },
            destroyed(){
                console.log("--- 当vm对象被销毁以后,会自动执行这里的代码 ---");
            }
        });
    </script>
</body>
</html>

总结:

在vue使用的过程中,如果要初始化操作,把初始化操作的代码放在 mounted 中执行。
mounted阶段就是在vm对象已经把data数据实现到页面以后。一般页面初始化使用。例如,用户访问页面加载成功以后,就要执行的ajax请求。

另一个就是created,这个阶段就是在 vue对象创建以后,把ajax请求后端数据的代码放进 created

3.4 阻止事件冒泡和刷新页面

事件冒泡:指代js中子元素的事件触发以后,会导致父级元素的同类事件一并被触发到。

事件冒泡有好处,也有坏处。

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

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

使用.stop和.prevent

 

js的事件冒泡和阻止事件冒泡

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

js中利用事件冒泡现象实现事件委托

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

vue中阻止事件冒泡

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>事件冒泡</title>
    <style>
    .box1{
        width: 400px;
        height: 300px;
        background-color: orange;
        padding-top: 100px;
    }
    .box2{
        width: 200px;
        height: 200px;
        background-color: #000;
        margin: auto;
    }
    </style>
    <script src="vue.js"></script>
</head>
<body>
    <div id="app" class="box1" @click="show('点击了box1')">
        <div class="box2" @click.stop="show('点击了box2')"></div>
    </div>
    <script>
    // vue本质上就是js,所以vue中的事件操作也会存在事件冒泡现象
    // 可以使用辅助指令 @click.stop来阻止事件冒泡
    var vm = new Vue({
        el:"#app",
        methods:{
            show(message){
                alert(message);
            }
        }
    })
    </script>
</body>
</html>

vue阻止页面刷新

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>事件冒泡</title>
    <script src="vue.js"></script>
</head>
<body>
    <div id="app">
        <!-- 辅助指令可以多个链式调用 -->
        <a href="http://www.baidu.com" @click.stop.prevent="show">百度</a>
    </div>
    <script>
    // vue本质上就是js,所以vue中的事件操作也会存在事件冒泡现象
    // 可以使用辅助指令 @click.stop来阻止事件冒泡
    var vm = new Vue({
        el:"#app",
        methods:{
            show(){

            }
        }
    })
    </script>
</body>
</html>

vue阻止表单内容提交

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .box1{
            width: 200px;
            height: 200px;
            background: #ccc;
        }
        .box2{
            width: 100px;
            height: 100px;
            background: pink;
        }
    </style>
    <script src="js/vue.min.js"></script>
    <script>
    window.onload = function(){
        var vm = new Vue({
            el:"#app",
            data:{}
        })        
    }
    </script>
</head>
<body>
    <div id="app">
        <div class="box1" @click="alert('box1')">
            <div class="box2" @click.stop.prevent="alert('box2')"></div>   <!-- @click.stop来阻止事件冒泡 -->
        </div>

        <form action="#">
            <input type="text">
            <input type="submit">
            <input type="submit" value="提交02" @click.prevent=""> <!-- @click.prevent来阻止表单提交 -->
        </form>
    </div>

</body>
</html>

3.5 综合案例-todolist

我的计划列表

html代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>todolist</title>
    <style type="text/css">
        .list_con{
            width:600px;
            margin:50px auto 0;
        }
        .inputtxt{
            width:550px;
            height:30px;
            border:1px solid #ccc;
            padding:0px;
            text-indent:10px;
        }
        .inputbtn{
            width: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>
</head>
<body>
    <div class="list_con">
        <h2>To do list</h2>
        <input type="text" name="" id="txt1" class="inputtxt">
        <input type="button" name="" value="增加" id="btn1" class="inputbtn">

        <ul id="list" class="list">
            <!-- javascript:; # 阻止a标签跳转 -->
            <li>
                <span>学习html</span>
                <a href="javascript:;" class="up"></a>
                <a href="javascript:;" class="down"></a>
                <a href="javascript:;" class="del">删除</a>
            </li>
            <li><span>学习css</span><a href="javascript:;" class="up"></a><a href="javascript:;" class="down"></a><a href="javascript:;" class="del">删除</a></li>
            <li><span>学习javascript</span><a href="javascript:;" class="up"></a><a href="javascript:;" class="down"></a><a href="javascript:;" class="del">删除</a></li>
        </ul>
    </div>
</body>
</html>

特效实现效果:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>todolist</title>
    <style type="text/css">
        .list_con{
            width:600px;
            margin:50px auto 0;
        }
        .inputtxt{
            width:550px;
            height:30px;
            border:1px solid #ccc;
            padding:0px;
            text-indent:10px;
        }
        .inputbtn{
            width: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="js/vue.js"></script>
</head>
<body>
    <div id="todolist" class="list_con">
        <h2>To do list</h2>
        <input type="text" v-model="message" class="inputtxt">
        <input type="button" @click="addItem" value="增加" class="inputbtn">
        <ul id="list" class="list">
            <li v-for="item,key in dolist">
                <span>{{item}}</span>
                <a @click="upItem(key)" class="up" ></a>
                <a @click="downItem(key)" class="down"></a>
                <a @click="delItem(key)" class="del">删除</a>
            </li>
        </ul>
    </div>
    <script>
    // 计划列表代码
    let vm = new Vue({
        el:"#todolist",
        data:{
            message:"",
            dolist:[
                "学习html",
                "学习css",
                "学习javascript",
            ]
        },
        methods:{
            addItem(){
                if(this.messsage==""){
                    return false;
                }

                this.dolist.push(this.message);
                this.message = ""
            },
            delItem(key){
                // 删除和替换
                // 参数1: 开始下表
                // 参数2: 元素长度,如果不填默认删除到最后
                // 参数3: 表示使用当前参数替换已经删除内容的位置
                this.dolist.splice(key, 1);
            },
            upItem(key){
                if(key==0){
                    return false;
                }
                // 向上移动
                let result = this.dolist.splice(key,1);
                this.dolist.splice(key-1,0,result[0]);
            },
            downItem(key){
                // 向下移动
                let result = this.dolist.splice(key, 1);
                console.log(result);
                this.dolist.splice(key+1,0,result[0]);
            }
        }
    })
    </script>
</body>
</html>

作业

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

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

提示: v-for显示商品列表,商品列表作为数组保存vm对象的data属性里面
            添加商品和删除商品就是对数组的添加成员和删除指定下标成员

作业1答案

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>todolist</title>
    <style type="text/css">
        .list_con {
            width: 600px;
            margin: 50px auto 0;
        }

        .inputtxt {
            width: 550px;
            height: 30px;
            border: 1px solid #ccc;
            padding: 0px;
            text-indent: 10px;
        }

        .inputbtn {
            width: 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;
        }

        .color1 {
            background-color: orange;
        }

        .color2 {
            background-color: blue;
        }
    </style>
    <script src="vue.js"></script>
</head>
<body>
<div class="list_con" id="app">
    <h2>To do list</h2>
    <input type="text" v-model="content" id="txt1" class="inputtxt">
    <input type="button" @click="add" value="增加" id="btn1" class="inputbtn">

    <ul id="list" class="list">
        <!-- javascript:; # 阻止a标签跳转 -->
        <li v-for="item,index in todolist" :class="index%2==0?'color1':'color2'">
            <span>{{item}}</span>
            <a href="javascript:;" class="up" @click="up(index)"></a>
            <a href="javascript:;" class="down" @click="down(index)"></a>
            <a href="javascript:;" class="del" @click="del(index)">删除</a>
        </li>
    </ul>
</div>
<script>
    let vm = new Vue({
        el: "#app",
        data: {
            content: "",
            todolist: ["学习html", "学习css", "学习javascript"],
        },
        methods: {
            add() {
                // 添加计划
                this.todolist.push(this.content);
                // 清空单行文本框中的信息
                this.content = "";
            },
            del(index) {
                // 删除计划
                this.todolist.splice(index, 1);
            },
            up(index) {
                // 向上移动计划
                let current = this.todolist.splice(index, 1)[0];
                this.todolist.splice(index - 1, 0, current);
            },
            down(index) {
                // 向下移动计划
                let current = this.todolist.splice(index, 1)[0];
                this.todolist.splice(index + 1, 0, current);
            }
        }
    })
</script>
</body>
</html>
作业1参考答案

作业2答案

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
    #goods table{
        width: 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;
        width: 280px;
        height: 160px;
        padding: 40px 80px;
    }
    </style>
    <script src="vue.js"></script>
</head>
<body>
    <div id="goods">
        <button @click="is_show=true;goods_index=-1;">添加商品</button>
        <table>
            <tr>
                <th>商品编号</th>
                <th>商品标题</th>
                <th>商品数量</th>
                <th>商品价格</th>
                <th>操作</th>
            </tr>
            <tr v-for="goods,index in goods_list">
                <td>{{index+1}}</td>
                <td>{{goods.name}}</td>
                <td>
                    <button>-</button>
                    <input type="text" size="2" v-model="goods.num">
                    <button>+</button>
                </td>
                <td>{{goods.price.toFixed(2)}}</td>
                <td>
                    <button @click="update(index)">编辑</button>
                    <button @click="del(index)">删除</button>
                </td>
            </tr>
            <tr>
                <td colspan="5">总计: 1000元</td>
            </tr>
        </table>
        <div class="box" v-show="is_show">
            商品标题: <input type="text" v-model="goods_name"><br><br>
            商品数量: <input type="text" v-model="goods_num"><br><br>
            商品价格: <input type="text" v-model="goods_price"><br><br>
            <button @click="save">保存</button>
            <button @click="cancel">取消</button>
        </div>
    </div>
    <script>
        var vm = new Vue({
            el:"#goods",
            data:{
                is_show:false,
                goods_name:"",
                goods_num:"",
                goods_price:"",
                goods_index:-1, // 当前本次操作的商品信息[-1表示新增,大于0表示编辑]
                goods_list:[
                    {"name":"python入门","num":27,"price":150},
                    {"name":"python进阶","num":21,"price":100},
                    {"name":"python高级","num":17,"price":75},
                    {"name":"python研究","num":37,"price":60},
                    {"name":"python放弃","num":57,"price":110},
                ]
            },
            methods:{
                save(){
                    // 保存数据[添加数据]
                    if(this.goods_index==-1){
                        this.goods_list.push({
                            "name":this.goods_name,
                            "num":parseInt(this.goods_num),
                            "price":parseFloat(this.goods_price),
                        });
                    }else{
                        this.goods_list[this.goods_index].name=this.goods_name;
                        this.goods_list[this.goods_index].num=parseInt(this.goods_num);
                        this.goods_list[this.goods_index].price=parseFloat(this.goods_price);
                    }

                    this.cancel();
                },
                cancel(){
                    this.is_show=false;
                    this.goods_index= -1;
                    this.goods_name= "";
                    this.goods_num= "";
                    this.goods_price= "";
                },
                del(index){
                    // 删除数据
                    this.goods_list.splice(index,1);
                },
                update(index){
                    // 先弹窗
                    this.is_show=true;
                    // 显示当前编辑的商品信息
                    this.goods_index=index;
                    this.goods_name=this.goods_list[index].name;
                    this.goods_num=this.goods_list[index].num;
                    this.goods_price=this.goods_list[index].price;
                    // 当用户点击保存时,修改对应数据
                }
            }
        })
    </script>
</body>
</html>
作业2参考答案

猜你喜欢

转载自www.cnblogs.com/wgwg/p/13174542.html