获取文本框的值(略)
获取单选框中的值
通过v-model
获取复选框中的值
通过v-model
和获取单选框中的值一样
复选框 checkbox
这种的组合时 data 中的 hobby 我们要定义成数组 否则无法实现多选
爱好:
获取下拉框和文本框中的值
通过v-model
职业:
.number 转换为数值
注意点:
当开始输入非数字的字符串时,因为Vue无法将字符串转换成数值
所以属性值将实时更新成相同的字符串。即使后面输入数字,也将被视作字符串。
.trim 自动过滤用户输入的首尾空白字符
只能去掉首尾的 不能去除中间的空格
.lazy 将input事件切换成change事件
.lazy 修饰符延迟了同步更新属性值的时机。即将原本绑定在 input 事件的同步逻辑转变为绑定在 change 事件上
在失去焦点 或者 按下回车键时才更新
内置指令不能满足我们特殊的需求
Vue允许我们自定义指令
自定义指令创建语法
Vue.directive('focus',{
inserted:function(el){
//获取元素焦点
el.focus();
}
})
自定义指令用法:
局部指令,需要定义在 directives 的选项 用法和全局用法一样
局部指令只能在当前组件里面使用
当全局指令和局部指令同名时以局部指令为准
/*使用keyup事件监听数据的变化*/
Document
+
=
模板中放入太多的逻辑会让模板过重且难以维护 使用计算属性可以让模板更加的简洁
计算属性出现的目的是解决模板中放入过多的逻辑会让模板过重且难以维护的问题.
计算属性是根据data中已有的属性,计算得到一个新的属性.
computed比较适合对多个变量或者对象进行处理后返回一个结果值,也就是数多个变量中的某一个值发生了变化则我们监控的这个值也就会发生变化
/*
计算属性与方法的区别:计算属性是基于依赖进行缓存的,而方法不缓存
*/
Document
+
=
使用watch来响应数据的变化
watch 中的属性 一定是data 中 已经存在的数据
Document
+
=
当然,侦听器有自己的应用场景,它的应用场景就是在执行异步请求或者进行开销比较大的操作的时候,会使用侦听器。
下面我们来看一个异步操作的情况。就是当用户在一个文本框中输入了用户名以后,要将输入的用户名发送到服务端,来检查该用户名是否已经被占用。
Document
用户名:
{{tip}}
1.methods方法表示一个具体的操作,主要书写业务逻辑。
2.computed属性的结果会被缓存,除非依赖的响应式属性变化才会重新计算,主要当做属性来使用。
3.watch是一个对象,键是需要观察的表达式,值是对应的回调函数,主要用来监听某些特定数据的变化,从而进行某些具体的业务逻辑操作,可以看做是computed和methods的结合体。
Vue.js允许自定义过滤器,可被用于一些常见的文本格式化。
过滤器可以用在两个地方:双花括号插值和v-bind表达式。
过滤器应该被添加在JavaScript表达式的尾部,由“管道”符号指示
支持级联操作
全局注册时是filter,没有s的。而局部过滤器是filters,是有s的
Document
{{msg | format1("帅气") | format2 }}
Document
{{date | format('yyyy-MM-dd hh:mm:ss')}}
事物从出生到死亡的过程
每个Vue
实例在被创建时都要经过一系列的初始化过程,例如:需要设置数据的监听,编译模板,将实例挂载到DOM
上,并且在数据变化时更新DOM
等,这些过程统称为Vue
实例的生命周期
。同时在这个过程中也会运行一些叫做生命周期钩子的函数,这给了用户在不同阶段添加自己的代码的机会。
常用的钩子函数
beforeCreate | 在实例初始化之后,数据观测和事件配置之前被调用 此时data 和 methods 以及页面的DOM结构都没有初始化 什么都做不了 |
---|---|
created | 在实例创建完成后被立即调用此时data 和 methods已经可以使用 但是页面还没有渲染出来 |
beforeMount | 在挂载开始之前被调用 此时页面上还看不到真实数据 只是一个模板页面而已 |
mounted | el被新创建的vm.$el替换,并挂载到实例上去之后调用该钩子。 数据已经真实渲染到页面上 在这个钩子函数里面我们可以使用一些第三方的插件 |
beforeUpdate | 数据更新时调用,发生在虚拟DOM打补丁之前。 页面上数据还是旧的 |
updated | 由于数据更改导致的虚拟DOM重新渲染和打补丁,在这之后会调用该钩子。 页面上数据已经替换成最新的 |
beforeDestroy | 实例销毁之前调用 |
destroyed | 实例销毁后调用 |
其实Vue
实例的生命周期,主要分为三个阶段,分别为
挂载(初始化相关属性,例如watch
属性,method
属性)
beforeCreate
啥也干不了
created
创建 初始化数据 method
beforeMount
虚拟dom
mounted
挂载 经历到这个阶段,数据才可以显示在页面上
更新(元素或组件的变更操作)
beforeUpdate
updated
更新 页面变化立刻,就会被同步到
销毁(销毁相关属性)
beforeDestroy
销毁前
destroyed
销毁。 挂了。彻底废了
前四个阶段 beforeCreate , created, beforeMount , Mounted. 这四个阶段叫做组件(实例)的创建阶段
第五个和第六个 beforeUpdate Updated 组件的运行阶段
第七个和第八个 beforeDestroy destroyed 组件的销毁阶段
一个案例让你了解什么是生命周期。
Document
{{msg}}
beforeCreate
: Vue
实例初始化之后,以及事件初始化,以及组件的父子关系确定后执行该钩子函数,一般在开发中很少使用。
created
: 在调用该方法之前,初始化会被使用到的状态,状态包括props
,methods
,data
,computed
,watch
.
而且会实现对data
中属性的监听,也就是在created
的时候数据已经和data
属性进行了绑定。(放在data
中的属性当值发生改变的时候,视图也会改变)。同时也会对传递到组件中的数据进行校验。
所以在执行created
的时候,所有的状态都初始化完成,我们也完全可以在该阶段发送异步的ajax
请求,获取数据。
但是,在created
方法中,是无法获取到对应的的$el
选项,也就是无法获取Dom
. 所以说上题中选项c
的说法是正确的
created
方法执行完毕后,下面会判断对象中有没有el
选项。如果有,继续执行下面的流程,也就是判断是否有template
选项,如果没有el
选项,则停止整个生命周期的流程,直到执行了vm.$mount(el)
后,才会继续向下执行生命周期的流程。
我们将上方代码el
选项去掉了,运行上面的代码后,我们发现执行完created
方法后,整个流程就停止了。
现在,我们不添加el
选项,但是手动执行vm.$mount(el)
,也能够使暂停的生命周期进行下去。
我们继续向下看,就是判断在对象中是否有template
选项。
第一:如果Vue
实例对象中有template
参数选项,则将其作为模板编译成render
函数,来完成渲染。
第二:如果没有template
参数选项,则将外部的HTML作
为模板编译(template
),也就是说,template
参数选项的优先级要比外部的HTML
高
第三:如果第一条,第二条件都不具备,则报错。
接下来会触发beforeMount
这个钩子函数:
在执行该钩子函数的时候,虚拟DOM
已经创建完成,马上就要渲染了,在这里可以更改data
中的数据,不会触发updated
, 其实在created
中也是可以更改数据,但是不会触发updated
函数。
下面再执行mounted
的时候,可以看到真实的数据。同时整个组件内容已经挂载到页面中了,数据以及真实DOM
都已经处理好了,可以在这里操作真实DOM
了,也就是在mounted
的时候,页面已经被渲染完毕了,在这个钩子函数中,我们可以去发送ajax
请求。
当整个组件挂载完成后,有可能会进行数据的修改,当Vue
发现data
中的数据发生了变化,会触发对应组件的重新渲染,先后调用了beforeUpdate
和updated
钩子函数。
在updated
之前beoreUpdate
之后有一个非常重要的操作就是虚拟DOM
会重新构建,也就是新构建的虚拟DOM
与上一次的虚拟DOM
树利用diff
算法进行对比之后重新渲染。
而到了updated
这个方法,就表示数据已经更新完成,dom
也重新render
完成。
下面如果我们调用了vm.$destroy
方法后,就会销毁所有的资源。
首先会执行beforeDestroy
这个钩子函数,这个钩子函数在实例销毁前调用,在这一步,实例仍然可用。
在该方法中,可以做一些清理的工作,例如:清除定时器等。
但是执行到destroyed
钩子函数的时候,Vue
实例已经被销毁,所有的事件监听器会被移除,所有的子实例也会被销毁。
最后做一个简单的总结:
beforeCreate( )// 该钩子函数执行时,组件实例还未创建.
created()//组件初始化完毕,各种数据可以使用,可以使用ajax发送异步请求获取数据
beforeMounted()// 未执行渲染,更新,虚拟DOM完成,真实DOM未创建
mounted()// 初始化阶段结束,真实DOM已经创建,可以发送异步请求获取数据,也可以访问dom元素
beforeUpdate()//更新前,可用于获取更新前各种状态数据
updated()//更新后执行该钩子函数,所有的状态数据是最新的。
beforeDestroy() // 销毁前执行,可以用于一些定时器的清除。
destroyed()//组件已经销毁,事件监听器被移除,所有的子实例也会被销毁。
力有不逮的对象
众所周知,在 Vue
中,直接修改对象属性的值无法触发响应式。当你直接修改了对象属性的值,你会发现,只有数据改了,但是页面内容并没有改变,上代码:
{{key}}----{{val}}
这是什么原因?
原因在于: Vue
的响应式系统是基于Object.defineProperty
这个方法的,该方法可以监听对象中某个元素的获取或修改,经过了该方法处理的数据,我们称其为响应式数据。但是,该方法有一个很大的缺点,新增属性或者删除属性不会触发监听
原因在于,在 Vue
初始化的时候, Vue
内部会对 data
方法的返回值进行深度响应式处理,使其变为响应式数据,所以, vm.obj.a
是响应式的。但是,之后设置的 vm.obj.b
并没有经过 Vue
初始化时响应式的洗礼,所以,理所应当的不是响应式。
更凄惨的数组
{{item }}
也就是说,数组连自身元素的修改也无法监听,原因在于, Vue
对 data
方法返回的对象中的元素进行响应式处理时,如果元素是数组时,仅仅对数组本身进行响应式化,而不对数组内部元素进行响应式化。
这也就导致如官方文档所写的后果,无法直接修改数组内部元素来触发响应式。那么,有没有破解方法呢?
当然有,官方规定了 7 个数组方法,通过这 7 个数组方法,可以很开心地触发数组的响应式,这 7 个数组方法分别是:
push() |
往数组最后面添加一个元素,成功返回当前数组的长度 |
---|---|
pop() |
删除数组的最后一个元素,成功返回删除元素的值 |
shift() |
删除数组的第一个元素,成功返回删除元素的值 |
unshift() |
往数组最前面添加一个元素,成功返回当前数组的长度 |
splice() |
有三个参数,第一个是想要删除的元素的下标(必选),第二个是想要删除的个数(必选),第三个是删除 后想要在原位置替换的值 |
sort() |
sort() 使数组按照字符编码默认从小到大排序,成功返回排序后的数组 |
reverse() |
reverse() 将数组倒序,成功返回倒序后的数组 |
Document
{{item}}
可以发现,这 7 个数组方法貌似就是原生的那些数组方法,为什么这 7 个数组方法可以触发应式,触发视图更新呢?
你是不是心里想着:数组方法了不起呀,数组方法就可以为所欲为啊?
Sorry,这 7 个数组方法是真的可以为所欲为的。
因为,它们是变异后的数组方法。什么是变异数组方法?变异数组方法即保持数组方法原有功能不变的前提下对其进行功能拓展,在 Vue
中这个所谓的功能拓展就是添加响应式功能。
不会改变原始数组,但总是返回一个新数组
filter | filter() 方法创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素。 |
---|---|
concat | concat() 方法用于连接两个或多个数组。该方法不会改变现有的数组 |
slice | slice() 方法可从已有的数组中返回选定的元素。该方法并不会修改数组,而是返回一个子数组 |
Document
{{item}}
了解完变异方法后,我们回到最初的问题,vm.obj.b = 2; 或者使用索引或length修改数组就真的不能变成响应式的吗?
在解决这个问题之前先了解一下 Vue 的响应式原理:
关于响应式,提出3个问题?
第一个问题: 给属性重新赋值成对象,是否是响应式的?
第二个问题: 给`Vue`实例新增一个成员是否是响应式的?
第三个问题: 通过索引和length修改数组是否是响应式的?
看一下官方的解决方法
深入响应式原理 — Vue.js
当你把一个 JS 对象传给 Vue 实例的 data 属性时,Vue 将遍历此对象的所有属性,并使用 Object.defineProperty 把这些属性全部转为 getter/setter。Object.defineProperty 是 ES5 中一个无法 shim 的特性,这也就是为什么 Vue 不支持 IE8 以及更低版本的浏览器。
受限于现代浏览器,Vue 检测不到对象的添加和删除;因为 Vue 在初始化实例时对 data
属性执行 getter/setter
转化操作,所以对象必须在 data
中才能让其响应式。
Vue 不允许在已经创建的实例上动态添加新的根级响应式属性,但是有时我们项目中一开始的对象的属性不确定,你可能需要为已有对象赋予多个新属性,不过可以使用 Vue.set
或者vm.$set 方法将响应式属性添加到嵌套的对象上。代码演示如下
- Vue.set(a,b,c) 让触发视图重新更新一遍,数据动态起来
- a是要更改的数据 、 b是数据的第几项、 c是更改后的数据
Document
{{ obj.message }}
{{ obj.newProperty }}
-
{{ item }}
总结:
vue中使用索引改变数组是不响应的,解决方式是使用Vue.set(a,b,c)
vue中使用length改变数组的长度也是不响应的,解决方法是使用this.arr.splice(0)---利用的是数组变异方法。
vue中如果给一个对象动态的添加了新属性,我们也需要使用Vue.set(a,b,c) 让 触发视图重新更新一遍