Vue 源码之 computed 和 watch

学如逆水行舟,不进则退!当今社会,很美好,也很残酷。一般软件或互联网公司,大多数的业务其实是没有很高的难度,所以员工也没有什么机会去提升自己。不过值得庆幸的是,编程界开源风气盛行,功夫秘籍随手可得,而代价仅是你的时间。本次文章的主题是 computed(计算属性) 和 watch(侦听器),代码基于 Vue 2.6.11 版本,和 2.5 还是有一些区别。用法回顾我们先来简单回顾下 computed 和 watch 的用法。computedexport default { name: .
摘要由CSDN通过智能技术生成

学如逆水行舟,不进则退!当今社会,很美好,也很残酷。一般软件或互联网公司,大多数的业务其实是没有很高的难度,所以员工也没有什么机会去提升自己。不过值得庆幸的是,编程界开源风气盛行,功夫秘籍随手可得,而代价仅是你的时间。

本次文章的主题是 computed(计算属性) 和 watch(侦听器),代码基于 Vue 2.6.11 版本,和 2.5 还是有一些区别。

用法回顾

我们先来简单回顾下 computed 和 watch 的用法。

computed

export default {
   
    name: 'App',
    data() {
   
        return {
   
            user: {
   
                name: 'Jack',
                job: 'UI',
            },
        };
    },
    computed: {
   
        name() {
   
            return 'I am ' + this.user.name;
        },
    },
};

在 computed 属性中,我们定义了 name,其值来自 data 中 user.name。只要 user.name 的值发生了变化,那么 computed 中的 name 就行改变。

定义 computed 的好处就是我们可以定一个变量,很方便引用“其它的对象数据封装处理”后的值。并且 computed 中的属性是响应式的,值改变了,会触发 DOM 的更新。如果依赖的值没有改变,computed 的值不会重新计算,而是复用上一次缓存的值。

watch

export default {
   
    name: 'App',
    data() {
   
        return {
   
            color: 'red'
        };
    },
    watch: {
   
        color(newVal) {
   
            alert('Color is changed', newVal)
        }
    }
};

computed 主要关注的是值改变后的新值和缓存功能,而 watch 主要关注值改变后,我要做什么动作。

源码分析

如果读者从来没有阅读过 Vue 相关的源码,接下来的内容可能有点云里雾里。博主会尽量把内容放在 computed 和 watch 这一块的流程上,辅助少量的其他模块的细节。

computed

Vue 在初始化时,会执行 _init,该方法在 Vue 原型对象上定义的。

Vue.prototype._init = function (options?: Object) {
   
  const vm: Component = this

  // 省略了一大波细节

  // expose real self
  vm._self = vm
  initLifecycle(vm)
  initEvents(vm)
  initRender(vm)
  callHook(vm, 'beforeCreate')
  initInjections(vm) // resolve injections before data/props
  initState(vm)
  initProvide(vm) // resolve provide after data/props
  callHook(vm, 'created')

  if (vm.$options.el) {
   
    vm.$mount(vm.$options.el)
  }
}

这个方法里面有执行一个函数 initState(vm) ,包含如 data、computed、watch 等属性的处理逻辑。

export function initState (vm: Component) {
   
  vm._watchers = []
  const opts = vm.$options
  if (opts.props) initProps(vm, opts.props)
  if (opts.methods) initMethods(vm, opts.methods)
  if (opts.data) {
   
    initData(vm)
  } else {
   
    observe(vm._data = {
   }, true /* asRootData */)
  }
  if (opts.computed) initComputed(vm, opts.computed)
  if (opts.watch && opts.watch !== nativeWatch) {
   
    initWatch(vm, opts.watch)
  }
}

从上面代码中,我们在最后几行代码可以看到 computed 和 watch 的处理。顺便一提,这里的 nativeWatch 判断主要是用来处理火狐浏览器上的一个兼容性问题,火狐浏览器中其默认对象的原型上有一个原生的 watch 属性。

我们先来看看 initComputed() 这个方法。

function initComputed (vm: Component, computed: Object) {
   
  // $flow-disable-line
  const watchers = vm._computedWatchers = Object.create(null)
  // computed properties are just getters during SSR
  const isSSR = isServerRendering()

  for (const key in computed) {
   
    const userDef = computed[key]
    const getter = typeof userDef === 'function' ? userDef : userDef.get

    if (
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值