三、v-model指令的详细用法、事件修饰符、按键修饰符

① v-model指令的详细用法

1.v-model指令,绑定文本框的内容,实现双向数据绑定

<input type="text" v-model="name">

2.v-model指令,绑定多行文本框的内容,实现双向数据绑定

注意:在文本区域插值 (<textarea>{{text}}</textarea>) 并不会生效,应用 v-model 来代替。

<textarea cols="80" rows="4" v-model="address"></textarea>

3.单个复选框,通过v-model绑定一个布尔值 选中=>true 不选中=> false

<input type="checkbox" v-model="isOK">

4.多个复选框,通过v-model绑定到同一个数组

<input type="checkbox" value="打篮球" v-model="hobbies">打篮球
<input type="checkbox" value="弹琴" v-model="hobbies">弹琴
<input type="checkbox" value="唱歌" v-model="hobbies">唱歌

5.多个单选框,通过v-model绑定同一个属性 

<input type="radio" value="男" name="sex" v-model="sex">男
<input type="radio" value="女" name="sex" v-model="sex">女

6. 通过v-model可以给下拉框绑定一个属性

<select v-model="education">
     <option value="小学">小学</option>
     <option value="硕士">硕士</option>
     <option value="博士">博士</option>
     <option value="博士后">博士后</option>
</select>

下拉框设置multiple属性后,就可以选择多个项 ,通过v-model可以给下拉框绑定一个数组 

<select v-model="foods" multiple>
    <option value="螃蟹">螃蟹</option>
    <option value="龙虾">龙虾</option>
    <option value="鸡腿">鸡腿</option>
    <option value="牛排">牛排</option>
    <option value="海鲜">海鲜</option>
</select>

7.v-model指令,添加.lazy修饰符,在文本框失去焦点后在更新数据

<input type="text" v-model.lazy="msg">

8. v-model指令,添加.number修饰符,在修改文本框内容时,会将修改后的内容转为

number类型

<input type="text" v-model.number="age">

9.v-model指令,添加.trim修饰符,在修改文本框内容时,会忽略前后的空格

<input type="text" v-model.trim="city">

② 事件修饰符

v-on:指令绑定事件,可以指定一个事件方法,事件方法要在methods里面定义。指定

事件方法时,如果没有给方法传递参数,默认会传递一个事件对象参数。

<button v-on:click="sayHi">Say Hi</button>

如果我们传递了一个参数,还想再传递事件对象参数,就要通过$event关键字设置。

<button v-on:click="sayHello('你好',$event)">Say Hello</button>

如果事件处理的逻辑比较简单,可以直接在行内编写。 

<button v-on:click="name+='*'">修改name</button>

1.通过.prevent事件修饰符,阻止默认行为

2.通过.stop事件修饰符,阻止事件冒泡

<div class="a" @click="a" @contextmenu.prevent="cm">
     <div class="b" @click.stop="b"></div>
</div>

3.通过.once事件修饰符,让事件方法只执行一次

<button @click.once="once">只触发一次</button>

4.通过.self事件修饰符,控制事件在当前元素自身触发,不在内部元素身上触发 

<div class="c" @click.self="c">
    <div class="d"></div>
</div>

5.默认情况下,手机的捕获模式是,从内部往外部挨个执行。 如果外部事件添

加.capture修饰符,此时事件的捕获模式就变成了,从外部到内部挨个执行。

<div class="e" @click.capture="e">
     <div class="f" @click="f"></div>
</div>

注意:修饰符可以串联。总结:使用修饰符时,顺序很重要。因此,用 v-on:click.prevent.self 会

阻止所有的点击,而 v-on:click.self.prevent 只会阻止对元素自身的点击。

③ 按键修饰符

 Vue针对键盘事件,提供了按键修饰符。一共有9个按键修饰符,分别是:

.enter 是回车键

.tab 是tab键

.delete 是删除键和退格键

.esc 是退出键

.space 是空格键

.up 是上箭头

.down 是下箭头

.left 是左箭头

.right 是右箭头

按键修饰符,也可以用按键码代替,注意:Vue3中取消了按键码

<input type="text" v-model="keywords" @keyup.13="keydown">

④ 深度响应式

Vue实例,在初始化的时候,会将对象身上的所有数据,做响应式处理,

之后再向对象中添加属性,这些属性就不再具备响应式能力了。

针对数组,只能通过以下方法,才能实现响应式:

push()   pop()    unshift()     shift()     splice()    reverse()     sort()

        <button @click="arr.push('可乐')">在末尾添加可乐</button>
        <button @click="arr.pop()">删除末尾元素</button>
        <button @click="arr.unshift('菠萝')">在开头添加菠萝</button>
        <button @click="arr.shift()">删除开始元素</button>
        <button @click="arr.splice(1,1,'榴莲')">通过方法修改元素</button>
        <button @click="arr.splice(1,2)">删除元素</button>
        <button @click="arr.reverse()">数组元素反转</button>
        <button @click="arr1.sort((a,b)=>a-b)">元素排序</button>

如何解决上面的问题?

方式1:通过Vue的set方法,更新指定的对象属性或数组成员;delete方法,删除指定对象的属性或数组的成员

方式2:通过Vue实例的$set方法,更新指定的对象属性或数组成员;$delete方法,删除指定对象的属性或数组的成员

methods: {
                // 给对象添加工作属性的方法
                addJob() {
                    // 通过观察可以发现,我们可以给对象添加属性,但是添加后的属性,不具备响应式能力。
                    // this.obj.job='前端开发工程师'
                    // set方法的参数分别是:指定的对象,对象的属性,属性值
                    // Vue.set(this.obj,'job','前端开发工程师')
                    this.$set(this.obj, 'job', '前端开发工程师')
                },
                // 删除对象身上年龄的方法
                delAge() {
                    // delete this.obj.age
                    // delete方法的参数分别是:指定的对象,对象的属性
                    // Vue.delete(this.obj,'age')
                    this.$delete(this.obj, 'age')
                },
                // 修改数组身上的成员
                updateArr() {
                    // this.arr[1] = '苹果'

                    // 这里set方法的参数分别是:指定的数组,数组的下标,对应的数据
                    this.$set(this.arr, 1, '苹果')
                },
                // 根据下标删除数组元素
                delArr() {
                    // delete this.arr[1]

                    // 这里的delete方法的参数分别是:指定的数组,数组的下标
                    this.$delete(this.arr, 3)
                }
            },

⑤ 购物车案例

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>购物车</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            list-style: none;
            text-decoration: none;
            outline: none;
        }

        #app {
            width: 700px;

        }

        table {
            border-collapse: collapse;
        }

        th,
        td {
            padding: 5px 10px;
            border: 1px solid #ccc;
        }

        img {
            width: 80px;
        }

        td .btn {
            padding: 5px 14px;
            border: none;
            border-radius: 5px;
            cursor: pointer;
        }

        td .btn:hover {
            background-color: #ea13ad;
            color: white;
        }

        td .count {
            width: 50px;
            padding: 5px;
            text-align: center;
            border: none;
        }

        td .del {
            cursor: pointer;
            padding: 5px 10px;
            border: none;
            border-radius: 5px;
        }

        td .del:hover {
            background-color: #ea13ad;
            color: white;
        }
    </style>
</head>

<body>
    <div id="app">
        <!-- 如果数组中有数据,显示购物车 -->
        <table v-if="goodses.length>0">
            <tr>
                <th><input type="checkbox" v-model="isckAll" />全选</th>
                <th>商品名称</th>
                <th>商品图片</th>
                <th>商品单价</th>
                <th>购买数量</th>
                <th>小计</th>
                <th>操作</th>
            </tr>
            <tr v-for="(item,index) in goodses" :key="item.id">
                <td><input type="checkbox" v-model="item.isck" /></td>
                <td>{{item.name}}</td>
                <td>
                    <img :src="item.img" />
                </td>
                <td>¥{{item.price | toFixed2}}</td>
                <td>
                    <!-- :disabled绑定的值为true,按钮禁用 -->
                    <button @click="item.count--" :disabled="item.count===1" class="btn">-</button>
                    <input readonly type="text" :value="item.count" class="count" />
                    <button @click="item.count++" :disabled="item.count===10" class="btn">+</button>
                </td>
                <td>¥{{item.price*item.count | toFixed2}}</td>
                <td>
                    <button @click="delGoods(index)" class="del">删除</button>
                </td>
            </tr>
            <tr>
                <td colspan="7" class="totalPrice">
                    <span>总计:¥{{totalPrice | toFixed2}}</span>
                    <!-- 过滤器可以链式调用 -->
                    <span style="color: red">${{totalPrice | toUS | toFixed2}}</span>
                </td>
            </tr>
        </table>
        <!-- 否则显示下面的div -->
        <div class="empty" v-else>您的购物车空空如也</div>
    </div>
    <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.14/vue.js"></script>
    <script>
        new Vue({
            el: "#app",
            // 数据
            data: {
                // 商品数组
                goodses: [
                    {
                        // 商品编号
                        id: "1001",
                        // 商品名称
                        name: "小米手机",
                        // 商品图片
                        img: "https://img.alicdn.com/bao/uploaded/i3/2279837698/O1CN01gkdsUP26jjYlI8HCS_!!2279837698.jpg",
                        // 商品单价
                        price: 1999,
                        // 购买数量
                        count: 3,
                        // 是否选中
                        isck: false,
                    },
                    {
                        id: "1002",
                        name: "西门子冰箱",
                        img: "https://img.alicdn.com/bao/uploaded/i4/2347095319/O1CN01xhxce31pA9MmYjHPc_!!2347095319.jpg",
                        price: 3999,
                        count: 2,
                        isck: true,
                    },
                    {
                        id: "1003",
                        name: "索尼电视",
                        img: "https://img.alicdn.com/bao/uploaded/i1/782731205/O1CN01o18KOx1KlvvaEIosx_!!0-item_pic.jpg",
                        price: 4999,
                        count: 1,
                        isck: true,
                    },
                    {
                        id: "1004",
                        name: "联想电脑",
                        img: "https://img.alicdn.com/bao/uploaded/i2/459462135/O1CN01yN7bD91RdsIyoddVW_!!459462135.jpg",
                        price: 5999,
                        count: 4,
                        isck: false,
                    },
                ],
            },
            // 方法
            methods: {
                delGoods(index) {
                    if (confirm("是否确定删除?")) {
                        this.goodses.splice(index, 1);
                    }
                },
            },
            // 计算属性
            computed: {
                // 表示是否全选
                isckAll: {
                    // 返回结果
                    get() {
                        // 商品数组中所有的商品的状态为true时,返回true
                        return (
                            this.goodses.length > 0 && this.goodses.every((g) => g.isck)
                        );
                    },
                    // 修改结果
                    set(val) {
                        // 循环所有的商品,设置所有商品的状态为最新的全选状态
                        this.goodses.forEach((g) => {
                            g.isck = val;
                        });
                    },
                },
                // 表示总价
                totalPrice() {
                    /* let total = 0
                                    for(let i=0;i<this.goodses.length;i++){
                                        if(this.goodses[i].isck){
                                            total += this.goodses[i].count * this.goodses[i].price
                                        }
                                    }
                                    return total */

                    let total = 0;
                    this.goodses.forEach((g) => {
                        if (g.isck) {
                            total += g.price * g.count;
                        }
                    });
                    return total;

                    /* return this.goodses.filter(g=>g.isck).map(g=>g.price*g.count).reduce((c,g)=>{
                                        return c + g
                                    },0) */
                },
            },
            // 过滤器
            filters: {
                // 数字保留两位小数
                toFixed2(val) {
                    return val.toFixed(2);
                },
                // 转美金的方法
                toUS(val) {
                    return val / 6.444;
                },
            },
            // 监听器
            watch: {
                // 监听totalPrice计算属性的值的变化
                totalPrice(val) {
                    if (val >= 10000) {
                        alert("请理性消费!");
                    }
                },
            },
        });
    </script>
</body>

</html>

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值