1.课程目标
实现vue
模拟一个最小版本的Vue
响应式原理在面试的常见问题
学习别人优秀的经验,转换成自己的经验
给Vue实例细则一个成员是否是响应式的
给属性重新赋值成对象,是否是响应式的
为血虚vue源码做准备
2.数据驱动
数据驱动
数据响应式
数据模型普通的js对象 当我们改变数据 识图会自动更新 避免繁琐的DOM操作 提高开发效率
双向绑定 数据 视图 互相都会改变 v-model在表单元素上创建双向数据绑定 数据驱动:vue 最独特的特性之一 开发过程中仅需要关注数据本身,不需要关心数据是如何渲染到视图的
3.数据响应式核心原理
vue2.x
对vue中的data 和实例
OBJ.defineProperty es5新增 数据劫持 代理整个对象
对象
属性赋值
属性描述符
get 里面没有入参
属性值发生变化 放入data中 放入dom中 多个属性怎么同时改 循环将属性遍历 并且调用Object.defineProperty()
4.数据响应式核心原理
vue3.x
Proxy 针对性修改属性 属性由系统传递 提高浏览器性能
es6新增 ie不支持
5.发布/订阅模式
发布/订阅模式
订阅者 家长 on
发布者 老师 emit
信号中心 班级
vue的自定义事件 vue的实例 $on 事件名称 事件处理函数 订阅者 $emit 触发 发布者 手写事件触发器 类 存储事件 键值对 对应 名称 和 函数方法 注册事件 的方法 $on 后注册的函数方法会加到后面去 触发事件 的方法 $emit
6.观察者模式
观察者 watcher
update 方法
发布者 Dep
subs 存储观察者
addSub 添加观察者
notify 调用观察者的update方法
区别 目标触发事件通知订阅者 订阅事件 通过事件中心转换 去除发布者和订阅者之间的依赖
7.模拟Vue响应式原理
熟悉vm对象 vue实例
属性 set/get 方法
$data _data
$el
$options
Vue ----》 Observer 数据劫持 ----》Dep 发布者 Compiler 解析指令 ----》观察者《------|
8.Vue
功能
1.接收初始化的参数
2.把data中的属性注入Vue实例,转换成 getter/setter
3.负责调用observer监听data中的所有属性的变化
4.负责调用compiler解析指令/差值表达式
结构 类图 $options $el $data _proxyData enumerable: true, 可枚举 configurable: true, 可遍历 get() set()
9.Observer 数据劫持 监听data中数据的变化并进行处理
功能
data选项中的属性 转化成响应式数据
data的某个属性也可以转换成响应式数据
数据变化发送通知 set方法
方法 walk(data) 遍历对象的所有属性 defineReactive(obj,key,val) 把属性转化成get set
10.observer.defineReactive
直接穿 obj[key]死递归 为什么
get 发生了闭包 没有释放掉val属性
1.data中的对象属性也要转化为响应式数据 在 defineReactive 里面调用 walk 再进行一次判断obj 2.data重新赋值新的对象的时候 也要转换成响应式数据
11.Compiler 操作DOM
功能
1.负责编译模板,解析指令/差值表达式
2.负责页面的渲染
3.当数据变化时重新渲染
结构 el dom对象 vm 实例 方法 complie(el) 遍历dom对象的节点 编译模板,处理文本节点和元素节点 isTextNode 判断节点是否是文本节点 compileText(node) 编译文本节点,处理差值表达式 node.nodeType === 3 取值为 node.textContent isElementNode 判断节点是否是文本节点 compileElement(node) 编译元素节点,处理指令 node.nodeType === 1 node.attributes 遍历属性节点是否时属性 isDirective 判断元素属性是否是指令 指令开头为 v- .startsWith() 以什么开头
12.响应式数据
Dep 发布者
收集依赖,添加观察者
通知所有观察者
结构 subs 观察者们 addSub 添加观察者 notify 通知所有观察者 watcher 观察者 功能 数据变化触发依赖,dep通知watcher实例更新视图 自身实例化的时候往dep对象中添加自己 结构 vm key data中的属性名称 cb callback 回调函数 如何更新视图 oldValue update() 可以拿到最新的值 将dep.target 记录watch实例 先给dep.target赋值 在访问属性的时候会调用get方法 get方法中会将dep.target添加到dep 中 添加完 清空 防止重复
13.创建watcher对象
引入文件顺序很重要
先引入dep 才可以引入watcher
处理文本节点的时候 创建watcher对象
处理指令节点的时候 创建watcher对象
14.双向绑定
数据变化 更新视图
视图变化 更新数据
给表单元素 即 model节点绑定inpit事件
重新赋值 相当于 更新数据 更新数据触发 响应式数据 带动视图变化 形成一个闭环
15.首次渲染
实例化watcher的时候生成了 Dep.target
16.数据改变
notify
update
对watcher的cb执行
cb为实例化watcher的时候的回调函数
17.总结-问题
1.给属性重新赋值成对象,是否是响应式的?
是的,会遍历子节点
2.给Vue实例新增一个成员是否是响应式的? 不会,初始化的时候才会调用 observer 类 可以使用Vue.set(obj,propertyName,Value) this.$set(obj,propertyName,Value)
18.总结
new vue对象
新建observer 建立get/set 通知变化给 Dep
发送通知给watcher 添加订阅者
新建compiler 解析指令 实例化+回调函数 watcher
更新视图