在前端开发中,我们需要经常和用于交互。
这个时候,我们就必须监听用户发生的时间,比如点击、拖拽、键盘事件等等
在Vue中如何监听事件呢?使用v-on指令
v-on介绍
作用:绑定事件监听器
缩写:@
预期:Function | Inline Statement | Object
参数:event
当通过methods中定义方法,以供@click调用时,需要注意参数问题:
情况一:如果该方法不需要额外参数,那么方法后的()可以不添加。
但是注意:如果方法本身中有一个参数,那么会默认将原生事件event参数传递进去
情况二:如果需要同时传入某个参数,同时需要event时,可以通过$event传入事件。
在某些情况下,我们拿到event的目的可能是进行一些事件处理。
Vue提供了修饰符来帮助我们方便的处理一些事件:
.stop - 调用 event.stopPropagation()作用:停止冒泡
.prevent - 调用 event.preventDefault()----作用:阻止默认行为
.native - 监听组件根元素的原生事件。
.once - 只触发一次回调。
.passive - 事件的默认行为立即执行,无须等待事件回调完毕
.串联修饰符
//先阻止默认事件在停止冒泡
常用的键盘事件:
keydown:按下按键无须抬起便触发事件
keyup:按下按键松手才触发事件
//按下enter键松手触发show事件
1、Vue常用的按键别名:
2、ye可以使用keyCode去指定具体的按键
//按下enter键松手触发show事件
3、 系统修饰键:ctrl、alt、shift、meta
(1)配合keyup使用时按下修饰键的同时,再按下其他键,随后释放其他键,事件才触发
(2)配合keydown 使用时正常触发
<div id="example">
<p>Original message: "{{ message }}"p>
<p>Computed reversed message: "{{ reversedMessage }}"p>
div>
var vm = new Vue({
el: '#example',
data: {
message: 'Hello'
},
computed: {
// 计算属性的 getter
reversedMessage: function () {
// `this` 指向 vm 实例
return this.message.split('').reverse().join('')
}
}
})
结果:
Original message: “Hello”
Computed reversed message: “olleH”
5.计算属性(computed)与方法(method)的区别:
当被监视的属性变化时,回调函数自动调用
监视的属性必须存在才能进行监视
监视属性的两种写法:new Vue时传入watch配置以及通过vm.$watch监视
配置项–immediate:true–初始化市让函数调用一下;deep:true–开启深度监视
<div id="demo">{{ fullName }}div>
var vm = new Vue({
el: '#demo',
data: {
firstName: 'Foo',
lastName: 'Bar',
fullName: 'Foo Bar'
},
watch: {
firstName: function (val) {
this.fullName = val + ' ' + this.lastName
},
lastName: function (val) {
this.fullName = this.firstName + ' ' + val
}
}
})
这三个指令与JavaScript的条件语句if、else、else if类似;适用于切换频率较低的场景;Vue的条件指令可以根据表达式的值在DOM中渲染或销毁元素或组件,当使用v-if时不展示的DOM元素直接被移除。
简单的案例演示:
<div>
<p v-if="score>=90">优秀p>
<p v-else ="score>=80">良好p>
<p v-else-if="score>=60">及格p>
<p v-else-if="score>=90">不及格p>
div>
const vm=new Vue({
el:'#app,
data:{
score:88
}
})
写法:v-show=“表达式”,适用于切换频率较高的场景
特点:当使用v-show时不展示的DOM元素未被移除,仅仅是使用样式隐藏,且使用v-if时元素可能无法获取到,而使用v-show一定可以获取到。
当我们有一组数据需要进行渲染时,我们就可以使用v-for来完成。v-for的语法类似于JavaScript中的for循环。v-for可遍历数组、对象、字符串、指定次数。
语法:语法格式:v-for=(item, index) in items
其中的index就代表了取出的item在原数组的索引值,从0开始。
<div id="app">
<ul>
<li v-for="(p,index) in persons" :key="index">
{{p.name}}--{{p.age}}
li>
ul>
div>
new Vue({
el:'#app',
data:{
persons:[
{name:"张三",age:20},
{name:"李四",age:29},
{name:"王五",age:33}
]
}
})
结果:
虚拟DOM中key的作用:
key是虚拟DOM对象的标识,当数据发生变化时,Vue会根据新的数据生成新的虚拟DOM,随后Vue进行新虚拟DOM与旧的虚拟DOM的差异比较;
对比规则:
旧虚拟DOM中找到了与新虚拟DOM相同的key:
若虚拟DOM中的内容没有变化,直接使用之前的真实DOM;
若虚拟DOM中的内容发生变化,则生成新的真实DOM,随后替换掉页面之前的真实DOM。
旧虚拟DOM中未找到与新虚拟DOM相同的key:
创建新的真实DOM,随后渲染到页面
用index作为key可能会引发的问题:
若对数据进行:逆序添加、删除等破坏顺序的操作:
会产生没有必要的真实DOM更新,界面显示没有问题,但效率低
如果结构中还包括输入类的DOM:
会产生错误DOM更新,界面显示会有问题
在自定义组件上,你可以像在任何普通元素上一样使用 v-for
。
2.2.0+ 的版本里,当在组件上使用 v-for 时,key 现在是必须的。
然而,任何数据都不会被自动传递到组件里,因为组件有自己独立的作用域。为了把迭代数据传递到组件里,我们要使用 prop:
不推荐在同一元素上使用 v-if 和 v-for。
当它们处于同一节点,v-for 的优先级比 v-if 更高,这意味着 v-if 将分别重复运行于每个 v-for 循环中。当你只想为部分项渲染节点时,这种优先级的机制会十分有用。
vue会监视data中所有层次的数据。
如何监测对象中的数据?
通过setter实现监视,且要在newVue时就传入要监测的数据。
对象中后追加的属性,Vue默认不做响应式处理
如需给后添加的属性做响应式,请使用如下API:
Vue . set(target, propertyName/index, value) 或
Vm .$set (target, propertyName/ index, value )
如何监测数组中的数据?
通过包裹数组更新元素的方法实现,本质就是做了两件事:
.在Vue修改数组中的某个元素定要用如 下方法:
特别注意: Vue.set() 和vm.$set() 不能给vm 或vm的根数据对象添加属性即不能运用在vm和vm._data上! !
例子:
学生信息
姓名:{{student.name}}
年龄:{{student.age}}
性别:{{student.sex}}
爱好:
- {{h}}
朋友:
-
{{p.name}}--{{p.age}}
const vm=new Vue({
el:'#app',
data:{
student:{
name:'张三',
age:19,
hobby:['学习','看书','打篮球'],
friends:[
{name:'李四',age:20},
{name:'王五',age:29}
]
}
},
methods: {
addSex(){
// Vue.set(this.student,'sex','男')
vm.$set(this.student,'sex','女')
},
addFriend(){
this.student.friends.unshift({name:'赵六',age:22})
},
changeName(){
this.student.friends[0].name='张三'
},
addHobby(){
this.student.hobby.push('打游戏')
},
changeHoppy(){
// this.student.hobby.splice(0,1,'游泳')
Vue.set(this.student.hobby,0,'游泳')
}
},
})
1、你可以用 v-model 指令在表单 、 及 元素上创建双向数据绑定。它会根据控件类型自动选取正确的方法来更新元素。尽管有些神奇,但 v-model 本质上不过是语法糖。它负责监听用户的输入事件以更新数据,并对一些极端场景进行一些特殊处理。
注意:
v-model 会忽略所有表单元素的 value、checked、selected attribute 的初始值而总是将 Vue 实例的数据作为数据来源。你应该通过 JavaScript 在组件的 data 选项中声明初始值。
2、v-model 在内部为不同的输入元素使用不同的 property 并抛出不同的事件:
注意:
text 和 textarea 元素使用 value property 和 input 事件;
checkbox 和 radio 使用 checked property 和 change 事件;
select 字段将 value 作为 prop 并将 change 作为事件。
对于需要使用输入法 (如中文、日文、韩文等) 的语言,你会发现 v-model 不会在输入法组合文字过程中得到更新。如果你也想处理这个过程,请使用 input 事件。
Message is: {{ message }}
Multiline message is:
{{ message }}
注意:
在文本区域插值 ({{text}}) 并不会生效,应用 v-model 来代替。
单个复选框,绑定到布尔值:
多个复选框,绑定到同一个数组:
Checked names: {{ checkedNames }}
new Vue({
el: '#app',
data: {
checkedNames: []
}
})
Picked: {{ picked }}
new Vue({
el: '#example-4',
data: {
picked: ''
}
})
Selected: {{ selected }}
new Vue({
el: '...',
data: {
selected: ''
}
})
Selected: {{ selected }}
new Vue({
el: '#example-6',
data: {
selected: []
}
})
lazy修饰符:
默认情况下,v-model默认是在input事件中同步输入框的数据的。也就是说,一旦有数据发生改变对应的data中的数据就会自动发生改变。lazy修饰符可以让数据在失去焦点或者回车时才会更新。
number修饰符:
默认情况下,在输入框中无论我们输入的是字母还是数字,都会被当做字符串类型进行处理。但是如果我们希望处理的是数字类型,那么最好直接将内容当做数字处理。number修饰符可以让在输入框中输入的内容自动转成数字类型。
trim修饰符:
如果输入的内容首尾有很多空格,通常我们希望将其去除trim修饰符可以过滤内容左右两边的空格。
v-text作用和Mustache比较相似:都是用于将数据显示在界面中;v-text通常情况下,接受一个string类型;
但它不够灵活。建议使用mastache语法–{{}}。
某些情况下,我们从服务器请求到的数据本身就是一个HTML代码如果我们直接通过{{}}来输出,会将HTML代码也一起输出。但是我们可能希望的是按照HTML格式进行解析,并且显示对应的内容。
如果我们希望解析出HTML展示可以使用v-html指令该指令后面往往会跟上一个string类型会将string的html解析出来并且进行渲染
1.作用:向指定节点中渲染包含html结构的内容。
2.与插值语法的区别:
(1).v-html会替换掉节点中所有的内容,{{xx}}则不会。
(2) .v-html可以识别htm1结构。
3.严重注意: v-html有安全性问题! ! ! !
(1).在网站上动态渲染任意HTML是非常危险的,容易导致XSS攻击。
(2).定要在可信的内容上使用v-html.永远不要用在用户提交的内容上!
1.本质是一个特殊属性,Vue实例创建完毕并接管容器后,会删掉v-cloak属性。
2.使用css配合v- cloak可以解决网速慢时页面展示出{{xxx}}的问题。
将代码原封不动的解析出来,不做任何处理;
v-pre用于跳过这个元素和它子元素的编译过程,用于显示原本的Mustache语法
1、在某些情况下,我们可能不希望界面随意的跟随改变,这个时候,我们就可以使用一个Vue的指令:v-once:
2、该指令后面不需要跟任何表达式(比如之前的v-for后面是由跟表达式的)
3、该指令表示元素和组件(组件后面才会学习)只渲染一次,不会随着数据的改变而改变。
初始化的n值为:{{n}}
当前n值为:{{n}}
new Vue({
el:'#app',
data:{
n:1
}
})
未使用v-once
(1).局部指令:
directives:{指令名:配置对象} 或
})
directives{指令名:回调函数}
})
(2).全局指令:
Vue .directive(指令名,配置对象)或Vue .directive(指令名,回调函数)
(1).bind:指令与元素成功绑定时调用。
(2).inserted:指令所在元素被插入页面时调用。
(3).update:指令所在模板结构被重新解析时调用。
指令定义时不加v-,但使用时要加v-; 指令名如果是多个单词,要使用kebab-case命名方式,不要用camelCase命名。
定义一个v-big指令,和v-text功能类似,但会把绑定的数值放大10倍
初始化的n值为:{{n}}
当前n值为:{{n}}
放大10倍后的n值为:
new Vue({
el:'#app',
data:{
n:1
},
directives:{
big(element,binding){
element.innerText=binding.value*10
}
}
})
1、创建前/后: 在 beforeCreate 阶段,vue 实例的挂载元素 el 还没有。
2、载入前/后:在 beforeMount 阶段,vue 实例的$el 和 data 都初始化了,但还是挂载之前为虚拟的 dom 节点,data.message 还未替换。在 mounted 阶段,vue 实例挂载完成,data.message 成功渲染。
3、更新前/后:当 data 变化时,会触发 beforeUpdate 和 updated 方法。
4、销毁前/后:在执行 destroy 方法后,对 data 的改变不会再触发周期函数,说明此时 vue 实例已经解除了事件监听以及和 dom 的绑定,但是 dom 结构依然存在
1.销毁后借助Vue开发者工具看不到任何信息。
2.销毁后自定义事件会失效,但原生DOM事件依然有效。
3.般不会在beforeDestroy操作 数据,因为即便操作数据,也不会再触发更新流程了。
定义组件
使用Vue . extend(options )创建,其中options 和new Vue(options)时传 入的那个options儿乎-样, 但也有点区别;区别如下:
1.el不要写——最终所有 的组件都要经过- 个vm的管理,由vm中的el决定服务哪个容器.
2.data必须写成函数。——避免维件被复用时,数据存在引用关系。
<template >
<div>
<h2>学生基本信息h2>
<h2>姓名:{{name}}h2>
<h2>学号:{{number}}h2>
div>
template >
const student=vue.extend({
data(){
return{
name:"张三"
number:123
}
}
})
注册组件
局部注册:考靠new Vue的时候传入components选项
new Vue({
el:'#app',
components:{
student
}
})
全局注册:靠Vue.component(‘组件名’,组件)
使用组价,编写组件标签——
注意:
1.关于组件名:
一个单词组成:
第一 种写法(首字母小写): school
第二种写法(首字母大写): School
多个单词组成:
第一种写法(kebab-case命 名): my- school
第二种写法(CamelCase命名): MySchool (需要Vue脚 手架支持)
备注:
(1).维件名尽可能回避HTML中已有的元素名称,例如:h27 H2都不行。
(2).可以使用name配置项指定组件在开发者工具中呈现的名字。
2.关于组件标签:
第一种写法:
第二种写法:
备注:不用使用脚手架时,会 导致后续组件不能演染。
3.一个简写方 式:
const school = Vue 。extend(options)可简写为: const school = options
关于VueComponent:
school组件本质是个 名为VueComponent的构造函数。 且不是程序员定义的,是Vue。extend生成的。
我们只需婴写或. Vue解析时公帮我们创建school组件的实例对象,即Vue格我们执行的: new VueComponent(options).
特别注意:每次调用Vue. extend.返回的都是一个 全新的VueComponent! ! ! !
关于this指向:
(1).组件配置中:
datar数、methods中的函数、watch中的函数、computed中的函 数它们的this均是[VueComponent实例对象]
(2).new Vue()配置中:
data丙数、methods中的两数、watch中的两数、computed中的函数它们的this均是[Vue实例对象]。