本文共 11251 字,大约阅读时间需要 37 分钟。
最近忙着找工作,在这期间的复习过程中,为了方便查阅,总结了很多我常用到的基础内容和面试题。在这里分享给大家,大家也可以参考复习。(Vuex和项目搭建就不在这里说了)
终于来到Vue环节。如果不是采用项目的结构的话,它的使用方法和jQuery、JS很类似。比如:
hi! {
{msg}}
作者想说的话:在这里和以后很多用法可能使用(或者类似于)ES6、AngularJS、Webpack等前端工具(内容)的方法。当你第一次看到时,可能会感到疑惑,但是在这里也不会再做详细说明了。如果对这些不感兴趣,那么就直接对现在Vue的很多用法记住就可以了。
在这个最基本的结构下,需要明白很多东西。这里的v-model和{
{}}到底是如何获取属性的?这涉及到数据绑定。数据绑定就是让数据从一个位置自动流向另一个位置。而它的流向是什么?这涉及到Vue的MVVM模式。 首先有一个监听,会监听输入框的内容。当输入框中的内容发生了改变,监听器就触发。这个监听器的回调函数就会把输入框的内容保存到data里,同时将这个数据输出到页面里去显示。而这个过程就会用到DOM监听和数据绑定。 即,MVVM是: 因此,数据绑定的流向就会有两种:View -> Model 、Model -> View 单向数据绑定就是只能支持一个方向。而双向数据绑定可以支持这两个方向。 之前提到的v-model是双向数据绑定,{ {}}是单向数据绑定。数据绑定就是:当数据改变的时候,视图能够重新渲染。
在Vue2.0中,采用的是ES5的Object.defineProperty defineProperty方式会有以下问题:首先遇到defineProperty就一定要克隆原始数据,因为如果是直接对原数据劫持和拦截,当运行到get时,就相当于又去obj中获取name,又会去执行get。这样就陷入了死循环。其次,get和set里,我们只能一个一个地给每个属性设置监听。且如果在运行过程中,给对象添加了新的属性,显然在最开始没有给它设置监听,那它就实现不出效果。
因为2.0的实现方式会有上述问题,所以在Vue3.0,就对它进行了改进,使用了ES6的Proxy。Proxy方式不用克隆原始数据,而且可以实时向对象中添加属性,还能为它设置监听,从而完美解决了问题。
{ {}}
是单向数据绑定,即用来获取data中数据的。 但是{ { {}}}
虽然也是获取数据,但是它会把这个数据当作标签来看待。 比如: (注意:{ { {}}}之前是能用的,是存在的,但是现在已不推荐这么用) 通过这部分,之后就一定要注意,不要忘记用: 。我有时候会忘记,如果不用的话会把这个数据当成文本。但是注意,这种强制数据绑定和之前的数据绑定v-model不要混淆,并不是任何时候都能用v-model来绑定。 作者想说的话:
在最开始我通常会将它和methods混淆。一定要注意好它们是何时使用。如果你要绑定事件,那么将所对应的事件写在methods下。而如果不是事件,就是很普通的,会使用Vue里data属性的一个普通函数,那就写在computed里。computed通常和input v-model一起使用,且其内部肯定是return。test
在上面的computed的使用:<input type="text" v-model="test4">
之前也说到,v-model不是什么情况都能用的,也就是说除了用v-model就没办法将computed返回的结果显示在页面上吗?
那么,从现在开始,就一定要留意{
{}}的使用,因为它不仅能获取Vue实例中data数据,也能获取computed。除此以外,computed还能做很多事,它不仅仅是上面的例子中,去用来计算。既然computed能像v-model一样显示数据,那不就意味着,它们都能数据绑定吗?即:实现数据的监听(监视) -》当数据变化时,页面能实时改变显示。
const vm = new Vue({ el: '#demo', data: { firstName: 'A', lastName: 'B', fullName2: 'A-B' }, computed: { //第三种方式 fullName1 () { return this.firstName + '-' + this.lastName } }, watch: { //第一种方式 firstName: function (value) { this.fullName2 = value + '-' + this.lastName } }})vm.$watch('lastName', function (value) { //第二种方式 this.fullName2 = this.firstName + '-' + value})
第一种方式,就是使用Vue实例中的watch。在使用时,你需要添加你想监听的属性名并配置监视,相当于属性的set。
第二种方式,就是在创建出Vue实例vm后,使用$watch的方式,来添加监听,完成监视,相当于属性的set。
第三种方式,就是利用computed来实时变化。computed就会在相关的data属性数据发生改变的时候触发,相当于属性的get。
在这三种方式下,我们可以探讨出很多东西。首先前两种方式,相当于属性的set,即:可以发现相关属性值的变化,从而将这个变化值传回到data中。再通过第三种方式computed,相当于属性的get,来获取到修改后的值再将它重新显示到页面上。
在这里就需要说:computed可以不用结合watch来使用,因为watch如果发现了变化,它就会直接修改data里的值,这时只需要再使用v-model或{
{}}就可以实现computed展示的效果,而且要比computed简单。因此第三种方式的使用,不必出现,除非你不是想单纯展示数据,而是要将数据以一定形式来输出,那么computed确实有用。其次,watch方法也可以不用出现。我们知道v-model是双向数据绑定,那么我们可以用更简单,不需要加watch方法,就可以实现数据的实时更新。但是当然,如果在页面上没给你输入框,那么v-model显然用不了,比如后台数据的变化,那就只能通过watch来监听了。这样一来,只要后台数据发生变化,页面的数据就也会发生变化。那么这种情况下,才是watch最关键的作用。
因此什么时候用什么样的监视,需要考虑实际用途和情况。
最后,第四种方式的computed,与前面三种方式相比,它是双向的。也就是利用了JS中的get,set属性。
computed: { fullName3: { get () { return this.firstName + '-' + this.lastName }, set (value) { const names = value.split('-') this.firstName = names[0] this.lastName = names[1] } }}
但是既然它是computed,那么它的局限性就已经很明显了。我们目前知道,computed只能通过v-model和{
{}}方式来调用。因此,在本例上,这个fullName3也暂时只加到了input上。那么,只有当你修改了这个input中的内容,才能触发get和set。那后台数据显然就不能这样用了。因此,总结下来看,computed的局限性不能忽略,watch虽然稍微繁琐一些,但它是监视的主流方案。最后还是推荐使用watch。
computed和methods都可以实现对 data 中的数据加工后再输出。
不同的是computed有一个缓存机制,只有在它的相关依赖发生改变时才会重新求值,即只要data中的数据还没有发生改变,多次访问对数据进行加工的处理函数,计算属性会立即返回之前的计算结果,而不必再次执行函数。而对于methods,每次访问函数,methods总会执行该函数。对于watch就是监视某个数据的变化,当该值变化时执行特定的函数。
在之前已经提到了强制数据绑定是如何使用的:v-bind或 :
在这里,将说到这个强制数据绑定,还能用于class和style。这个用法还是比较关键的,可以实现很多有用的功能。比如之前曾实现的效果:当你点击按钮,将可以切换标签样式。但是当时样式是写在jQuery部分上的。而现在可以直接把切换的样式写在Css上。如下:
class与style绑定 1. class绑定: :class='xxx'
xxx是字符串
xxx是对象
xxx是数组
2. style绑定
测试
首先,对于第一个class的绑定,一共有三种用法,即绑定的是字符串、对象、数组。
(1)字符串:字符串的用法就没什么好说的,只是不要忘记用双引号以及绑定时的冒号。最后就是标签是允许有多个class的,只要样式不重复,那么就取样式的并集。如果样式重复,会被后面的类中的样式替代。
(2)数组:数组的用法并不是很常用。因为使用了数组也就只能意味着这个标签是要这个多class取并集的。但是使用字符串就可以实现,没必要让它变成数组的形式。和字符串时一样,如果样式重复,会被后面类中的样式替代。
对于上面字符串和数组的方式,我们可以知道,这么使用就证明这个标签一定是有多个类的。但实际上,如果你在最开始就知道它有多个类,那么你显然只需要把这些样式全放在一个类中就可以了。而如果是后续动态加入类,那么无论使用数组还是字符串形式去实现,都是可以的,因此常用的还是字符串,这也就是为什么数组不是很常用的原因。
(3)对象:但是使用对象形式,就和上面两种不一样了。因为既然是对象,那么它内部存储的一定有属性名和属性值。而有了属性值,那么就比前两种方式多了一种用法,就是判定当前使用的是哪个类,又或者这些类取并集。比如上面的例子,这个hasClassA和hasClassB的值分别为true和false,并通过点击按钮,将它们取非,这样一来,该标签的类就在不断转换,也就导致标签的样式在不断转换。那如果将这种用法和定时器配合在一起,那么标签的样式,就在自动转换了。同时这些样式不需要写在Vue中,写在css下就可以。
即:<div :class="{classA: hasClassA, classB: hasClassB}"></div>
但是这里一定要注意一点,这里使用的classA,classB,需要在css中实现,而这里的hasClassA和hasClassB是需要在Vue,data里去定义的。然后修改它们的true或false就看你怎么让它实现了。 对于第二个style的绑定,和class就差不多了:
<p :style="{color:activeColor, fontSize: fontSize}">测试</p>
style显然是用来设置样式的,里面的color、fontSize就和css中一样用即可。后面的activeColor和fontSize是定义在Vue,data里的。 除此以外,在这里还有一点要说的。在Html部分使用双引号,在Vue里使用单引号。在这里就有它的用了,如下例:
<p :style="{color: 'red', fontSize: fontSize}">style绑定</p>
这样就可以直接给它设置样式。如果不加单引号,它就会认为red是data里的属性名,而不会把它当成红色看待。因此单引号必不可少,证明它是文本,不是变量。 成功
失败
成功
失败
条件渲染能应用的场景挺多的,如果也想实现像上面class绑定的样式切换那种功能,也是比较容易实现的,但是多了一行代码。
但其实有时候也许我们并不是想切换样式,这时候用类去改变就行不通了。 这时条件渲染的作用就出现了。即:条件渲染比较通用,不仅限于class的改变。如果经常切换的话,推荐使用v-show。同时v-if和v-else是两个一组,但v-show无要求,就算有很多v-show,它也只看里面属性值是true还是false。
v-if会根据表达式的值在DOM中生成或移除一个元素。而v-show是根据表达式的值来显示或者隐藏HTML元素。当v-show赋值为false时,元素被隐藏,此时查看代码时,该元素上会多一个内联样式style=“display:none”。
除此以外,v-if有更高的切换消耗,如果需要频繁切换,则使用v-show更好。
测试: v-for 遍历数组
- { {index}}--{ {p.name}}--{ {p.age}} -- --
测试: v-for 遍历对象
- { {key}}={ {item}}
- { {key}}={ {item}}
对于上面的第二种用法:遍历对象形式,是真的不常用,因此也不再赘述。只需要记住第一种用法。
在这里需要注意一个问题,如果想修改persons中指定索引的值,最基本的方式是:this.persons[index] = newP。但是在这里不能这么用,只能用splice方法。原因是:Vue本身只监视了persons的改变,即它没有监视数组内部数据的改变。也就是说,如果用[index]的方式,它确实修改了指定索引位置的数据,但是Vue并没有检测到persons的变化。存储对象时,存储的都会是[object Object]。也就是说当前Vue只会在persons本身出现增加或删除的情况,才能监视到变化,从而显示出结果。
但是为什么使用splice就可以了?因为这个splice已经不是数组本身的splice方法了,它已经是个变异方法了,即它只是对原方法的一个包装。简单来说就是当你调用原来这个方法,Vue就会对它重写,让它能够因为数组内部改变,而界面自动变化。
最后还需要说,这个filterPersons也能是个computed函数,只不过它一定要返回一个数组。当然数组中是什么样的就看什么需求了。
v-for="(p, index) in filterPersons"
- { {index}}--{ {p.name}}--{ {p.age}}
对于这个实例,如果你仔细看,对JS了解的不够深的话,除了v-for,关键部分可能根本看不懂。在详细看之前,先说一点,这个v-for后面的 :key=”index”,看似毫无作用,但是属于必须加的内容。
接下来看具体操作:
首先对于const {searchName, persons, orderType} = this
,这个到了Vue项目中,将是最常用的用法,到时候一定还会遇到。这个用法,可以快速的将data中和目前同名的属性名对应上。如果不用这个简便用法,要不就是三行this赋值,要不就是每次用都要加上this,这显然很麻烦。而这种方式很简便。 对于let arr = [...persons]
,只要对JS中的深浅克隆有了解,就明白了。详情可以见我之前JS基础知识分享 / 面试文章 中关于深浅克隆的部分。这个浅克隆是ES6的方式,可以将persons数组快速克隆给arr,也是之后Vuex中会用到的用法。
对于arr = persons.filter(p => p.name.indexOf(searchName)!==-1)
key的作用主要是为了高效的更新虚拟DOM,其原理是vue在patch过程中通过key可以精准判断两个节点是否是同一个,从而避免频繁更新不同元素,使得整个patch过程更加高效,减少DOM操作量,提高性能。
另外,若不设置key还可能在列表更新时引发一些隐蔽的bug。
vue中在使用相同标签名元素的过渡切换时,也会使用到key属性,其目的也是为了让vue可以区分它们,否则vue只会替换其内部属性而不会触发过渡效果。
之前已经知道,绑定事件监听使用v-on,也可以用@替代,同时也能用event作形参。
除此以外,大家肯定也都知道和事件相关肯定还有其他用法,如下:
对于按键修饰符,这个13就是enter,而其他按键对应的数字是多少,可以查看百度,或者使用event.keyCode就可以查看,如上例。毕竟如果知道对应数字,那么编写代码时就会快速很多。(但并不是所有按键都能用)对于表单项,我们可以看到一个用法,就是去判定当前的多选框、单选框、下拉框的选择结果。如上例。如果v-model用在text、password、textarea中,就只会在页面上显示v-model内容的属性值。而如果v-model用在radio、checkbox、select中,就会去判定v-model中的值和各自input中设置的value值的相等情况,如果相等就默认(暂时)选择它。
这个生命周期重要就重要在,它可以在Vue的某个阶段,自动作出相关操作。
首先先来看一下所有生命周期: 首先,当建立了一个Vue实例后,马上就会调用beforeCreate,之后Vue做一些准备工作:监视属性值的变化用来实现数据绑定以及初始化事件。之后调用created。接着就去判断el有没有设置。如果设置了,也就指定了Vue会为谁服务,假如在这里不设置,也可以通过手动设置。然后判断是否设置了template,如果没有设置过,那它就会以el指定的区域作为模板,来进行解析。在这里有一个概念叫批量处理。即在解析的时候并不是在页面上直接进行解析,而是先在内存中对所有内容进行批量处理,编译好之后再一次性全部送回到页面。而送回之前就是beforeMount,送回之后就是mounted。到这里为止是生命周期的第一个阶段,初始化显示。
生命周期的第二个阶段:更新状态。在数据发生改变之前就是beforeUpdate,更新后就是updated。
生命周期的第三个阶段:销毁。当调用了vm.$destroy()就意味着要开始进行销毁。通常使用beforeDestroy来做一些销毁前的工作,比如清除定时器。销毁后就是destroyed。
其中最常用的生命周期方法是:
简单使用例:
hello
created:在模板渲染成html前调用,去初始化某些属性值。
mounted:在模板渲染成html后调用,对html的dom节点进行一些需要的操作。加载渲染过程
同步引入时生命周期顺序为: 父组件的beforeCreate、created、beforeMount --> 所有子组件的beforeCreate、created、beforeMount --> 所有子组件的mounted --> 父组件的mounted 总结:父组件先创建,然后子组件创建;子组件先挂载,然后父组件挂载 异步引入时生命周期顺序为: 父组件的beforeCreate、created、beforeMount、mounted --> 子组件的beforeCreate、created、beforeMount、mounted 总结:父组件创建,父组件挂载;子组件创建,子组件挂载。子组件更新过程
父beforeUpdate->子beforeUpdate->子updated->父updated父组件更新过程
父beforeUpdate->父updated销毁过程
父beforeDestroy->子beforeDestroy->子destroyed->父destroyed我们知道CSS中过渡和动画分别是transition和animation,但是需要注意在Vue中使用时,只需要在目标元素外包裹transition标签(没有animation标签!),然后为transition标签设置一个name,然后去CSS中对这个name作过渡和动画操作即可。比如:(name可以设置为任何值)
但是它具体是怎么做到的?整个过程如下: 在这里想实现的效果就是hello的消失与出现。简单来看,这段代码貌似没有什么办法可以触发过渡和动画效果,实际上Vue帮我们做了一个事:给目标元素添加/移除特定的class。比如它在Vue处理后,实际上是这样的:<p v-show="show" class="xxx-enter">
就像上图中展示的过程,在这里就以出现和消失举例,其他效果也是同理的。 当最开始的时候,元素是隐藏的状态,即Opacity:0,它会给元素加一个类名: xxx-enter,也就是通过xxx-enter来指定了元素隐藏时候的样式。元素要出现时(出现的过程),就会给它加xxx-enter-active的类名,过渡/动画 效果结束的时候,就会给它加xxx-enter-to的类名。 对于消失部分也是同样的,在要消失前是xxx-leave,消失的过程是
xxx-leave-active,消失后就是xxx-leave-to,同时通过xxx-leave-to来指定了元素隐藏时候的样式。(当然 过渡/动画 效果不仅限于出现和消失,也会有其他效果,在这里以出现和消失举例,并不意味着这种方法只能实现出现和消失或者必须实现出现和消失)
所以通过整个过程的分析,也就不难看出,对于该元素来将:
xxx-enter和xxx-leave-to,都用来指定隐藏时的样式,只不过一个是出现前,一个是消失后,因此它们通常放在一起实现。 xxx-enter-active和xxx-leave-active,分别用来记录出现的过程和消失的过程,即用它们来指定过渡效果。在这里需要注意的是,xxx-enter-to和xxx-leave只代表着 过渡/动画 效果结束时和元素准备实现 过渡/动画 效果这两个瞬间,即这两个类名不会长时间存在。所以通常也不需要实现它们。
因此根据这些特性,具体例子如下:
10_过渡&动画1 hello
hello
同样地,对于动画,依然需要@keyframes:
10_过渡&动画2 Lorem
除了之前的所有指令外,还有两个Vue内置的指令,ref和v-cloak。
{
{content}}abcd
首先对于这个ref的使用,之前都是在data里设定一些属性名,现在通过ref相当于在标签里设定属性名,即:为某个元素注册一个唯一标识。然后vue对象就可以通过$refs属性访问这个元素对象。如上例。
然后对于v-cloak的作用:
当你第一次进网页时(即:网页还没被解析时),你会看到它的表达式形式,即:{ {content}}。但是正常看大家肯定看不出效果,因为它一闪而过。如果想要看这个效果,可以在新建Vue对象前,加一个alert,即可看到效果。而为了避免这种情况,我们就可以使用v-cloak那么v-cloak为什么可以避免这种情况呢?
在Vue中,所有的这些内置指令都有一种特性:在页面被解析后,这些和Vue相关的指令都会消失,如下图所示。 而v-cloak正是用了这样的特性,在没被解析之前,因为这个指令的存在,设置了css样式display:none,所以指定的标签就不会出现,当页面被解析后,因为指令的消失从而让标签内容出现。 (但实际上平常很少使用v-cloak,因为一闪而过,没人会注意)test {
{test4}}
- { {p.name}}--{ {p.age}}
转载地址:http://rlyki.baihongyu.com/