MVVM
M:model 模型
V:view 视图
VM:视图模型
传统的MVC模式数据是动态渲染的,但视图更新需要获取dom进行操作,性能不好;
MVVM模式新加了VM作为中间件,实现数据驱动视图,开发者更多的精力用于研究逻辑和数据,开发效率高,性能也好。
响应式原理
核心API:Object.defineProperty()
vue中data对象在初始化的时候,会添加get和set方法,当数据发生改变的时候,会触发更新视图的函数。
Object.defineProperty()缺点:
- 深度监听,需要递归到底,一次性计算量大
- 无法监听新增属性/删除属性(Vue.set Vue.delete)
- 无法原生监听数组,需要修改数组原型
vdom
vdom是js生成的对象,模仿的是dom结构,根据vdom去生成真实dom
dom如何转化成js对象
//html
<div id="box" style="color:red;">
<p>段落</p>
<ul>
<li style="font-size:20px;">标签</li>
</ul>
</div>
//js对象
{
tag: 'div',
props: {
style: 'color:red',id:'box' },
children: [
{
tag: 'p', children: '段落' },
{
tag: 'ul',
children: [
{
tag: 'li', props: {
style: "font-size:20px" },
children: '标签'
}
]
}
]
}
diff算法
虚拟dom和真实dom进行比较
- 只比较同一层级,不跨级比较
- tag不相同,则直接删掉重建,不再深度比较
- tag和key,两者都相同,则认为是相同节点,不在深度比较
模板编译
with
方法
- 改变{}内自由变量的查找规则,当作obj属性来查找
- 如果找不到匹配的obj属性,就会报错
- with要慎用,它打破了作用域规则,易读性变差
template模板通过vue中compiler方法解析成render函数,此函数会返回一串vnode,也就是虚拟dom,接下来使用diff算法和真实dom进行对比,将不同的节点进行替换。
//vue文件
import {
compile} from '../../node_modules/vue-template-compiler'
console.log(compile('<div>{
{text}}</div>'))
//with(this){return _c('div',[_v(_s(text))])}
初次渲染过程
- 解析模板为render函数(或在开发环境已完成,vue-loder)
- 触发响应式,监听data属性 getter,setter
- 执行render函数,生成vnode,patch(elem,vnode)
更新过程
- 修改data,触发setter
- 重新执行render函数,生成newVnode
- patch(vnode,newVnode)
hash路由
- hash变化会触发网页跳转,即浏览器的前进,后退
- hash不会刷新页面,SPA必需的特点
- hash永远不会提交的server端(前端自生自灭)
监听hash改变的函数
window.onhashchange=(event)=>{}
JS修改url
location.href=##
history路由
- 用url规范的路由,但跳转时不刷新页面
- 添加路由:history.pushState 浏览器不会刷新页面
history.pushState(state,'','pageName')
- 监听浏览器前进,后退:window.onpopstate=(event)=>{}