先看下Vue运行机制图
那么我们思考一件事,vue是通过watcher监听数据的变化然后给发布-订阅,这样实现了dom的渲染,那么我们思考一件事,我们往往需要知道一个数据的变化然后给页面相应的渲染,那么我们工作中在组件中的数据发生了变化我们监听到然后给相应的行为。
watch登场
watch:是vue中常用的侦听器(监听器),用来监听数据的变化。
做一个简单的思考,其实就是当数据变化的时候,把新的旧的数据都同步给了watch,所以我们通过watch来去调用相应数据的方法,就可以取到相应的值。
watch的使用方式(简单数据类型)
watch: {
这里写你在data中定义的变量名或别处方法名: {
handler(数据改变后新的值, 数据改变之前旧的值) {
这里写你拿到变化值后的逻辑}
}
}
举例
data() {return {value: ""}},watch: {//方法1"value"(newVal, oldVal) {console.log(`新值:${newVal}`);console.log(`旧值:${oldVal}`);console.log("hellow world");}//方法2"value": {handler(newVal, oldVal) {console.log(`新的值: ${newVal}`);console.log(`旧的值: ${oldVal}`);console.log("hellow world");}}}
监听:复杂数据类型的单一属性
'query.page': {handler(val, oldval) {console.log('1获取新的数据真正是', val, oldval)}},
watch的使用方式(复杂数据类型)
query: {handler(newVal, oldVal) {console.log('2获取复杂数据', newVal, oldVal)},deep: true}
因为watch是数据发生变化的时候才会调用,如果想已进入页面就使用watch(这个不常用)
value: {handler(val, oldval) {console.log('获取新的数据真正的', val, oldval)},immediate: true},
我们再思考一件事情我们除了监听data里边的数据,可不可以监听filter,computed呢?
首先我们总结一下vue组件中出现的数据有哪些?
vue中其他类型的数据
computed
computed的监听
computed: {newValue: function() {if (this.value === 0) {return 'this is a computed'} else {return 'this is a new computed'}}},watch:{newValue: {handler(newVal, oldVal) {console.log('监听computed', newVal, oldVal)}},}
我们延申一下,再思考一下,computed是一个什么样的存在,相当于爆露出来还是一个新的数据,因为在beforeUpdate的回调中的我们也可以做这样的操作,比如把一个新的值给新的值,这样实现数据修饰。
我们看一下computed的介绍
computed用来监控自己定义的变量,该变量不在data里面声明,直接在computed里面定义.
然后就可以在页面上进行双向数据绑定展示出结果或者用作其他处理;并且带有缓存功能
computed比较适合对多个变量或者对象进行处理后返回一个结果值,也就是数多个变量中的某一个值发生了变化则我们监控的这个值也就会发生变化,
举例:总金额=价格*数量
也就是说当我们需要进行大量计算的时候我们适合用computed。c=a*b,a和b不发生变化,就不会重新去取,这就是computed的优势。也就是说这个可以提高项目的性能。
我们总结一下一个页面重新渲染的办法有哪些?
页面渲染的方式
1.表达式。(缺点是不太灵活)
2.methods。(缺点是每次调用都需要重新的解析)
3.filters
4.computed
5.生命周期内实现数据修饰
6.props (父组件传过来的值)
这里我们主要提到filter的computed的使用,可以提高项目的运行效率。那么filter与computed的区别是什么呢?
filter经常使用在格式化上。
computed经常使用在计算上。
filter 与 computed 的区别
触发时机不同
computed 属性背后的处理逻辑比较复杂,依赖 Vue 的数据更新通知机制,在属性所依赖的其他数据项发生变化时才会重新触发计算。优点是计算频率相对较低;缺点是依赖于组件,难以抽取成独立逻辑,也就是复用性低。
filter 则显的简单很多,只在显式调用时触发,一般应用在模板渲染上。优点是容易在组件外抽象;缺点是每次模板渲染时都需要重新执行计算。可以通过示例 感受调用时机的区别:
应用范围不同
computed 很广泛,可以应用在其他computed、methods、生命周期函数、模板;filter 一般只应用于模板渲染上,如果要在其他位置复用,需要使用 this._f 函数:
Vue.component('HelloWorld', {filters: {hello() {return 'hello';}},methods: {ping() {return `${this._f('hello')()} world`;}}
})
另外,在使用上filter支持链式调用,这为其增加了组合拼接的能力:
{{ name | normalize | capitalize }}
定义方式
最后需要指出,computed 属性只能在组件内部或通过mixins对象定义;而 filter 有两种定义方式,一是在组件内部通过 filters 属性定义;一是在组件外部通过 Vue.filter 函数定义:
Vue.component('HelloWorld', {filters: {hello() {return 'hello';}}
});
Vue.filter('hello', ()=> 'hello');
应用规则
综上,filter 无法缓存,调用频率高,因此特别适用于格式化输出场景,比如日期格式化。filter 具有组合调用能力,因此可以在项目架构层面定义一堆基础的、简单的filter,按需在组件内组合适用。
computed 属性具有缓存能力,在组件内普适性更强,因此适用于复杂的数据转换、统计等场景。
- 要用的属性不存在,要通过已有的属性(Vue实例上的data属性值)计算得来
- 原理:底层借助了Object.defineProperty方法提供的getter和setter
- 优势:与methods属性相比,computed内部有缓存机制(数据复用),效率更高,调试更方便
- 计算属性最终会出现在vm上,直接读取使用即可
- 如果计算属性要被修改,那必须写setter去响应修改,且setter要引起计算时依赖的数据发生变化
再延申一点,watch在deforeUpdated之前,先获取,再监听,然后再更新,再渲染