[vue]6-vue的事件绑定/条件渲染/循环/表单绑定

事件监听

在前端开发中,我们需要经常和用于交互。

  • 这个时候,我们就必须监听用户发生的时间,比如点击、拖拽、键盘事件等等

  • 在Vue中如何监听事件呢?使用v-on指令

v-on介绍

  • 作用:绑定事件监听器
  • 缩写:@
  • 预期:Function | Inline Statement | Object
  • 参数:event

v-on基础

这里,我们用一个监听按钮的点击事件,来简单看看v-on的使用

下面的代码中,我们使用了v-on:click="counter++”

另外,我们可以将事件指向一个在methods中定义的函数

    <div id="app">
        <h2>{{number}}</h2>
        <button v-on:click="number++">按钮1</button>
        <button v-on:click="changeNumber">按钮2</button>
    </div>
    <script>
        let app = new Vue({
            el: '#app',
            data: {
                number: ''
            },
            methods: {
                changeNumber() {
                    this.number++
                }
            }
        })
    </script>

在这里插入图片描述

点击哪一个都可以让number增加

注:v-on也有对应的语法糖

​ v-on:click可以写成@click

        <button @click="number++">按钮1</button>
        <button @click="changeNumber">按钮2</button>

效果也是一样的

v-on参数

  • 当通过methods中定义方法,以供@click调用时,需要注意参数问题

  • 情况一:如果该方法不需要额外参数,那么方法后的()可以不添加。

    • 但是注意:如果方法本身中有一个参数,那么会默认将原生事件event参数传递进去
  • 情况二:如果需要同时传入某个参数,同时需要event时,可以通过$event传入事件。

没有传参数

    <div id="app">
        <h2>{{number}}</h2>
        <button @click="btnClick">按钮</button>
    </div>
    <script>
        let app = new Vue({
            el: '#app',
            data: {
                number: ''
            },
            methods: {
                // 如果不传递参数,默认vue给我传一个参数,这个参数就是event
                btnClick(e) {
                    console.log(e)
                }
            }
        })
    </script>

如果传了参数,又想要event

    <div id="app">
        <h2>{{number}}</h2>
        <button @click="btnClick(3, $event)">按钮</button>
    </div>
    <script>
        let app = new Vue({
            el: '#app',
            data: {
                number: ''
            },
            methods: {
                // 如果传参数了,number这个值就是那个参数,如果想再要event,name就需要传过来
                btnClick(number, event) {
                    console.log(number, event)
                }
            }
        })
    </script>

v-on修饰符

在某些情况下,我们拿到event的目的可能是进行一些事件处理。

但是不想写一个函数,想更简单点,这个vue也帮我们实现了

Vue提供了修饰符来帮助我们方便的处理一些事件:

  • .stop - 调用 event.stopPropagation()。阻止冒泡
  • .prevent - 调用 event.preventDefault()。阻止默认事件
  • .{keyCode | keyAlias} - 只当事件是从特定键触发时才触发回调。
  • .native - 监听组件根元素的原生事件。
  • .once - 只触发一次回调。
    <div id="app">
        <!-- 阻止冒泡 -->
        <button @click.stop="stopBubble">按钮</button>
        <!-- 阻止默认行为 -->
        <button @click.prevent="stopDefault">按钮</button>
        <!-- 阻止默认行为,如果不需要事件函数,也可以直接这样写 -->
        <button @click.prevent>按钮</button>
        <!-- 既阻止默认行为,又阻止冒泡 -->
        <button @click.prevent.stop="stop">按钮</button>
        <!-- enter键盘修饰符 -->
        <input @keyup.enter="btnEnter1" type="text">
        <!-- enter键盘修饰符 -->
        <input type="text" @keyup.13="btnEnter2">
        <!-- 点击回调只会触发一次 -->
        <button @click.once="onlyOne">按钮</button>
    </div>

v-on绑定多个事件

    <div id="app">
        <div v-on="{mousemove:isMouseMove, click:isClick}" class="box"></div>

    </div>
    <script>
        let app = new Vue({
            el: '#app',
            data: {

            },
            methods: {
                isMouseMove() {
                    console.log('我是isMouseMove')
                },
                isClick() {
                    console.log('我是isClick')
                }
            }
        })
    </script>

在这里插入图片描述

一个事件绑定多个函数

    <div id="app">
        <div @click="one(), two()" class="box"></div>

    </div>
    <script>
        let app = new Vue({
            el: '#app',
            data: {

            },
            methods: {
                one() {
                    console.log('我是one')
                },
                two() {
                    console.log('我是two')
                }
            }
        })
    </script>

在这里插入图片描述

条件渲染

v-if、v-else-if、v-else

  • 这三个指令与JavaScript的条件语句if、else、else if类似。
  • Vue的条件指令可以根据表达式的值在DOM中渲染或销毁元素或组件
    <div id="app">
        <div v-if="score >= 90">优秀</div>
        <div v-else-if="score >= 80">良好</div>
        <div v-else="score >= 60">及格</div>
    </div>
    <script>
        let app = new Vue({
            el: '#app',
            data: {
                score: 80
            }
        })
    </script>

注意:

  • 指令后面跟的是表达式,不需要花括号。
  • v-else 元素必须紧跟在带 v-if 或者 v-else-if 的元素的后面,否则它将不会被识别。

v-if的原理:

  • v-if后面的条件为false时,对应的元素以及其子元素不会渲染。
  • 也就是根本没有不会有对应的标签出现在DOM中。

条件渲染案例

  • 用户再登录时,可以切换使用用户账号登录还是邮箱地址登录。
    <div id="app">
        <span v-if="type === 'userId'">
            <label for="userId">用户账号:</label>
            <input type="text" placeholder="请输入账号" id="userId">
        </span>
        <span v-else>
            <label for="email">邮箱地址:</label>
            <input type="email" placeholder="请输入邮箱地址" id="email">
        </span>
        <button @click="changeType">切换类型</button>
    </div>
    <script>
        let app = new Vue({
            el: '#app',
            data: {
                type: 'userId'
            },
            methods: {
                changeType() {
                    this.type = this.type === 'userId' ?  'userEmail' : 'userId'
                }
            }
        })
    </script>

案例小问题

  • 如果我们在有输入内容的情况下,切换了类型,我们会发现文字依然显示之前的输入的内容。
  • 但是按道理讲,我们应该切换到另外一个input元素中了。
  • 在另一个input元素中,我们并没有输入内容。

为什么呢?

  • 这是因为Vue在进行DOM渲染时,出于性能考虑,会尽可能的复用已经存在的元素,而不是重新创建新的元素。
  • 在上面的案例中,Vue内部会发现原来的input元素不再使用,直接作为else中的input来使用了。

解决方案:

  • 如果我们不希望Vue出现类似重复利用的问题,可以给对应的input添加key
  • 并且我们需要保证key的不同
    在这里插入图片描述

v-show

v-show的用法和v-if非常相似,也用于决定一个元素是否渲染:

    <div id="app">
        <h2 v-show="isShow">我要不要显示呢?</h2>
    </div>
    <script>
        let app = new Vue({
            el: "#app",
            data: {
                isShow: true
            }
        })
    </script>

会显示出来
在这里插入图片描述

如果是false就什么都不显示

v-if和v-show都可以决定一个元素是否渲染,那么开发中我们如何选择呢?

区别

  • v-if当条件为false时,压根不会有对应的元素在DOM中(创建和销毁节点)。
  • v-show当条件为false时,仅仅是将元素的display属性设置为none而已。

开发中如何选择呢?

  • 当需要在显示与隐藏之间切片很频繁时,使用v-show
  • 当只有一次切换时,通过使用v-if

其实 v-if 是重新重建一个标签,而v-show仅仅是把代码的css修改了 display:none

对性能而言,如果使用v-if 在每一次切换的时候都会重新创建一个标签或组件,然后卸载一个标签或组件,这样做对性能的要求比较高

而v-show仅仅是display:none,打开,对性能的要求相对较小,但是第一次加载组件的时候v-show是会被创建的,所以就有了上面那个结论,在开发中如何选择。

在这里插入图片描述

v-for循环遍历

v-for可以遍历数组,字符串,对象,number

v-for遍历数组

当我们有一组数据需要进行渲染时,我们就可以使用v-for来完成。

v-for的语法类似于JavaScript中的for循环。

格式如下:item in items的形式。(item of items 也可以)

如果在遍历的过程中不需要使用索引值

  • v-for=“movie in movies”
  • 依次从movies中取出movie,并且在元素的内容中,我们可以使用Mustache语法,来使用movie

如果在遍历的过程中,我们需要拿到元素在数组中的索引值呢?

  • 语法格式:v-for=(item, index) in items
  • 其中的index就代表了取出的item在原数组的索引值。
    <div id="app">
        <ul>
            <!-- 如果需要需要,每一项和序号之间用逗号隔开,并且需要用括号括起来 -->
            <li v-for="(item, index) in data">序号:{{index}}---->内容:{{item}}</li>
        </ul>
    </div>
    <script>
        let app = new Vue({
            el: "#app",
            data: {
                data: [
                    '乡村爱情1',
                    '乡村爱情2',
                    '乡村爱情3',
                    '乡村爱情4'
                ]
            }
        })
    </script>

在这里插入图片描述

v-for遍历对象

    <div id="app">
        <ul>
            <!-- 循环对象的话,有三个值可以使用,第一个是键值,第二个值是键名,第三个值是序号 -->
            <li v-for="(item, key, index) in obj">序号:{{index}}---->键名:{{key}};   键值----->{{item}}</li>
        </ul>
    </div>
    <script>
        let app = new Vue({
            el: "#app",
            data: {
                obj: {
                    name: 'vue',
                    age: '5',
                    initiator: '尤雨溪'
                }
            }
        })
    </script>

在这里插入图片描述

v-for遍历字符串

    <div id="app">
        <ul>
            <!-- 循环字符串的话,有两个值可以使用,第一个是内容,第二个值是序号 -->
            <li v-for="(item, index) in string">序号:{{index}}---->内容:{{item}}</li>
        </ul>
    </div>
    <script>
        let app = new Vue({
            el: "#app",
            data: {
                string:'hello world'
            }
        })
    </script>

在这里插入图片描述

v-for循环数字

    <div id="app">
        <ul>
            <!-- 循环数字的话,有两个值可以使用,第一个是内容,第二个值是序号 -->
            <li v-for="(item, index) in 10">序号:{{index}}---->内容:{{item}}</li>
        </ul>
    </div>

组件的key属性

官方推荐我们在使用v-for时,给对应的元素或组件添加上一个:key属性。

为什么需要这个key属性呢(了解)?

  • 这个其实和Vue的虚拟DOM的Diff算法有关系。
  • 这里我们借用React’s diff algorithm中的一张图来简单说明一下:

当某一层有很多相同的节点时,也就是列表节点时,我们希望插入一个新的节点

  • 我们希望可以在B和C之间加一个F,Diff算法默认执行起来是这样的。
  • 即把C更新成F,D更新成C,E更新成D,最后再插入E,是不是很没有效率?

所以我们需要使用key来给每个节点做一个唯一标识

  • Diff算法就可以正确的识别此节点
  • 找到正确的位置区插入新的节点。

所以一句话,key的作用主要是为了高效的更新虚拟DOM。

在这里插入图片描述

如果我要往ABCDE里面插入一个F

在这里插入图片描述

是左边这个顺序,就是本来一个标签对应一个字母,

但是我新来一个,这个时候,就需要重新编排,比如以前的li1对应A,li2对应B

我要在B和C之间插入C,这个时候,li3对应的C就变了,编程li3对应F,li4对应C,依次往后排了

在这里插入图片描述

这样的效率比较低,那么加了key会怎么样呢

在这里插入图片描述

他就会按照右边,每一个key都对应一个li,也对应一个字母,比如给li1加一个key它的值是A,那么它类似绑定了,就算你再来一个,也不会重新创建li,并且给li加一个值,不会这样的,他会怎么样呢,如果你在c和d之间加入z,每一个li都有key,都有绑定的值,他们都不变,只是在cd之间创建一个li,再绑定上key,绑定上值。这样的效率更高。

上面的li,li1都是举例,也就是

  • 有很多,li1表示第一个li标签

    所以,key必须是唯一的,否则没有意义

    当然如果在最后一个加,加不加key都一样

    在这里插入图片描述

    检测数组更新

    因为Vue是响应式的,所以当数据发生变化时,Vue会自动检测数据变化,视图会发生对应的更新。

    Vue中包含了一组观察数组编译的方法,使用它们改变数组也会触发视图的更新。

    push()

    pop()

    shift()

    unshift()

    splice()

    sort()

    reverse()

    这些方法和原生js类似。

    this.letters.push('aaa')
    

    类似这种,可以和普通的js一样使用

    案例:

    在这里插入图片描述

    实现上图效果

        <div id="app">
            <table>
                <thead>
                    <tr>
                        <td></td>
                        <td>书籍名称</td>
                        <td>出版日期</td>
                        <td>价格</td>
                        <td>购买数量</td>
                        <td>操作</td>
                    </tr>
                </thead>
                <tbody>
                    <tr v-for="(item, index) in nv" :key="item.name">
                        <td>{{index}}</td>
                        <td>{{item.name}}</td>
                        <td>{{item.time}}</td>
                        <td>{{item.price}}</td>
                        <td>
                            <button @click="decrease(index)">-</button>
                            {{item.num}}
                            <button @click="increase(index)">+</button>
                        </td>
                        <td>
                            <button @click="del(index)">移除</button>
                        </td>
                    </tr>
                </tbody>
            </table>
            <p>总价:{{allPrice}}</p>
        </div>
        <script>
            let app = new Vue({
                el: "#app",
                data: {
                    nv: [
                        {
                            name: '《算法导论》',
                            time: '2006-9',
                            price: '¥85.00',
                            num: 1,
                        },
                        {
                            name: '《unix编程艺术》',
                            time: '2006-2',
                            price: '¥59.00',
                            num: 1,
                        }, {
                            name: '《编程珠玑》',
                            time: '2008-10',
                            price: '¥39.00',
                            num: 1,
                        },
                        {
                            name: '《编程大全》',
                            time: '2006-3',
                            price: '¥128.00',
                            num: 1,
                        }
                    ],
                },
                computed: {
                    allPrice() {
                        return this.nv.reduce((item, curr) => {
                            let price = curr.price.substr(1)
                            let arr = price.split('.')
                            return item + arr[0] * curr.num
                        }, 0)
                    }
                },
                methods: {
                    increase(index) {
                        this.nv[index].num += 1;
                    },
                    decrease(index) {
                        this.nv[index].num -=1;
                        if(this.nv[index].num < 0) {
                            this.nv[index].num = 0
                        }
                    },
                    del(index) {
                        this.nv.splice(index, 1)
                    }
                }
            })
        </script>
    

    v-model

    表单绑定v-model

    表单控件在实际开发中是非常常见的。特别是对于用户信息的提交,需要大量的表单。

    Vue中使用v-model指令来实现表单元素和数据的双向绑定。

    • 绑定input
        <div id="app">
            <input type="text" v-model="message">
            <p>输入的内容是:{{message}}</p>
        </div>
        <script>
            let app = new Vue({
                el: '#app',
                data: {
                    message:''
                }
            })
        </script>
    

    在这里插入图片描述

    案例的解析:

    • 当我们在输入框输入内容时

    • 因为input中的v-model绑定了message,所以会实时将输入的内容传递给message,message发生改变。

    • 当message发生改变时,因为上面我们使用Mustache语法,将message的值插入到DOM中,所以DOM会发生响应的改变。

    • 所以,通过v-model实现了双向的绑定。

    • 绑定textarea

        <div id="app">
            <textarea v-model="message"></textarea>
            <p>输入的内容是:{{message}}</p>
        </div>
        <script>
            let app = new Vue({
                el: '#app',
                data: {
                    message:''
                }
            })
        </script>
    

    在这里插入图片描述

    • 绑定 radio
        <div id="app">
            <label for="male">
                <!-- 这里的v-model绑定的是value, 这里的value是动态绑定,所以其实这个v-model绑定的是abc,所以其实是abc的值给到了gender。 -->
                <input type="radio" v-model="gender" :value="abc" id="male" />男
            </label>
            <label for="female">
                <input type="radio" value="female" v-model="gender" id="female" />女
            </label>
            <p>您的选择:{{gender}}</p>
        </div>
        <script>
            let app = new Vue({
                el: '#app',
                data: {
                    gender: '',
                    abc: 'male'
                }
            })
        </script>
    

    v-model:checkbox

    复选框分为两种情况:单个勾选框和多个勾选框

    单个勾选框:

    • v-model即为布尔值。
    • 此时input的value并不影响v-model的值。
        <div id="app">
            <label for="check">
                <input type="checkbox" v-model="checked" id="check">同意协议
            </label>
        </div>
        <script>
            let app = new Vue({
                el: '#app',
                data: {
                    checked: false
                }
            })
        </script>
    

    多个复选框:

    • 当是多个复选框时,因为可以选中多个,所以对应的data中属性是一个数组。

    • 当选中某一个时,就会将input的value添加到数组中。

        <div id="app">
            <label ><input type="checkbox" v-model="hobbies" value="篮球">篮球</label>
            <label ><input type="checkbox" v-model="hobbies" value="足球">足球</label>
            <label ><input type="checkbox" v-model="hobbies" value="台球">台球</label>
            <p>您选中的爱好:{{hobbies}}</p>
        </div>
        <script>
            let app = new Vue({
                el: '#app',
                data: {
                    checked: false,
                    //这里必须是一个数组
                    hobbies: []
                }
            })
        </script>
    

    在这里插入图片描述

    v-model:select

    和checkbox一样,select也分单选和多选两种情况。

    单选:只能选中一个值。

    v-model绑定的是一个值。

    当我们选中option中的一个时,会将它对应的value赋值到mySelect中

        <div id="app">
            <select v-model="select">
                <option disabled value="">请选择</option>
                <option>A</option>
                <option>B</option>
                <option>C</option>
            </select>
            <p>当前选择的是:{{select}}</p>
        </div>
        <script>
            let app = new Vue({
                el: '#app',
                data: {
                    select: ''
                }
            })
        </script>
    

    多选:可以选中多个值。

    v-model绑定的是一个数组。

    当选中多个值时,就会将选中的option对应的value添加到数组mySelects中

        <div id="app">
            <!-- multiple是用来多选的,ctrl+鼠标进行多选 -->
            <select v-model="select" multiple >
                <option disabled value="">请选择</option>
                <option>A</option>
                <option>B</option>
                <option>C</option>
            </select>
            <p>当前选择的是:{{select}}</p>
        </div>
        <script>
            let app = new Vue({
                el: '#app',
                data: {
                    select: []
                }
            })
        </script>
    

    在这里插入图片描述

    值绑定

    值绑定就是动态的给value赋值而已

    • 我们前面的value中的值,可以回头去看一下,都是在定义input的时候直接给定的。

    • 但是真实开发中,这些input的值可能是从网络获取或定义在data中的。

    • 所以我们可以通过v-bind:value动态的给value绑定值。

    • 这不就是v-bind在input中的应用吗?

        <div id="app">
            <!-- 这里的v-bind是为了和下面的id进行绑定,这样点击文字就能选中了 -->
            <!-- 这里对likes进行了循环 -->
            <label v-bind:for="item" v-for="item in likes" >
                <!-- 这里的v-bind绑定的value是为了让v-model获取到值,绑定的是每一个item,这样我们的v-model就能用数组的方式获取到点击的值了 -->
                <input type="checkbox" v-bind:id="item" v-bind:value="item" v-model="myLikes">{{item}}
            </label>
            <p>当前选择了:{{myLikes}}</p>
        </div>
        <script>
            let app = new Vue({
                el: '#app',
                data: {
                    myLikes:[],
                    likes: ['足球', '篮球', '乒乓球', '台球', '羽毛球']
                }
            })
        </script>
    

    v-model的修饰符

    lazy修饰符:

    • 默认情况下,v-model默认是在input事件中同步输入框的数据的。

    • 也就是说,一旦有数据发生改变对应的data中的数据就会自动发生改变。

    • lazy修饰符可以让数据在失去焦点或者回车时才会更新:

        <div id="app">
            <input type="text" v-model.lazy="message">
            <p>输入的内容是:{{message}}</p>
        </div>
        <script>
            let app = new Vue({
                el: '#app',
                data: {
                    message: ''
                }
            })
        </script>
    

    在这里插入图片描述

    number修饰符:

    • 默认情况下,在输入框中无论我们输入的是字母还是数字,都会被当做字符串类型进行处理。
    • 但是如果我们希望处理的是数字类型,那么最好直接将内容当做数字处理。
    • number修饰符可以让在输入框中输入的内容自动转成数字类型

    对比一下

    没有加修饰符

        <div id="app">
            <input type="number" v-model="message">
            <p>输入的内容是:{{typeof message}}</p>
        </div>
        <script>
            let app = new Vue({
                el: '#app',
                data: {
                    message: ''
                }
            })
        </script>
    

    在这里插入图片描述

    使用修饰符

        <div id="app">
            <input type="number" v-model.number="message">
            <p>输入的内容是:{{typeof message}}</p>
        </div>
        <script>
            let app = new Vue({
                el: '#app',
                data: {
                    message: ''
                }
            })
        </script>
    

    在这里插入图片描述

    trim修饰符:

    • 如果输入的内容首尾有很多空格,通常我们希望将其去除
    • trim修饰符可以过滤内容左右两边的空格

    对比一下

        <div id="app">
            <input type="text" v-model="message">
            <p>输入的内容是:{{message}}哟哟哟</p>
        </div>
        <script>
            let app = new Vue({
                el: '#app',
                data: {
                    message: ''
                }
            })
        </script>
    

    在这里插入图片描述

    加上修饰符

        <div id="app">
            <input type="text" v-model.trim="message">
            <p>输入的内容是:{{message}}哟哟哟</p>
        </div>
        <script>
            let app = new Vue({
                el: '#app',
                data: {
                    message: ''
                }
            })
        </script>
    

    在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值