一:计算属性computed
在模板(HTML)中放入太多的逻辑会让模板过重且难以维护,而且不好阅读。计算属性computed来帮忙。
计算属性是一个函数,是经过元数据(data里)进一步运算后的数据。
计算属性的优点是:当元数据不发生变化时,不会再做计算(即:缓存了第一次调用函数的结果),只有元数据发生变化时,才做计算。是响应式的,需要在模板中渲染才可调用(计算属性只能在模板上使用)。
语法:
//定义
//1、计算属性默认是只读的
computed:{
计算属性名: function(){return 返回值}
}
//2、如果想修改计算属性的值
computed:{
计算属性名:{
//当读取计算属性的值时,会调用get函数
get:function(){
return 返回值
},
//当修改计算属性的值时,会调用get函数
set:function(newVal){//newVal:是计算属性的新值。
}
}
}
//使用
使用: {{计算属性}} | v-指令="计算属性"
computed和methods:
methods | computed |
---|---|
每次调用都会执行函数里的代码 | 基于它们的响应式依赖进行缓存的,如果依赖没有变化,就不再调用 |
性能一般 | 性能高 |
{{methodname()}} | {{computedname}} |
适合强制执行和渲染 | 适合做筛选 |
任何地方都可以使用 | 只能在模板上使用 |
二:属性检测(侦听属性)watch
需要在数据变化时执行异步或开销较大的操作时,这个时候需要属性检测watch。而不要使用计算属性,因为计算属性是同步的(需要立即返回结果)。
语法:
watch:{
被侦听的属性名:'methods的里函数名' //数据名==data的key
被侦听的属性名:函数体(new,old){}
被侦听的属性名:{
handler:function(new,old){},
deep: true //面试题:深度检测,当侦听的属性是个对象,修改对象的某个键时,就能检测到
immediate: true //首次运行,要不要监听
}
}
示例:
请输入您的问题:<input type="text" v-model.lazy="question" /><br/>
答案:<input type="text" v-model="answer" /><br/>
let vm = new Vue({
el:"#app",
data:{
question:"",
answer:""
},
watch:{
question:function(){ //此处为简写模式
setTimeout(()=>{
this.answer = "你说的我不懂"
},2000);
}
}
});
计算属性 VS 函数 (方法)VS 属性检测
计算属性(computed) | 函数(methods) | 属性检测(侦听)(watch) | |
---|---|---|---|
作用 | 为了显示而用 | 只是处理逻辑,跟普通的函数一样 | 属性变化的检测(相当于事件),当属性的值发生变化时,可以调用函数 |
依赖模板调用 | √(只能在模板上调用的) | √(可以在模板使用) | ×(不能在模板上使用) |
是否缓存 | √ | × | √ |
异步 | ×(必须是同步) | √(可以有异步) | √(可以有异步) |
三:自定义指令
系统(官方)指令在不够用的情况下,考虑自定义,指令是个函数|对象,用来操作dom的, 里面的this 返回window
全局定义:
Vue.directive('指令名',{
bind:function(el,binding){
binding.arg v-bind:class
}//指令第一次绑定到元素时调用,此时DOM元素还没有显示在页面上
inserted:function(el,binding){} //绑定指令的DOM元素插入到父节点时调用。DOM已经渲染(显示)
update:function(el,binding){} //指令所在的元素的model层的数据被修改,view有更新请求时
componentUpdated:function(el,binding){} //更新完成时,不讲
})
-
指令名:定义指令时,不用加 v- , 使用指令时,加 v-
-
钩子函数:
-
钩子函数的参数:
-
钩子函数的参数 (即 el、binding、vnode 和 oldVnode)。//主要关注el和binding。
-
el:使用指令的 DOM元素
binding:
示例:
//定义指令:
Vue.directive('myfocus', {
inserted: function (el) { // 当被绑定的元素插入到 DOM 中时……
// 聚焦元素
el.focus()
}
})
使用指令
<div>
<input type="text" v-myfocus />
</div>
全局定义格式(简写):
Vue.directive('指令名', function(el,binding){ //等价于:bind + update
})
局部定义格式:
new Vue({
directives:{
指令名 : function(el,binding){},//简写方式: bind + update
指令名(el,binding){},
指令名:{
bind:fn(el,binding){} //指令第一次绑定到元素时调用 v-drag
inserted:fn(el,binding){} //绑定指令的元素插入到父节点时调用 v-focus
update:fn(el,binding){} //指令所在的元素的model层的数据,view有更新请求时
componentUpdated:fn(el,binding){} //更新完成时
}
}
})
示例:模拟v-bind指令的功能:
Vue.directive("mybind",{
bind:function(el,binding){
el[binding.arg] = binding.value;
},
update:function(el,binding){
el[binding.arg] = binding.value;
}
});
//===============简写===============
Vue.directive("mybind",function(el,binding){
el[binding.arg] = binding.value;
});
四:过滤器
对数据在模板中的表现过滤,符合预期,比如:数据是0和1,想要表现成对错、成功失败、数据需要过滤器来格式化。
vue1.x版本有系统自带过滤器,vue2.x之后完全需要自定义,没有自带过滤器。
全局定义:
Vue.filter('过滤器名称',函数(要过滤的元数据,参数1,参数n){
过滤器的功能
return 过滤的结果
})
使用:
{{数据名 | 过滤器名(参数1,参数2)}}
v-bind:属性="数据 | 过滤器名(参数1,参数2)"
| :管道符
示例:
new Vue({
filters:{
过滤器名称:函数(要过滤的元数据,参数){
过滤器的功能
return 过滤的结果
} //函数必须要有返回值
}
})
自定义指令和过滤器的使用场景区别
1、相同点:自定义指令和过滤器都是封装
2、不同点:
1)、自定义指令使用在,dom操作上
2)、过滤器使用在:不需要做逻辑处理,只做数据(格式)转换。
五:混入(mixins)
意义在于分发 Vue 组件(对象)中的可复用功能,混入对象就是一个json对象,json对象的属性就是 Vue对象的配置项(data,methods等等,注意没有el)。
1.定义格式
let mixin1 = {
data: ...
methods:{
sort(){
}
} ...
}
let mixin2 = {
data: ...
methods: ...
}
2.局部混入
mixins: [mixin1,mixin2] //当混入的键与引入键冲突时以组件内的键为主
new Vue({
el:"#app",
data:{
msg:"hello"
}
mixins: [mixin1,mixin2]
})
3.全局混入
Vue.mixin(mixin1)//绝对不推荐的
混入对象和vue对象配置项出现冲突:
1、 混入普通选项与组件(vue对象)选项合并,遇冲突,以组件(Vue对象)为主,即:就近原则。
2、 如果是生命周期钩子函数,那么都会调用(混入的钩子先调用),所以,不推荐使用全局混入。
自定义指令、过滤器、混入的使用场景区别
1、相同点:自定义指令、过滤器、混入都是封装
2、不同点:
1)、自定义指令使用在 dom操作上
2)、过滤器使用在:不需要做逻辑处理,只做数据转换。
3)、混入的功能比较强大,比较综合。因为,它里面包含了vue配置项的所有配置项