DOMcontentLoaded 是指 html文档加载和解析完成,html加载和解析的过程中会解析css,因此在加载的过程中会行程dom树和css渲染树 如果在html中嵌入js文档 js脚本会阻止浏览器的渲染 js如果是内联 则会先执行js文件 js如果是外链接 则只会等待js加载 DOMcontentLoaded 不需要等待图片等其他资源加载完成
load事件:页面上所有的资源(图片 视频 音频)被加载完成以后才会触发load事件
vue初始化将data返回的数据 for in 遍历 通过Obejct.defineProperty 将data返回的对象内每个数据都进行响应式定义变成可以观察的
vue proxy 将vue._data[key]转换到vue[key]上
funcrion proxy(data){ const that = this; Object.keys(data).forEach(key => { configurable: true, enumerable: true, get: function proxyGetter(){ return that._data[key] }, set: funcrion getProxyGetter(val){ that._data[key] = val; } }) }
这样就能代替 that._data[key];
类的所有方法都是挂载在类的 prototype上
constructor 方法是类的默认方法 在new命令生成对象实例的时候 自动调用该方法。一个类必须有 constructor 方法 如果没有显示定义 则默认创建 默认返回this 完全可以指定返回其他的对象
static静态方法不会被 new新建的实例继承 子类必须在 constructor中调用super方法 因为子类自己的this对象 必须先通过父类的 构造函数完成塑造 得到与父类同样的实例属性和方法 ,然后加工加上子类的属性和方法 不调用super报错referrence error
super在静态方法指向父类 this调用父类作用域的方法和属性 在普通方法中指向父类的原型
如果在代码内定义的数据 没有运用到 根据之前的挂载规则 凡是对数据定义 就会触发set回调 当模板未用到该变量的情况下 会造成多余不必要的渲染刷新
所以需要制造一个依赖收集的集合 对模板使用到的变量进行收集 选择性的更新视图 在页面最开始的时候进行一次render 这样就能对模板依赖的变量进行取值 从而触发get 在此时将模板上的变量放进依赖集合sub内
observe返回一个可以观察的Observe实例对象 传入一个对象参数和asRootData 通过_ob_的属性来挂载data对象 所需要的observe实例 通过instanceOf判断value.ob.instanceof Observer判断是否已经创建了实例 通过严格的校验确保data是单纯的对象 然后创建
if (hasOwn(value, '__ob__') && value.__ob__ instanceof Observer) {
ob = value.__ob__
} else if (
/*这里的判断是为了确保value是单纯的对象,而不是函数或者是Regexp等情况。*/
observerState.shouldConvert &&
!isServerRendering() &&
(Array.isArray(value) || isPlainObject(value)) &&
Object.isExtensible(value) &&
!value._isVue
) {
ob = new Observer(value)
}
Vue的响应式数据(这里需要双向相应的data对象)都会有一个_ob_属性,存放了该属性的观察器 Observer函数创造的实例 防止重复绑定
函数Obeserver,遍历传入的纯对象 对对象的数据属性进行双向绑定 class组件 编译过后就是es5的构造函数
对数组做了区分处理 如果是数组 则将数组的每个成员都一一进行 数据绑定 如果是纯对象的话 则对对象进行Objec.keys进行数组遍历,获得所有属性的数组 遍历 进行defineReactive(obj, keys[i], obj[keys[i]]) export class { value: any, //依赖收集 dep: Dep, //作为记录root data的数字 vmCount: 0
//es6初始化执行构造函数
constructor(){
//将observe实例挂载到value的_ob_属性上
def(value, '__ob__', this);
//判断是数组还是纯对象
//如果是数组的话 对数组内的数据进行一一响应化
if (Array.isArray(value)){
//数组是否支持原型属性 支持的话直接进行数据方法覆盖
const agument = hasProto ? protoArgument: copyAugument
agument(value, arrayMethods, arrayKeys);
this.observeArray(value)
}else{
this.walk(value)
}
}
//定义构造函数类 拥有的方法
walk(obj: Object){
//属性数组
const keys = Object.keys(value);
for (ket i = 0; i< keys.length; i++){
//对data的属性一一defineProperty
defineReactive(value, keys[i], value[keys[i]]);
}
}
observeArray(items: Array<any>){
for (let i = 0; i < items.length; i++){
observe(items[i]);
}
}
//如果是修改一个数组的成员,这个成员是一个对象,那就只需要对数组的成员对象进行绑定即可
但是如果对这个数组 进行数组操作 push pop shift unshift splice sort reverse 的时候 成员对象是没有被加入可观察的 所以vue重写了这七个方法 pop push shift unshift splice sort reverse
覆盖原型的方法
funcrion protoArgument(target, src: Object){
target.__proto__ = src;
}
funcrion copyAgument(target: Object, src: Object, keys: Array<string>){
for (let i = 0;i< keys.length; i++){
const key = keys[i];
def(target, key, src[key])
}
}
Observer负责将数组或者需要观察的对象 变为被观察监听的
通过覆盖数组原型的__proto__来对数组对象进行覆盖
伪代码:
//新建proto对象覆盖
const arrayProto = Object.create(arrayProto);
['splice', 'shift'].forEach(funcrion(method){
const originMethod = arrayProto[method];
//新建proto对象覆盖
def ()
//对数组元素监听化
ob.observeArray(inserted);
//notify 通知
ob.dep.notify();
})
//建立watcher
export default class Watcher{
//es6组件继承参数 格式验证
vm: Component;
cb: Function;
dirty: Boolean;
//dep
deps: Array<Dep>;
newDeps: Array<Dep>;
depIds: ISet,
newDepIds: Iset,
getter: Function,
value: any,
//初始化函数
constructor(
vm: Component,
expPrFn
)
}
2.VUE事件机制 $on $once $emit $off