达达前端 · 2019年11月01日

Vue绑定事件,双向数据绑定,只是循环没那么简单

v-on
对象处理

<p @mouseover = "doTish" @mouseout = "doThat"> 对象形式 </p>

<p v-on="{ mouseover: doTish, mouseout: doThat }"> 对象形式 </p>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <!--导入Vue cdn 的网址-->
    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.22/dist/vue.js"></script>
</head>
<body>
<div id="app" >
    <p v-on="{ mouseover: doTish, mouseout: doThat }">对象形式</p>
</div>
<script>
    var vm = new Vue({
        el:"#app",
        methods:{
            doTish(){
                event.target.style.color = "red";
            },

            doThat(){
                event.target.style.color = "#0f0";
            },
        },
    })
</script>
</body>
</html>

v-on:keyup
监听按键触发
常见的按键别名:

    '.enter'
    '.tab'
    '.delete'(捕获“删除”和“退格”键)
    '.esc'
    '.space'
    '.up'
    '.down'
    '.left'
    '.right'

按键序号网址查询:'http://www.cnblogs.com/wuhua1...'

Vue.config.keyCodes.f1 = 112
<!-- Ctrl + Click -->
<div @click.ctrl="doSomething">Do something</div>
<!-- 有且只有 Ctrl 被按下的时候才触发 -->

<button @click.ctrl.exact="onCtrlClick">A</button>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <!--导入Vue cdn 的网址-->
    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.22/dist/vue.js"></script>
</head>
<body>
<div id="app" >
    <!--鼠标点击+ctrl 才能触发-->
    <p @click.ctrl.exact ="doTish">对象形式</p>
</div>
<script>
    var vm = new Vue({
        el:"#app",
        methods:{
            doTish(){
                event.target.style.color = "red";
            },

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

事件修饰符

    '.stop'      -- 阻止事件冒泡
    '.prevent'   -- 阻止默认事件
    '.capture'   -- 添加事件侦听器时使用事件捕获模式
    '.self'      --只当事件在该元素本身(比如不是子元素)触发时触发回调
    '.once'      --事件只触发一次
    'native'     -- 给组件绑定点击事件

阻止事件冒泡

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <!--导入Vue cdn 的网址-->
    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.22/dist/vue.js"></script>
    <style>
        .inner{
            width: 200px;
            height: 200px;
            background-color: darkseagreen;
        }
    </style>
</head>
<body>
<div class="inner" id="app" @click="divClick">
    <input type="button" value="点击" @click.stop="inputClick">
</div>
<script>
    var vm = new Vue({
        el:'#app',
        // data 负责输出理数据的
        data:{
        },
        // methods 负责处理调用方法的
        methods:{
            divClick(){
                console.log("最外层div")
            },
            inputClick(){
                console.log("最内层div")
            }
        }
    })
</script>
</body>
</html>

实现捕获触发事件的机制 -- capture

冒泡是从向外依次触发,使用capture,就变成了从先显示外面,在显示里面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <!--导入Vue cdn 的网址-->
    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.22/dist/vue.js"></script>
    <style>
        .inner{
            width: 200px;
            height: 200px;
            background-color: darkseagreen;
        }
    </style>
</head>
<body>
<div class="inner" id="app" @click.capture="divClick">
    <input type="button" value="点击" @click="inputClick">
</div>
<script>
    var vm = new Vue({
        el:'#app',
        // data 负责输出理数据的
        data:{},
        // methods 负责处理调用方法的
        methods:{
            divClick(){
                console.log("最外层div")
            },
            inputClick(){
                console.log("最内层div")
            }
        }
    })
</script>
</body>
</html>

打印结果
最外层div
最内层div

只会阻止自己身上冒泡行为 -- self
只会阻止自己身上冒泡行为 ,当有多层嵌套的时候,只会阻止有self 冒泡行为

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <!--导入Vue cdn 的网址-->
    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.22/dist/vue.js"></script>
    <style>
        .inner{
            width: 200px;
            height: 200px;
            background-color: darkseagreen;
        }
    </style>
</head>
<body>
<div id="app">
    <div class="outer" @click="div2Handler">
        <div class="inner" @click.self="div1Handler">
            <input type="button" value="戳他" @click="btnHandler">
        </div>
    </div>
</div>
<script>
    // 创建 Vue 实例,得到 ViewModel
    var vm = new Vue({
        el: '#app',
        data: {},
        methods: {
            div1Handler() {
                console.log('这是触发了 inner div 的点击事件')
            },
            btnHandler() {
                console.log('这是触发了 btn 按钮 的点击事件')
            },
            div2Handler() {
                console.log('这是触发了 outer div 的点击事件')
            }
        }
    });
</script>
</body>
</html>

这是触发了 btn 按钮 的点击事件
这是触发了 outer div 的点击事件

阻止默认事件 -- prevent
1.例如a标签默认事件就是点击跳转页面,为了阻止a标签的默认事件触发我
们绑定的事件,可以使用prevent
2.图片的默认事件禁止拖拽,如果想给图片设置拖拽效果的话记得做阻止默
认行为

<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <!--导入Vue cdn 的网址-->
    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.22/dist/vue.js"></script>
</head>
<body>
<div id="app">
    <a href="www.baidu.com" @click.prevent.once="linkClick">百度</a>
</div>
<script>
    var vm = new Vue({
        el:'#app',
        // data 负责输出理数据的
        data:{},
        // methods 负责处理调用方法的
        methods:{
            linkClick:function () {
                alert(1)
            }
        }

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

只触发一次默认行为
1.只触一次规定的默认行为
2.下面的案例第二次点击就会跳转页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <!--导入Vue cdn 的网址-->
    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.22/dist/vue.js"></script>
</head>
<body>
<div id="app">
    <a href="www.baidu.com" @click.prevent.once="linkClick">百度</a>
</div>
<script>
    var vm = new Vue({
        el:'#app',
        // data 负责输出理数据的
        data:{},
        // methods 负责处理调用方法的
        methods:{
            linkClick:function () {
                alert(1)
            }
        }
    })
</script>
</body>
</html>

阻止事件冒泡 -- stop

事件冒泡从里向外
阻止事件冒泡使用stop

v-on -- 方法处理器和内联处理器
两者区别写法上,带不带括号

没有括号不支持传参但只带event
由于带括号支持传参,但必须$evnet 当参数传入才有evet事件

方法处理器
内联处理器

v-model 双向数据绑定

修饰符<input type="text" v-model.lazy="name" />
        .lazy :失去焦点同步一次
        .number :格式化数字
        .trim : 去除首尾空格

checked -- 多选框(用数组接收)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <!--导入Vue cdn 的网址-->
    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.22/dist/vue.js"></script>
</head>
<body>
<div id="app">
    爱好
    <br>
    足球<input name="text" v-model="msg" type="checkbox" value="foot">
    篮球<input name="text" v-model="msg" type="checkbox" value="bask">
    {{msg}}
</div>
<script>
    // 创建 Vue 实例,得到 ViewModel
    var vm = new Vue({
        el: '#app',
        data: {
            msg:[]
        },
    });
</script>
</body>
</html>

select --下拉

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <!--导入Vue cdn 的网址-->
    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.22/dist/vue.js"></script>
</head>
<body>
<div id="app">
    <select v-model="selected">
        <option v-for="option in options" v-bind:value="option.value">
            {{ option.text }}
        </option>
    </select>
    <span>Selected: {{ selected }}</span>
</div>
<script>
    // 创建 Vue 实例,得到 ViewModel
    var vm = new Vue({
        el: '#app',
        data: {
            selected: 'A',
            options: [
                { text: 'One', value: 'A' },
                { text: 'Two', value: 'B' },
                { text: 'Three', value: 'C' }
            ]
        },
    });
</script>
</body>
</html>
<input v-model.lazy ="msg" >

<input type="text" v-on:input="inputHandle" />

v-for -- 循环

支持循环数组|对象|数字|字符串,Array | Object | number | string

数组使用

<p v-for="item,index in items">{{item}}--{{index}}</p>

循环对象

<p v-for="(value,key,index) in items">{{value}}-{{key}}-{{index}}</p>

<p v-for="item in 3">{{item}}</p>

对象重新渲染

file

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <!--导入Vue cdn 的网址-->
    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.22/dist/vue.js"></script>
</head>
<body>
<div id="app">
    <input v-model="msg.title" type="submit" @click="changeMsg">
</div>
<script>
    // 创建 Vue 实例,得到 ViewModel
    var vm = new Vue({
        el: '#app',
        data: {
            msg:{},
        },
        methods:{
            changeMsg(){
                this.msg.title = "改变"
            }
        }
    });
</script>
</body>
</html>

怎么保证不在计划内的值也被重新渲染
1.调用Vue的静态方法:set
2.调用实例上的方法 :$set
3.给计划内的对象重新赋值:vm.object = {key:'新的'}
4.添加指定属性重新构建赋值:Object.assign()

第一种解决方法 -- set/$set

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <!--导入Vue cdn 的网址-->
    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.22/dist/vue.js"></script>
</head>
<body>
<div id="app">
    <input v-model="msg.title" type="submit" @click="changeMsg">
</div>
<script>
    // 创建 Vue 实例,得到 ViewModel
    var vm = new Vue({
        el: '#app',
        data: {
            msg:{},
        },
        methods:{
            changeMsg(){
                Vue.set(this.msg, 'title', '新的' )
            }
        }
    });
</script>
</body>
</html>
$set ($set 是实例方法因此也是this在内部直接调用)
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <!--导入Vue cdn 的网址-->
    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.22/dist/vue.js"></script>
</head>
<body>
<div id="app">
    <input v-model="msg.title" type="submit" @click="changeMsg">
</div>
<script>
    // 创建 Vue 实例,得到 ViewModel
    var vm = new Vue({
        el: '#app',
        data: {
            msg:{},
        },
        methods:{
            changeMsg(){
                this.$set(this.msg, 'title', '新的' )
            }
        }
    });
</script>
</body>
</html>
给计划内的对象重新赋值
vm.object = {key:'新的'}

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <!--导入Vue cdn 的网址-->
    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.22/dist/vue.js"></script>
</head>
<body>
<div id="app">
    <input v-model="msg.title" type="submit" @click="changeMsg">
</div>
<script>
    // 创建 Vue 实例,得到 ViewModel
    var vm = new Vue({
        el: '#app',
        data: {
            msg:{},
        },
        methods:{
            changeMsg(){
                this.msg = {title:"新的"}
            }
        }
    });
</script>
</body>
</html>
Object.assign({},this.object,{key,value})

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <!--导入Vue cdn 的网址-->
    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.22/dist/vue.js"></script>
</head>
<body>
<div id="app">
    <input v-model="msg.title" type="submit" @click="changeMsg">
</div>
<script>
    // 创建 Vue 实例,得到 ViewModel
    var vm = new Vue({
        el: '#app',
        data: {
            msg:{},
        },
        methods:{
            changeMsg(){
                this.msg = Object.assign({},  {
                    title: '新的',
                })
            }
        }
    });
</script>
</body>
</html>
数组重新渲染
    'push()'
    'pop()'
    'shift()'
    'unshift()'
    'splice()'
    'sort()'
    'reverse()'
        
filter(), concat() 和 slice() ,map()

依旧支持set/$set

splice是个好方法会常用

解决vm.items[indexOfItem] = newValue不能被渲染的问题

使用方法set 是Vue静态方法,通过Vue调用
使用Vue.set( array, indexOfItem, newValue)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <!--导入Vue cdn 的网址-->
    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.22/dist/vue.js"></script>
</head>
<body>
<div id="app">
    <p v-for="i in msg">{{i}}</p>
    <input v-model="pushArray">
    <button @click="changeMsg">提交</button>
</div>
<script>
    // 创建 Vue 实例,得到 ViewModel
    var vm = new Vue({
        el: '#app',
        data: {
            pushArray:'',
            msg:['我是', '测试', '数据'],
        },
        methods:{
            changeMsg(){
                Vue.set(this.msg, 0, this.pushArray);
            }
        }
    });
</script>
</body>
</html>
splice 是一个好方法

v-for 为什么要配合v-bind:key

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.22/dist/vue.js"></script>
</head>
<body>
  <div id="app">

    <div>
      <label>Id:
        <input type="text" v-model="id">
      </label>

      <label>Name:
        <input type="text" v-model="name">
      </label>

      <input type="button" value="添加" @click="add">
    </div>

    <!-- 注意: v-for 循环的时候,key 属性只能使用 number或者string -->
    <!-- 注意: key 在使用的时候,必须使用 v-bind 属性绑定的形式,指定 key 的值 -->
    <!-- 在组件中,使用v-for循环的时候,或者在一些特殊情况中,如果 v-for 有问题,必须 在使用 v-for 的同时,指定 唯一的 字符串/数字 类型 :key 值 -->
    <p v-for="item in list" :key="item.id">
      <input type="checkbox">{{item.id}} --- {{item.name}}
    </p>
  </div>

  <script>
    // 创建 Vue 实例,得到 ViewModel
    var vm = new Vue({
      el: '#app',
      data: {
        id: '',
        name: '',
        list: [
          { id: 1, name: '李斯' },
          { id: 2, name: '嬴政' },
          { id: 3, name: '赵高' },
          { id: 4, name: '韩非' },
          { id: 5, name: '荀子' }
        ]
      },
      methods: {
        add() { // 添加方法
          this.list.unshift({ id: this.id, name: this.name })
        }
      }
    });
  </script>
</body>

</html>

若本号内容有做得不到位的地方(比如:涉及版权或其他问题),请及时联系我们进行整改即可,会在第一时间进行处理。


请点赞!因为你们的赞同/鼓励是我写作的最大动力!

欢迎关注达达的简书!

这是一个有质量,有态度的博客

博客

推荐阅读
关注数
2
文章数
124
前端资源下载群:通告:前端开发交流群:711613774 文章 每天更新(点个赞,证明你还爱我哦,亲)友链大礼包:[链接]
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息