• Vue框架-02-数据和事件


    Vue里的MVVM

    MVVM模型:

    1.M:模型(Model):对应data的数据
    2.V: 视图(View):模板
    3.VM: 视图模型(ViewModel): Vue实例对象

    在这里插入图片描述
    代码演示

    <body>
    
        
        <div id="app">
            <h1>name:{{name}}h1>
            <h1>age:{{age}}h1>
        div>
        
        
        <script type="text/javascript">
    
            Vue.config.productiontip=false
    
            // ViewModel :视图模型
            const vm = new Vue({
                el:'#app',
                // Model 数据
                data:{
                    name:'张三',
                    age: 12
                }
            })
        script>
    body>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    总结:

    MVVM模型:

    1. M:模型(model):对应data的数据
    2. V: 视图(View):模板数据
    3. VM: 视图模型(ViewModel): Vue实例

    观察发现:
    4. data所有的属性,最后都在vm身上
    5. vm身上所有的属性及Vue原型的所有属性,在Vue模板上都可以直接使用。

    数据代理

    Object_defineProperty

    Object_defineProperty:用于给对象添加属性,添加的属性可有控制属性是否可修改,是否可删除,是否支持枚举。

    枚举是不支持遍历的。

    Object_defineProperty构造方法有4个基本属性,分别是对象,添加属性,添加的配置

    基本的配置有:

    1. 是否能修改属性
    2. 是否能枚举属性
    3. 是否能删除属性
        Object.defineProperty(person,'age',{
                //基本配置项
                value:'18', //赋初值
                enumrable:true, //控制属性是否可以枚举,默认为false
                wirtable:true, //控制属性是否可修改 ,默认为false
                configurable: true //控制属性是否可以删除,默认为false
            })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    默认通过Object_defineProperty的方式的属性是不可枚举,不可修改和不可删除的。
    在这里插入图片描述

    配置的高级项

    let number =18 
    
    Object.defineProperty(person,'age',{
                get(){     
                    console.log('有人读取了age属性')
                    return number
                    
                },
    
                //当有人修改person的age时,set方法就会被调用,保存修改后的数据
                set(value){
                    console.log('有人修改了age属性,且值是'+value)
                    number = value
                }
    
            })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    在这里插入图片描述

    理解数据代理

    数据代理:通过一个对象代理对另一个对象属性的操作(读/写)

    代码演示

        <script type="text/javascript">
            let obj1 = {x:100}
            let obj2 = {y:200}
    
            Object.defineProperty(obj2,'x',{
                get(){
                    return obj1.x
                },
                set(value){
                    obj1.x= value
                }
    
            })
        </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    Vue中的数据代理

    通过观察一下代码:

        <div id="app">
            <h2>学校名称:{{name}}</h2>
            <h2>学校地址:{{address}}</h2>
        </div>
        
        <script type="text/javascript">
           
           Vue.config.productiontip = false
    
           const vm = new Vue({
            el:'#app',
            // data中的数据读取和写入实质上是数据代理
            data:{
                name:'涉外经济学院',
                address: '湖南的'
            }
           })
        </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    为什么插值语法中输入的表达式可以直接读取到data区域的所有属性?

    实际上是数据代理实现的,打开控制台观察:

    在这里插入图片描述
    data对象的属性可以在Vue实例中找到,是通过数据代理Object.defineProperty实现的,通过我们的Vue实例对象去代理了data对象属性的操作。
    在这里插入图片描述

    验证:

    在这里插入图片描述
    读取验证:
    验证是否是从data对象取的属性值,修改name的值重新启动即可。

    修改验证:

    验证是否是从data对象修改属性值。
    在这里插入图片描述
    可以得知通过修改vm.data,data对象的name也发生了变化,验证了Vue实例数据代理。

    vm._data和Vue实例的data是相同的,且vue实例以及Vue原型的所有属性和方法可以在模板上直接使用。

    Vue实例数据代理实质是将data对象的属性复制了一份,为了方便操作。
    在这里插入图片描述
    总结:

    1. Vue的数据代理:通过vm对象来代理data对象中属性的操作(读/写)。
    2. Vue实例的好处: 更加方便操作data中的属性数据
    3. 基本原理: 通过Object.defineProperty()把data对象所有属性添加到vm上。为每一个添加到vm上的属性,都指定一个getter/setter。在getter/setter内部去操作(读/写)data对应的属性。

    vm._data对象的内部:

    在这里插入图片描述
    其底层不是数据代理,而是数据结池,完成对页面数据的响应。

    事件

    事件代理

    我们点击事件使用到一个vue指令:v-on

    <div id="app">
    
            <h2>欢迎来到{{name}}</h2>
            <button v-on:click="showInfo">点击我</button>
        </div>
    
        <script type="text/javascript">
            Vue.config.productiontip=false
    
            new Vue({
                el:'#app',
                data:{
                    name:'Vue'
                },
                methods:{
                    showInfo(){
                        alert('hello,你好吖')
                    }
                }
            })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    其中v-on点击的事件要在我们的Vue实例里,放置在methods对象上。

    其中方法默认有一个event参数,可以得到event的事件信息。

                   showInfo(event){
                        console.log(event.target.innerText)
                        console.log(this)     //this指的是vue实例对象               
                        alert('hello,你好吖')
                    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    methods里面的方法的this正常情况下是Vue实例对象,但若加上箭头函数,那么找不到自己的this,就将全局的window作为this。

            methods:{
                    showInfo:(event)=>{
                        console.log(event.target.innerText)
                        console.log(this)
                        alert('hello,你好吖')
                    }
                }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    在这里插入图片描述

    v-on的简写方式直接写一个‘@‘即可,不传参事件方法可以不写括号

    实现点击事件传入一个参数,完成要求。

    
       <div id="app">
    
            <h2>欢迎来到{{name}}h2>
            
            <button @click="showInfo1">点击我(未传参)button>
            <button @click="showInfo2(1)">点击我(传参)button>
        div>
    
        <script type="text/javascript">
            Vue.config.productiontip=false
    
            // 点击事件的时候传入一个参数,这跟删除和更新操作有关。
            new Vue({
                el:'#app',
                data:{
                    name:'Vue'
                },
                methods:{
                    showInfo1:(event)=>{
                        alert('hello,你好吖')
                    },
                    showInfo2:(value)=>{
                        console.log(value)
                        alert('hello,你好吖'+value)
                    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    事件同时实现event和传参

        <button @click="showInfo3($event,1)">点击我(传参和event)</button>
    
                    showInfo3:(event,value)=>{
                        console.log(event,value)
                        alert('hello,你好吖'+value)
                    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    输出event的同时也同时实现了传参。
    在这里插入图片描述

    vm的methods底层不是数据代理,数据代理是代理会改变的数据操作。而方法是用来给调用的,不需要改变。是被Vue管理的函数。

    在这里插入图片描述
    总结:

    1.使用v-on:xxx或@xxx绑定时间,其中xxx是事件名。
    2.事件的回调需要配置在methods对象中,最终会在vm上。
    3.methods配置的函数,不要用箭头函数,否则this就不再是vm了。
    4.methods配置的函数,都是被Vue管理的函数,this的指向是vm或组件实例对象。
    5.@click=“demo” 或@click="demo($event)"效果一致,但后者可以传入参数。

    事件修饰符

    Vue的事件修饰符有六种

    1.prevent:阻止默认事件(常用)
    2.stop:阻止事件冒泡(常用)
    3,once: 控制事件只触发一次(常用)
    4.capture: 使用事件捕获模式
    5.self: 只有event,tartget是当前操作的元素才触发事件
    6.passive:事件的默认行为立即执行,无需等待时间回调执行完毕。

    先准备一个点击事件如下:

        <div id="app">
            <a :href="url" @click="showInfo">点击我跳转到QQ</a>
        </div>
    
        <script type="text/javascript">
            Vue.config.productiontip=false
    
            const vm =new Vue({
                el:'#app',
                data:{
                    url:'www.qq.com'
                },
                methods:{
                    showInfo(){
                        alert('跳转到QQ')
                    }
                }
            })
        </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    使用Vue的事件修饰符

    prevent

    再点击事件后面添加prevent即可阻止跳转页面。

    在这里插入图片描述

    stop

    在之前的代码再添加如下代码

    
        <style>
            *{
                margin-top: 20px;
            }
            .demo1{
                height: 50px;
                background-color: skyblue
            }
        </style>
        <div id="app">
            <a :href="url" @click.prevent="showInfo">点击我跳转到QQ</a>
            <div id="demo" @click="showInfo">
                <button @click="showInfo">点击提示信息</button>
            </div>
        </div>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    打开浏览器运行发现点击按钮弹出两次窗口,发生了事件冒泡。

    解决方法
    1.在事件方法中使用e.stopPropagation()

       methods:{
                    showInfo(e){
                        e.stopPropagation()
                        alert('跳转到QQ')
                    }
                }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    2.在vue指令@click后添加stop。

         <div id="demo" @click="showInfo">
                <button @click.stop="showInfo">点击提示信息</button>
            </div>
    
    • 1
    • 2
    • 3

    由内往外阻止冒泡。在里面使用stop。

    once

    事件只触发一次,之后的点击都不会触发,都不会响应事件了。

            <button @click.once="showInfo">点击提示信息(once)</button>
    
    
    • 1
    • 2

    capture

    编写一个小案例,两个div边框点击div2,发现输出结果从里往外,由此发生了冒泡。

            #box1{
                padding: 5px;
                background-color: salmon;
            }
            #box2{
                padding: 5px;
                background-color: lightcoral;
            }
    
            <div id="box1" @click="showMsg(1)">
                div1
                <div id="box2" @click="showMsg(2)">
                    (capture:捕获模式)div2
                </div>
            </div>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    在这里插入图片描述
    分析

    事件先进行捕获,然后再进行冒泡。捕获由外向里,而冒泡由里往外。阻止冒泡,实现捕获阶段处理事件。用capture就可以实现了。

        
            <div id="box1" @click.capture="showMsg(1)">
                div1
                <div id="box2" @click="showMsg(2)">
                    (capture:捕获模式)div2
                </div>
            </div>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    输出结果:
    在这里插入图片描述

    self

    小例子演示,self的效果和stop类似

            <div class="demo1" @click="showInfo">
                <button @click="showInfo">点我提示信息(self)</button>
            </div>
    
    • 1
    • 2
    • 3

    分析

    div的事件是冒泡冒上去的,通过在冒泡事件上加上self,冒泡问题得以解决。

    passive

    记录一个鼠标事件,滚轮和滚动条。分别使用@wheel和@scroll。滚动条是计算滚动的距离(大小有限制),滚轮是计算滚动的次数(大小无限制)。

        
            
            <ul  @scroll="show" class="list">
                <li>1li>
                <li>2li>
                <li>3li>
                <li>4li>
            ul>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    相应结果:

    滚动条结果
    在这里插入图片描述
    滚动轮结果
    在这里插入图片描述

    使用滚动条进行复杂的运算

    在事件中添加一个循环。如下:

      <ul  @wheel="show" class="list">
                <li>1</li>
                <li>2</li>
                <li>3</li>
                <li>4</li>
            </ul>
                      show(){
                        for(let i =0 ; i< 100000;i++){
                            console.log('@')
                        }
                        console.log('累坏了')
                    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    结果分析:滚动滚轮,事件一直在发生,而滚动条没有移动。
    在这里插入图片描述
    使用passive,滚轮事件问题解决。(但滚动条@scroll优先响应滚动)

    <ul  @wheel.passive="show" class="list">
    
    • 1

    键盘事件

    键盘有常用两个键盘事件,keydown和keyup。

    keyup: 键盘按下去抬起来的时候触发
    keydown: 键盘按下去触发事件。

    使用keyup或keydown后不使用判断条件,按下容易一个键就会触发事件。如下:

    部分代码:

    
    <div id="app">
            <h1>Hello,{{name}}h1>
            <input type="text" placeholder="请输入" @keyup="showInfo">
        div>
    
      new Vue({
                el:'#app',
                data:{
                    name: 'Vue'
                },
                methods:{
                    showInfo(event){
                        console.log(event.target.value)
                    }
                }
            })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    运行出来会立即触发事件。

    要求只有回车才进行回车事件

    1.通过js代码来进行判断

     methods:{
                    showInfo(event){
                        // 使用关键码来控制条件 回车 ===13
                         if(event.keyCode === 13){ console.log(event.target.value)}
    
                    }
                }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    2.通过vue提供的常用键盘判断按键

    <input type="text" placeholder="请输入" @keyup.enter="showInfo">
    
    • 1

    Vue按键知识

    1. 常用按键:

      enter: 换行
      删除: delete(按删除或者退格键)
      退出: esc
      切换光标/缩进: tab (配合keydown使用,使用keyup会切换到其他的图标,会将焦点切走)
      上: up
      下: down
      左: left
      右: right

    2.Vue没有提供别名的按键可以使用键盘原始的key去绑定,但要注意以kebab-case(短横线命名)

     <input type="text" placeholder="按下capsLock提示输入" @keyup.caps-lock="showInfo">
    
    • 1

    3.系统特殊修饰键(用法特殊)ctrl,alt,meta,shift
    (1).配合keyup使用: 按下修饰键的同时,还需要按下其他键,然后释放其他键,事件才被触发。例如:ctrl+l l
    (2).配合keydown使用: 可以正常触发事件。

            <input type="text" placeholder="按下tab提示输入" @keydown.tab="showInfo">
                    <input type="text" placeholder="按下meta提示输入" @keyup.meta="showInfo">
    
    • 1
    • 2

    4.使用keycode去指定具体的按键。(不推荐)

            <input type="text" placeholder="按下回车提示输入" @keyup.13="showInfo">
    
    • 1

    5.可以使用Vue.config.keyCodes.自定义键名 = 键码,定制按键别名

     <input type="text" placeholder="按下回车提示输入" @keyup.huiche="showInfo">
    
            // 自定义按键别名
            Vue.config.keyCodes.huiche = 13
    
    • 1
    • 2
    • 3
    • 4

    事件总结

    阻止冒泡的同时阻止默认行为,可以通过以下代码实现。

         <div id="demo1" @click="showMsg">
                <a href="www.qqmusic.com" @click.stop.prevent="showInfo">点击我提示信息(stop.prevent)a>
            div>
    
    
    • 1
    • 2
    • 3
    • 4

    要求按下ctrl+y的时候才响应键盘事件

     <input type="text" placeholder="按下ctrl+y提示输入" @keyup.ctrl.y="showInfo">
    
    • 1
  • 相关阅读:
    19 使用MapReduce编程统计超市1月商品被购买的次数
    JEECMS安装部署方法以及使用说明教程
    SpringWeb项目获取所有访问路由
    淘宝大数据揭秘:购物狂欢节背后的秘密
    微信小程序中 vant weapp 使用外部的icon作为图标的步骤
    安装特定指定版本 低版本的r包 r包降级
    mit6.824lab2D-Debug记录
    CentOS7.5 更新内核 内核升级
    微信小程序实现蓝牙开门前后端项目(一)
    DevOps-4:Jenkins配置.Net项目模板Job
  • 原文地址:https://blog.csdn.net/paiidds/article/details/127062865