vue.js的两个核心
数据驱动和组件化
v-if
和 v-show
的区别
相同点: 两者都是在判断DOM节点是否要显示
不同点:
a.实现方式: v-if是根据后面数据的真假值判断直接从Dom树上删除或重建元素节点。 v-show只是在修改元素的css样式,也就是display的属性值,元素始终在Dom树上。
b.编译过程:v-if切换有一个局部编译/卸载的过程,切换过程中合适地销毁和重建内部的事件监听和子组件; v-show只是简单的基于css切换;
c.编译条件:v-if是惰性的,如果初始条件为假,则什么也不做;只有在条件第一次变为真时才开始局部编译; v-show是在任何条件下(首次条件是否为真)都被编译,然后被缓存,而且DOM元素始终被保留;
d.性能消耗:v-if有更高的切换消耗,不适合做频繁的切换; v-show有更高的初始渲染消耗,适合做频繁的额切换;
vue常用的修饰符
a、按键修饰符
.delete(捕获“删除”和”退格“键):用法上和事件修饰符一样,挂载在v-on:后面,语法:v-on:keyup.xxx=’yyy’
<input class = 'aaa' v-model="inputValue" @keyup.delete="onKey"/>
b、系统修饰符
可以用如下修饰符来实现仅在按下相应按键时才触发鼠标或键盘事件的监听器:
.ctrl、.alt、.shift、.meta
c、鼠标按钮修饰符
.left、.right、.middle
这些修饰符会限制处理函数仅响应特定的鼠标按钮。如:<button @click.middle ="onClick">A</button>,
鼠标滚轮单击触发 Click默认是鼠标左键单击
d、其他修饰符
.lazy
在默认情况下,v-model
在每次 input
事件触发后将输入框的值与数据进行同步 ,我们可以添加 lazy
修饰符,从而转变为使用 change
事件进行同步:
<!-- 在“change”时而非“input”时更新 -->
<input v-model.lazy="msg" >
.number
如果想自动将用户的输入值转为数值类型,可以给 v-model
添加 .number
修饰符:
<input v-model.number="age" type="number">
这通常很有用,因为即使在type="number"
时,HTML 输入元素的值也总会返回字符串。如果这个值无法被 parseFloat()
解析,则会返回原始的值。
.trim
如果要自动过滤用户输入的首尾空白字符,可以给 v-model 添加 trim 修饰符:
<input v-model.trim="msg">
vue中 key
值的作用
使用key来给每个节点做一个唯一标识。
key的作用主要有以下两个:
高效的更新虚拟DOM:用v-for
正在更新已渲染过的元素列表时,它默认用“就地复用”策略。如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序, 而是简单复用此处每个元素,并且确保它在特定索引下显示已被渲染过的每个元素。
假设Vue实例的data
属性中有一个叫numbers
的变量,它的值是[1, 2, 3, 7, 8, 9]
:
<div v-for="num in numbers">
{{num}}
</div>
这种情况下应当是渲染了6个<div>元素,其中的内容分别对应numbers中6个数字,此时如果numbers变成了[0, 1, 2, 3, 7, 8, 9],即在数组头部插入了一个数字0,在没有key属性的情况下,渲染输出的更新步骤是这样的:
原先内容为1的<div>元素内容变成0,原先内容为2的<div>元素内容变成1,……以此类推,最后新增一个<div>元素,内容为9。
在这种情况下,Vue会通过改变原来元素的内容和增加/减少元素来完成这个改变,因为没有key属性,Vue无法跟踪每个节点,只能通过这样的方法来完成变更。
让我们对以上代码进行一个小修改:
<div v-for="(num, index) in numbers" :key="index">
{{num}}
</div>
我这里用index变量,根据列表渲染的规则,它实际上对应了数组中每个元素的索引,这样做的好处是它可以使得每个元素的key值都不同,这是很重要的,如果我们要利用key属性的优点,必须保证同一父元素的所有子元素有不同的key属性。
此时如果numbers从[1, 2, 3, 7, 8, 9]变成了[0, 1, 2, 3, 7, 8, 9],渲染输出的更新步骤就变化了:
新增一个<div>元素,它的内容为0,并将它插入原先内容为1的元素之前。
在有了key属性之后,Vue会记住元素们的顺序,并根据这个顺序在适当的位置插入/删除元素来完成更新,这种方法比没有key属性时的就地复用策略效率更高。
强制替换元素,触发过渡效果:
key
属性还有另外一种使用方法,即强制替换元素,从而可以触发组件的生命周期钩子或者触发过渡。因为当key
改变时,Vue认为一个新的元素产生了,从而会新插入一个元素来替换掉原有的元素。
<transition>
<span :key="text">{{text}}</span>
</transition>
这里如果text
发生改变,整个<span>
元素会发生更新,因为当text
改变时,这个元素的key
属性就发生了改变,在渲染更新时,Vue会认为这里新产生了一个元素,而老的元素由于key
不存在了,所以会被删除,从而触发了过渡。
假如没有key
属性:
<transition>
<span>{{text}}</span>
</transition>
那么当text
改变时,Vue会复用元素,只改变<span>
元素的内容,而不会有新的元素被添加进来,也不会有旧的元素被删除。
同理,key
属性被用在组件上时,当key
改变时会引起新组件的创建和原有组件的删除,此时组件的生命周期钩子就会被触发。
Vue 组件中 data 为什么必须是函数
当data选项是一个函数的时候,返回的是一个独立的对象,这样各个实例中的data不会相互影响。
vue生命周期钩子函数
总共分为8个阶段:
创建前/后
beforeCreated:vue实例的挂载元素$el和数据对象data都为undefined,还未初始化。
created:vue实例的数据对象data有了,$el还没有。
载入前/后
beforeMount:vue实例的$el和data都初始化了,但还是挂载之前为虚拟的dom节点,data.message还未替换。
mounted:vue实例挂载完成,data.message成功渲染。
更新前/后
当data变化时,会触发beforeUpdate和updated方法。
销毁前/后
beforeDestroy和destroy
vue 的双向绑定的原理
vue事件中如何使用event对象
1、使用不带圆括号的形式,event 对象将被自动当做实参传入;
2、使用带圆括号的形式,我们需要使用 $event 变量显式传入 event 对象。
//不带圆括号,自动传入enevt
<button v-on:click="click">click me</button>
methods: {
click(event) {
console.log(typeof event); // object
}
}
//带圆括号,使用$event 变量显式传入 event 对象
<button v-on:click="click($event, 233)">click me</button>
click(event, val) {
console.log(typeof event); // object
}
vue中 keep-alive
组件的作用
<keep-alive>
是Vue的内置组件,当使用它包裹动态组件时,会缓存不活动的组件实例,将组件状态保留在内存中,防止重复渲染DOM,而不是销毁它们。详情请查看keep-alive详解
vue更新数组或对象触发视图更新
使用Vue.set( target, propertyName/index, value ),或者vm.$set(),vm是vue实例:
参数:
{Object | Array} target
{string | number} propertyName/index
{any} value
向响应式对象中添加一个属性,并确保这个新属性同样是响应式的,且触发视图更新。它必须用于向响应式对象上添加新属性,因为 Vue 无法探测普通的新增属性 (比如 this.myObject.newProperty = 'hi'
),正确的方法是:Vue.set(this.myObject
, 'newProperty
', 'hi
');
对于数组,当修改数组的长度时,或者利用索引直接改变数组的一个元素时,不会触发视图更新,需要使用Vue.use(),或者使用数组的push、splice等方法。
解决非工程化项目初始化页面闪动问题
vue页面在加载的时候闪烁花括号{}},v-cloak指令和css规则如[v-cloak]{display:none}一起用时,这个指令可以隐藏未编译的Mustache标签直到实例准备完毕。
/*css样式*/
[v-cloak] {
display: none;
}
v-model语法糖的组件中的使用
v-model 主要是用于表单上数据的双向绑定和在组件上使用。
表单上的数据双向绑定:
<input type="text" v-model="mes">
此时mes值就与input的值进行双向绑定, 实际上上面的代码是下面代码的语法糖。
<input v-bind:value="mes" v-on:input="mes= $event.target.value"/>
组件上的使用:
父组件
<InputBox v-model="mes"></InputBox>
根据上面讲的v-model语法糖,所以 InputBox那行代码也可以写成
<InputBox v-bind:value="value" v-on:input="mes= $event.target.value"></InputBox>
子组件:
但是单选复选框不会触发input事件,只会触发change事件。所以在子组件我们需要自定义v-model。
vue等单页面应用及其优缺点
单页面应用(SPA),是指只有一个主页面的应用,浏览器一开始要加载所有必须的 html, js, css。所有的页面内容都包含在这个所谓的主页面中,然后在交互的时候由路由程序动态载入,单页面的页面跳转,仅刷新局部资源。多应用于pc端。
优点:
- 用户体验好,快,内容的改变不需要重新加载整个页面,基于这一点spa对服务器压力较小
- 前后端分离
- 页面效果会比较炫酷(比如切换页面内容时的专场动画)
缺点:
- 不利于seo
- 导航不可用,如果一定要导航需要自行实现前进、后退。(由于是单页面不能用浏览器的前进后退功能,所以需要自己建立堆栈管理)
- 初次加载时耗时多
- 页面复杂度提高很多
vue添加自定义指令
使用Vue.directive(id, [definition]),id是指令的名称,在使用时加上‘v-’,definition是一个对象,这个对象的属性是directive的钩子函数:
bind: 只调用一次,指令第一次绑定到元素时调用,用这个钩子函数可以定义一个在绑定时执行一次的初始化动作。
inserted: 被绑定元素插入父节点时调用(父节点存在即可调用,不必存在于 document 中)。
update: 被绑定元素所在的模板更新时调用,而不论绑定值是否变化。通过比较更新前后的绑定值,可以忽略不必要的模板更新
componentUpdated: 被绑定元素所在模板完成一次更新周期时调用。unbind: 只调用一次, 指令与元素解绑时调用。
大多数情况下,我们可能想在 bind 和 update 钩子上做重复动作,并且不想关心其它的钩子函数。此时可以简写成如下形式:
Vue.directive('test',function(el,binding){
//el是event对象
//binding是一个对象,可以访问它的value属性,来获取传给该指令的值
console.log(binding.value);
})
//使用
<div v-test="{a:'aa',b:'bb'}"></div>