dave-wind / blog

native javascript blog
0 stars 0 forks source link

vue props $emit $on 原理 #7

Open dave-wind opened 1 year ago

dave-wind commented 1 year ago

props 原理

伪代码思路

==> ast语法树 ===> vnode虚拟节点 ===> 真实dom;

// 生成组件虚拟节点过程: function createElement(vm, tag, data = {}, ...children) { if(原生组件) { return vnode(xxx) }else { // vm是实例,在实例上的$options方法上找到子组件的定义 let Ctor = vm.$options.components[tag]; // 通过构造函数 去创建组件 生成虚拟节点 return createComponent(vm, tag, data, key, children, Ctor) } } // 传递参数 生成虚拟节点;Ctor 为组件构造函数 const vnode = new Vnode(vue-component-${Ctor.cid}-${tag}, data, key, undefined, undefined,{ Ctor, children, propsData, // 这就是props,propsData 都是从上到下传递, 其实就是options里传来的props; });

// 组件紧接着需要初始化: function initInternalComponent(vm:Component) { const opts = vm.$options = Object.create(vm.constructor.$options) // 永远继承于父级的构造函数;挂载在vm.$options实例上 var vnodeComponentOptions = parentVnode.componentOptions; opts.propsData = vnodeComponentOptions.propsData; // 虚拟节点options的 props 混合定义到了 options上

} // 最后初始化属性 function initProps(vm,propsOptions) { const options = vm.$options.propsData || {} // 如果是根元素 不需要做响应式 if(!!vm.$parent) { toggleObserving() } // 循环遍历 用户 传进来的 props var props = vm._props = {}; for (let key in propsOptions) { // 做校验 得到value const value = validateProp(key, propsOptions, propsData, vm);

// 对key 做响应式 defineReactive(props, key, value) // 如果没有定义在prototype实例上 把 _props 定义到实例上, if (!(key in vm)) { proxy(vm, "_props", key); } }

} 总结就是 父组件传递到子组件的propsData 属性 重新定义在组件实例上