17 KiB
Vue基本认知
Vue是一个JavaScript框架,它的特点在于使用者不用再思考DOM的操作,一切都由Vue来承担,这就是Vue的MVVM模式,使用Vue框架你只需要操作数据而不是DOM。
Vue的v-for: 是Vue中一个简单的for循环,目前学到的课程中它可以用来遍历数组。 Vue的v-on: 是Vue中用于绑定事件的指令,它的作用是绑定一个事件,它可以简写成@。 Vue的v-bind: 用于传递数据,它可以帮你在组件之中传递值。 Vue的v-model: 数据的双向绑定。
Vue的el: 是Vue实例的“管辖范围”,它用于确定Vue实例的生效区域。 Vue的data: 是Vue实例的数据区域,它一般用于放置Vue实例中的数据内容。 Vue的methods: 用于放置Vue实例的方法,任何Vue中的使用的函数方法都要在其中定义。
Vue 的深入理解
Vue的组件间传值
需要用到props
、v-bind
、$emit
等方法的配合。
Vue的生命周期函数
Vue在实例生成之前和生成之后总共有8个生命周期函数,他们分别是:
beforeCreate
:在实例生成之前created
:实例生成之后beforeMount
:实例渲染之前mounted
:实例渲染之后beforeUpdata
:实例数据修改之前updatad
:实例数据修改之后beforeDestroy
:实例销毁之前destroyed
:实例销毁之后
Vue的模板语法
Vue中的模板语法有插值表达式、v-text
、v-html
等等。
任何v-开头的Vue指令,后面接的都是JS的表达式,也就是说可以在后面接上加减乘除等JS语句,插值表达式也是如此。
计算属性,方法和侦听器
计算属性 computed
:
直接通过属性名就能使用,因为原因和上面说的一样:
任何v-开头的Vue指令,后面接的都是JS的表达式。也就是说可以在后面接上加减乘除等JS语句。
缓存功能在计算的成员值不变的情况下将不会进行第二次计算,节省资源。
方法methods:
也可以直接通过属性名使用(注意方法独有的括号),但是它没有计算属性的缓存功能,在计算成员值不变的情况下每次都会重新计算一次,在网页元素比较多的情况下可能会有比较明显的资源浪费。
监听器watch:
可以监听指定的方法,当监听的方法发生变化时会执行指定的操作,保留了计算属性的缓存功能。
当以上三种方法同是适用的候,优先推荐计算属性 computed
,既简洁,也保留了性能。
计算属性的getter和setter
计算属性你可以使用 Get
方法,通过其他值算出一个新值,也可以使用 Set
方法,通过设置一个值改变相关联的值,从而使用计算属性的特性引起第二次计算。
Vue中的样式绑定
可以使用 isActivated
来控制样式名字的显示和隐藏,在 data
或 methods
中设置 isActivated
为true就会绑定上CSS的样式。也可以使用数组来控制样式名字,设置数组的第一个值为空,标签就没有绑定CSS样式,设置数组第一个值为CSS样式名字则会绑定,还可以使用V-bind:style="CSS样式名字"
的方式来进行绑定,这样CSS样式名字就是一个Vue的 data
值,可以在Vue的data
中控制它的属性,以此类推,这种方法后面也能接一个数组,更多样化。
Vue的条件渲染
v-if、v-else-if、v-else:
v-if
是一个Vue的指令,它的值决定了它所在的这个DIV标签是否渲染显示,每次的隐藏和显示都相当于删除和增加一个DOM元素,它还能搭配 v-else
或 v-else-if
一起组合使用(警告,v-if
和 v-else
、v-else-if
必须紧靠在一起使用!)。
由于Vue的特性,Vue在渲染网页的时候会尽量复用页面上已有的DOM,这可能会产生一些问题,为了解决这些问题就有key
值这个概念,key
值是独一无二的,Vue并不会复用key值不一样的DOM元素。
v-show:
v-show
与 v-if
类似,但是它每次的隐藏和显示并非是在页面上删除和增加一个新的DOM,而是通过隐藏DOM标签,在相同的环境下,v-show
所需要的性能相对要低于前者。
Vue的列表循环
key、数组操作:
当使用v-for
遍历来实现列表渲染编写key
值时,考虑到性能和一些未知的问题,尽量不要使用数组的下标作为key
值,而是使用数组中一些独一无二的值。
当你直接对Vue的数组操作其下标时,数据会发生变化,但是页面不会发生变化,你需要使用Vue提供的7个数组操作方法来对数组进行操作,它们分别是:
push
:向数组的末尾添加一个元素pop
:删除数组的最后一个元素shift
:删除数组的第一个元素unshift
:向数组的开头添加一个或多个元素splice
: 向数组中删除或添加元素sort
: 对数组进行排序reverse
对数组进行取反
还有通过改变数组的引用来实现对数据的操作,即直接改变遍历的数组,这种方法也能在数据变化的同时页面同时变化
遍历对象:
列表渲染不但可以使用数组,也可以使用一个对象,使用的方式和数组相同,但是使用对象进行列表渲染时,网页并不会渲染对象的键名,而是直接显示对象的值,取而代替的是一个叫key
的变量,其中对象的index
和数组相同。
在使用对象进行列表渲染时,你无法使用Vue提供的7个数组操作方法,你可以直接修改对象里的数据,数组变的同时页面也会跟着发生变化,但是和数字相同:直接往对象里添加数据时,页面是不会发生变化,与之类似,你可以直接改变对象的引用来实现数据的变化页面跟着变。
使用组件的细节点
当你使用Vue的组件功能实现组件化时,你定义了一个组件,这个组件的名字可能与HTML自有的标准不符,使用这些组件的时候会产生一些问题,这时Vue提供了 is="组件名"
的语法来解决这种问题,这种方法的作用就是在遵守HTML标准的同时使用你自定义的组件。
在组件中定义data
时,data
必须是一个函数而不是一个对象。
ref:
当你在HTML标签中使用ref时,你获取到的是 ref
对应标签的DOM元素,而当你在组件中使用 ref
时,你获取到的是子组件的引用。
父子组件传值
隐形的规定——单向数据流:
父组件可以随意的向子组件传值,子组件也可以修改父组件传递过来的值,但是这样可能会导致一些问题,所以在子组件中使用父组件传递来的值时,需要使用子组件自己的 data
来复制一份来自父组件的值。
emit():
子组件向父组件传值需要用的 $emit()
这个方法,这个方法不但可以向外触发事件,还可以在触发事件的同时传递一个值(向外触发的事件名可能不允许大写)。
组件参数校验与非props特性
参数校验:
父组件可以任意向子组件传值,子组件对传递过来的值可以进行一个校验,也就是对传递的值有一定的约束,要使用这个特性,子组件里的props就不再是一个数组,而是一个对象,在对象中可以对传递过来的值进行一个约束,约束的条件还可以是一个数组,甚至是一个对象。
当 props
是一个对象时,你可以使用 validator
这一个函数还对传递值进行校验,还可以使用 default
来规定一个未传值时的默认值,required来规定父组件必须传值,当然还有 type
来约束传递的值类型。
非props特性:
当父组件向子组件传值的时候,子组件需要声明 props
来获取来自父组件的值,这个时候父组件传递的值并不会显示在子组件DOM中,但是子组件如果并没有声明 props
来获取父组件的值,那么这个值会显示在子组件的DOM中,这就是 非props
特性。
给组件绑定原生事件
当你直接在子组件的中使用父组件的函数,这时候绑定的其实是组件的自定义事件,需要用 $emit
来向外触发和监听,你需要在子组件中的模板中绑定这个事件,这时候绑定和触发的才会是父组件的函数,如果你确实需要直接用子组件绑定父组件的事件,你可以在子组件的自定义事件后面添加 .native
,这个时候绑定的也是父组件的函数。
非父子组件间的传值
bus:
在使用Vue进行组件化传值的时候,会遇到这样一个问题:非父子组件间传值。如果按照传统的方法将值一层一层传递上去,这样写出来的代码将会非常冗长,这是就有了 bus
这个概念,在使用 bus
前你需要事先给 Vue.prototype.bus
赋值一个新的Vue实例: Vue.prototype.bus = new Vue()
,这句话的意思在 Vue.prototype
上挂载了一个名叫 bus
的属性,它指向一个Vue的实例。每当你去创建一个Vue实例或者一个组件时,都会有bus这个属性。
有了 bus
,非父子组件间传值就变的非常容易了,就像子组件向父组件传值那样,传值组件中用 bus
向外触发一个事件:this.bus.$emit("事件名","数据")
。然后在Vue的8个生命周期钩子之一:mounted
(实例渲染之后)中写一个函数,这个函数 bus
中的 $on
函数监听 bus
向外触发的事件名和数据,再传递给接收组件。这样就完成了非父子组件间传值的需要。(警告:在接受组件的 mounted
函数中操作数据时,this
的作用域可能会发生变化,需要用 var this_ = this
来保存 this
的数据。)
在Vue中使用插槽
插槽:
子组件内的某些元素需要由来自父组件或者其他组件的值来决定时,子组件自带的模板似乎就不是那么好用,这时Vue就提供了一个新的功能:插槽。插槽使用的方法很简单,只需要在子组件的模板中添加一行要插入的内容,之后在 template
中相应的位置插入 <slot></slot>
就可以了,在这个元素中还可以加入默认值以表示插槽未定义时的值。
具名插槽v-slot:
假如你需要由来自两个不同的组件的值来显示在不同的插槽位置时,单单<slot></slot>
是不够的,为了解决这个问题,Vue有一个新的指令 v-slot
,它用于给插槽指定一个名字,之后在 template
使用name="插槽名"
就可以实现不同位置显示不同的插槽的需求。(注意:v-slot
只能写在模板占位符即 template
中)
作用域插槽slot_sope:
组件化的使用过程中还有可能遇到一种情况:当子组件的 DOM结构应该由外部传递进来的时候,这个时候就要使用作用域插槽来解决问题,子组件插槽可以向父组件插槽传数据,子组件用 v-bind
传,父组件用 slot-scope="属性名"
接受数据。
动态组件与v-once指令
动态组件:
在之前的笔记中可以看到:在一个 DOM元素中使用 is="组件名"
的方式可以在不影响语法要求的情况下将原来的DOM元素替换为定义的组件,这种特性与<component></component>
结合就成了Vue的动态组件(也可以不是<component></component>
),在 data
中定义一个变量,变量的值是组件名,通过改变这个变量的名为其他组件名来实现动态组件。
v-once:
在上面的方法每当 is="组件名"
的值变化,在渲染显示一个组件的同时,Vue会将其他的未被渲染的组件隐藏销毁,也就是说用上面的方法每次动态组件切换时Vue就会渲染组件的同时和销毁隐藏的组件,如果频繁切换组件这种方法无疑会影响性能,v-once
指令会将组件在隐藏时放入内存中,重新调用的时候再从内存中拿出来,通过 v-once
指令,可以有效提高一些静态内容的展示效率。
Vue中的CSS动画原理
为Vue元素添加动画时,需要用<transition>
标签包住元素,这样才能为Vue元素添加动画效果,当你不为<transition>
标签指定一个name
时,动画样式的前缀默认为v-
,还可以在<transition>
使用-class
为enter
和leave
动画指定一个CSS样式名字,这样Vue就会使用你指定的样式名字。(这个时候就不在需要name
)
Vue动画从开始到结束会有3个过程即从开始到结束和中间,进入过程:Vue会为这三个不同的过程中添加不同的CSS样式:enter
、enter-active
、enter-to
。
与之相似,退出过程也会有三个CSS样式:leave
、leave-active
、leave-to
。
为什么使用enter作为动画的入场开始:
使用enter
作为入场开始是因为动画在默认情况下opacity
为1,这时需要在第一帧是将其写为0,在之后的进行中中过程中enter
会被移除,这时opacity
为0。
为什么使用leave-to作为动画的出场开始:
使用leave-to
作为出场开始是因为动画第一帧opacity
需要为1,从第二帧开始leave
被移除,这时opacity
的值还是1,需要将其改为0,动画才会被正常触发。
在Vue中使用animate.css库
库的动画是CSS3标准的动画。由于Vue可以更改CSS样式的名字,所以我们可以使用在实现复杂的动画时可以使用使用一些CSS库如animate.css,用-class
为动画指定名字为CSS库的样式名字,实现CSS库的绑定。
在Vue中同时使用过渡和动画
元素第一次显示的动画效果:
当需要元素第一次显示时也有动画效果,需要在<transition>
标签中写入两个属性:appear
、appear-active-class
,第一个表示第一次显示元素时也有动画效果,第二个表示动画效果的CSS规则,它的值就是CSS动画规则名。
同时使用CSS库和过渡动画:
要实现这种效果,需要为在<transition>
标签中为元素绑定两个CSS规则,分别为CSS库动画和过渡动画——enter
和leave
CSS库和过渡动画执行时间不一致:
在使用CSS库的时候,而它往往都是固定的,而自定义的过渡效果可能和它不一样,这是可以在<transition>
标签中写一个新的属性type,它的值决定了最终动画时长以谁为准(animation
或 transition
)
来自官方的解释:Vue 为了知道过渡的完成,必须设置相应的事件监听器。它可以是
transitionend
或animationend
,这取决于给元素应用的 CSS 规则。如果你使用其中任何一种,Vue 能自动识别类型并设置监听。 但是,在一些场景中,你需要给同一个元素同时设置两种过渡动效,比如animation
很快的被触发并完成了,而transition
效果还没结束。在这种情况中,你就需要使用type attribute
并设置animation
或transition
来明确声明你需要 Vue 监听的类型。
显性的过渡持续时间:
在大多数情况下,Vue可以自动得出动画所需要的执行时长,当然也可以用duration
属性定制执行时长(这个属性需要用v-bind绑定,并且以毫秒表示)。duration
属性的值还可以是多个,用{}符号包裹,这个情况下可以分别为enter
和leave
动画定制执行时长。
Vue中的JS动画
在Vue动画的开始和结束,有6个JS钩子,它们分别是:
before-enter
:入场动画之前
enter
:入场动画执行中
after-enter
:入场动画之后
before-leave
:出场动画之前
leave
:出场动画执行中
after-leave
:出场动画之后
Vue中多个元素或组件的过渡
Vue在渲染网页的时候会尽量复用页面上已有的DOM
,在使用Vue的动画效果时可能会产生一些问题,这时候也需要为元素指定Key
值,保证动画的正常执行。
<transition>
标签中有一个属性叫:mode
,它有两个值:in-out
和out-in
,mode
的值为in-out
时,动画会先显示再隐藏,而out-in
则与之相反,不使用mode
属性时,动画就会同时执行。多个组件的过渡动画可以使用动态组件来实现。
Vue的列表过渡
与单个元素使用动画效果不同,列表渲染相当于渲染多个元素的,这是<transition>
标签不支持的,这时候就需要使用<transition-group>
标签,这个标签相当于为每一个渲染的元素添加上一个<transition>
标签。
Vue中的动画封装
在很多时候一个相同的动画会用上很多次,尽管他们的元素各不相同,这样一来,每为一个元素设定这个动画都需要重复编写<transition>
,这是很不方便的,为了解决这个问题,我们可以使用Vue组件来对重复使用的动画进行封装。除此之外还可以将CSS规则进行封装,用Vue动画的6个JS钩子将它改写为JS动画写在组件的methods
中。
拓展
或许我可以用Vue的模板功能来生成一个带有Vue实例接管的模板,例如:
template: "<li id="app">Hello Wrold</li>"
在Vue框架的使用中,你可以使用一个叫<template>
的新标签,这个标签并不会真的渲染到页面之上,但是它可以结合Vue指令来实现一些意想不到的效果,一个既不会真的渲染多一个标签但又确实存在的效果。
还有一个特别的方法能改变列表渲染时的值:Vue.set方法