1:浏览器真实渲染DOM的过程
1:解析 HTML 构建 DOM(DOM 树),并行请求 css/image/js
2:CSS 文件下载完成,开始构建 CSSOM(CSS 树)
3:CSSOM 构建结束后,和 DOM 一起生成 Render Tree(渲染树)
4:布局(Layout):计算出每个节点在屏幕中的位置
5:显示(Painting):通过显卡把页面画到屏幕上
2:虚拟DOM的概念-尽可能少的操作真实DOM
1:当用原生js或者jq去操作真实DOM的时候,浏览器会从构建DOM树开始
从头到尾执行一遍流程,当操作次数过多的时候,之前计算DOM节点坐标值
等都是白白浪费的性能,虚拟DOM因此产生了
2:Virtual DOM 其实就是一棵以 JavaScript 对象(VNode 节点)作为基础的树,
用对象属性来描述节点,实际上它只是一层对真实 DOM 的抽象。
最终可以通过一系列操作使这棵树映射到真实环境上
。由于 Virtual DOM 是以 JavaScript 对象为基础而不依赖真实平台环境,所以使它具有了跨平台的能力,
比如说浏览器平台、Weex、Node 等。
3:虚拟DOM的好处
假设一次操作中有10次更新DOM的操作的动作,虚拟DOM不会立即操作DOM,而是将这十次更新的diff内容保存到本地的一个js对象中,最终将这个js对象一次性attach到DOM树上,在进行后续操作,避免了大量无谓的计算量,所以,用js对象模拟DOM节点的好处是,页面的更新可以先全部反应在虚拟DOM上,操作内存中的js对象的速度显然要更快,等更新完成,再将最终的js对象映射成真实的DOM,交给浏览器去绘制
对比真实DOM的工作流程
<div>
<h1>My title</h1>
Some text content
<!-- TODO: Add tagline -->
</div>
当浏览器去解析这段html代码时,它会创建一个DOM节点树来保持追踪所有内容
3:DOM更新时机
<el-button @click="btnText">{{text}}</el-button>
btnText(){
this.text + = 1;
}
如果我连续十次点击按钮,每次都要在text的基础上加1,如果我连续点击了100次,虚拟DOM如何更新?
4:梳理一个vue实例对象的工作流程
Vue-cli 生成的项目中,<template> 标签中的内容都会被编译为 render 函数,
render 函数返回整棵虚拟节点树
<template>
<el-button @click="changeText">{{text}}</el-button>
</template>
<script>
export default {
name: 'bookList',
data() {
return {
text: 'htllo'
}
},
methods: {
changeText() {
this.text += 1;
}
}
}
</script>
// 一个vue的单页面,简单的执行流
==>初始化生命周期
==>初始化事件系统
==>初始化state,依次处理 props、data、computed …
==>开始渲染 _mount() => _render() 返回 vdom=> _update() => __patch__() 更新真实DOM
<html>
<head>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<button @click="changeText">{{text}}</button>
</div>
</body>
<script type="text/javascript">
var vm = new Vue({
el:'#app',
data(){
return {
text: 'hello'
}
},
methods: {
changeText(){
this.text = this.text+1
}
}
})
console.log('this', this)
</script>
</html>
// 当一个vue实例被创建时,它将data对象中所有属性加入到vue响应系统中,
这些属性的值发生改变时,视图将会产生响应,即匹配更新为新的值
//初始化之后调用 $mount 会挂载组件,如果是运行时编译,
即不存在 render function 但是存在 template 的情况,需要进行「编译」步骤。
//会有一个虚拟DOM生成真实DOM的过程
// 我们已经执行完了vm._render方法拿到了VNode,现在将它作为参数传给vm._update方法并执行。vm._update这个方法的作用就是就是将VNode转为真实的Dom,不过它有两个执行的时机:
1:首次渲染
当执行new Vue到此时就是首次渲染了,会将传入的VNode对象映射为真实的Dom。
2:更新页面
数据变化会驱动页面发生变化,这也是vue最独特的特性之一,数据改变之前和之后会生成两份VNode进行比较,而怎么样在旧的VNode上做最小的改动去渲染页面
5:虚拟DOM与真实DOM之间的爱恨情仇
虚拟DOM其实是使用Javascript对象来对真实DOM的一个描述。
<div id="app" class="wrap">
<h2>hello</h2>
</div>
可以在render函数内部这样描述它
new Vue({
render(h){
return h('div', {
attrs: {
id: 'app',
class: 'wrap'
}
},[
h('h2', 'hello')
])
}
})
// render函数使用的是参数h方法并用VNode这个类来实例化它们
真实的元素节点:
<div>
hello
<span>Vue!</span>
</div>
VNode描述:
{
tag: 'div',
children: [
{
text: 'hello'
},
{
tag: 'span',
children: [
{
text: Vue!
}
]
}
],
}
// 开始挂载阶段
//如果用户有传入el属性,就执行vm.$mount方法并传入el开始挂载