vue响应式的理解(个人心得。。很乱,也就只有我自己看得懂了)
自己看了很多的文档的读书笔记,也还没整理好。。。。。
先说明一点每一个组件其实就是vue的实例 每一个组件内部都有一个watcher的实例 每一个watcher实例都有更新渲染dom节点的update方法 dep的实例保存着很多watcher实例
创建一个组件或者vue的实例过程中执行以下步骤: 搭配官网生命周期图食用
2. vm._self = vm 3. /*初始化生命周期*/ 4. initLifecycle(vm) 5. /*初始化事件*/ 6. initEvents(vm) 7. /*初始化render*/ 8. initRender(vm) 9. /*调用beforeCreate钩子函数并且触发beforeCreate钩子事件*/ 10. callHook(vm, 'beforeCreate') 11. initInjections(vm) // resolve injections before data/props 12. /*初始化props、methods、data、computed与watch*/ 13. initState(vm) 14. initProvide(vm) // resolve provide after data/props 15. /*调用created钩子函数并且触发created钩子事件*/ 16. callHook(vm, 'created') 17. 18. /* istanbul ignore if */ 19. if (process.env.NODE_ENV !== 'production' && config.performance && mark) { 20. /*格式化组件名*/ 21. vm._name = formatComponentName(vm, false) 22. mark(endTag) 23. measure(`${vm._name} init`, startTag, endTag) 24. } 25. 26. if (vm.$options.el) { 27. /*挂载组件 内部创建一个watcher实例 */ 28. vm.$mount(vm.$options.el) 29. }
1初始化事件函数以及初始化生命周期函数 初始化render函数
事件函数就是 on emit once这些事件 声明周期函数就是 created啊 beforecreated这种
执行完成之后执行beforeCreated钩子
2 初始化状态 初始化注入值
其中初始化状态中执行了这么一些方法 看图
首先通过proxy方法(原理还是Object.defineProperty) 对data中的值进行代理
第二 通过observer方法中的defineReactive 对data中的数据重写get set方法
然后在get方法中进行了依赖收集 判断当前的Dep.target(就是当前实例的watcher对象)是否存在 存在的话吧watcher丢进dep.的sups中 还有set方法先不说
Dep类(发布者)
执行完成之后执行Created钩子(这时候可以访问data属性和以及一些方法)
3 判断当前实例是否含有el属性 如果有的话会再次判断是否有template属性 有的话把template编译成render函数 --- 没有el的话 等到组件注册调用才会调用mount方法
------------执行beforeMounted方法 这时候可以获取生成的虚拟dom vndom但是因为没有挂载 所以是无法获取dom结构的
4 执行$mount.方法 这个方法是干嘛的呢! 非常重要
回到get 方法 get方法 干了什么呢
先说明一点 在对每一个data中的属性进行getset方法绑定的同事 内部定义了一个dep实例(什么意思呢 就是可以说每一个data中的属性都有一个dep实例) get方法中先判断是否有dep.target 上面new watcher 把当前的实例watcher赋值给了dep.target 所以也就是把需要相应更新的watcher实例push进了subs中 这就进行了依赖收集
------------如果是第一次更新的话执行Mounted生命周期钩子 如果是之后修改值触发set操作执行beforeUpdate生命周期钩子(内部有一个标示量进行判断 执行了mounted赋值为true) 这时候可以获取dom结构 已经进行了挂载了
这时候修改值 然后触发set操作的时候会调用dep实例的notify方法 然后循环里面所有的watcher订阅者进行update方法—update方法会重新生成一个rendertree然后通过diff算法计算需要渲染的节点重新渲染
大佬们的图解释