组件通信
父子通信: props\emit, $ parent和$ children对象来访问组件实例中的方法,
跨层级组件通信: provide/inject
任意组件:Vuex\EventBus
computed和watch区别
computed是计算属性,依赖其他属性计算值, 并且computed的值有缓存,只有当计算值变化才会返回内容
watch 监听到值的变化就会执行回调,在回调中可以进行一些逻辑操作
所以一般来说依赖别的属性动态获得值的时候可以使用computed,对于监听到值的变化需要做一些复杂业务逻辑的情况可以用watch
keep-alive
切换组件防止状态多次渲染,用keep-alive包裹需要保存的组件,被包裹的组件在切换时不会进行销毁,而是缓存到内存中执行
组件中data什么时候可以使用对象
一般data都是函数,防止一个组件影响别的组件
当使用new Vue()方式的时候,无论将data设置对象还是函数都是可以的,因为new Vue()的方式是生成一个根组件,该组件不会复用,也就不存在共享data的情况了
object.defineProperty缺陷
通过下标方式修改数组数据或者给对象新增属性并不会出发组件的重新渲染
编译过程
vue会通过编译器将模版通过几个阶段最终编译为render函数
- 将模版解析为AST,通过各式各样的正则表达式匹配模版中的内容,然后提取出来做逻辑,生成一个最基本的AST对象
{// 类型 type: 1, // 标签: tag, // 属性列表 attrsList: attrs, // 属性映射 attrsMap: makeAttrsMap(attrs), // 父节点 parent, // 子节点 children: [] }
,同时要判断开闭标签是否一致,根组件是否只存在一个,是否符合HTML5 - 优化AST
- 将AST转换为render函数
路由原理
history路由
html5推出的新模式,用history的popState和history.replaceState改变URL
hash路由
当#号后面的值发生变化了,可以通过hashChange方法监听到url的变化,从而进行页面跳转,hash模式相对来说更简单,且兼容性更好
对比
- hash模式只可以改变#号后面的内容,history模式可以通过api设置任意同源的url
- history可以用api添加任意类型的数据到历史记录里,hash模式只能改变hash值,也就是字符串
- hash模式无需后端配置,而且兼容性好。history模式在用户手动输入地址或者刷新页面的时候会发起请求,后端要通过设置index.html页面用于匹配不到静态资源的时候
Vitural dom
本来完整比较两棵二叉树复杂度为o(n^3),但是优化后变成了o(1)
关键是只对比同层的,而不是跨层对比,因为实际业务中也很少跨层对比
- 首先从上往下,从左往右遍历对象,也就是树的深度遍历,这一步中会给每个节点添加索引,便于最后渲染差异(需要判断tagName,如果不同就代表被替换了)
- 一旦节点有子元素,就去判断子元素是否不同(需要判断节点是否有移除,是否有加入,是否有移动)
通过key来给节点打标记,用于判断是否是同一个节点