vue是当下最流行的前端框架,简单,易上手,使用场景丰富的特点,从刚学习vue到现在也有一年多了,期间从vue播放器,到个人网站,再到公司的一些vue项目,感觉对于vue的学习和了解也就是一些基本的操作。为了更深入了解vue的实现机制,开始学习和了解vue的源码。这也是基于 [Vue.js 技术揭秘](https://ustbhuangyi.github.io/vue-analysis/)
的学习
vue: 一款MVVM框架 核心思想: 数据驱动 特点:低耦合,易上手,环境搭建方便
以下是边看 Vue.js 技术揭秘 边总结的一点对于vue认识,只是为了加深对于vue的认识和了解
body
, html
vue 不允许挂载到body,html上 (提供的元素只能作为挂载点。不同于 Vue 1.x,所有的挂载元素会被 Vue 生成的 DOM 替换。因此不推荐挂载root实例到 或者 上。这是官方的解释)1
const mount = Vue.prototype.$mount
1
2
3
4
5
6
7
8
9
10
new Vue({
el: '.app',
data: {
info: '这是通过el属性获取挂载元素的outerHTML方式渲染。'
},
template: '<div>这是template属性模板渲染。</div>',
render: function(h){
return h('div', {}, '这是render属性方式渲染。')
}
})
render
方法里的内容 template
中的内容,且通过 compileToFunctions
来生成render方法getOuterHTML(el)
来设置模版,且通过 compileToFunctions
来生成render方法最后都会调用原先原型上的 $mount 方法挂载。
1
return mount.call(this, el, hydrating)
$mount 方法是定于在Vue.prototype上的方法
$mount 方法实际上会去调用 mountComponent
而 mountComponent
的核心作用就是
1
2
3
4
5
6
7
new Watcher(vm, updateComponent, noop, {
before () {
if (vm._isMounted) {
callHook(vm, 'beforeUpdate') // 如果已经是Mounted的状态, 则执行 beforeUpdate 的钩子函数
}
}
}, true /* isRenderWatcher */)
1
2
3
4
5
if (vm.$vnode == null) {
vm._isMounted = true
callHook(vm, 'mounted')
}
return vm
Vue 的 _render 方法是实例的一个私有方法,它用来把实例渲染成一个虚拟 Node
1
vnode = render.call(vm._renderProxy, vm.$createElement)
虚拟dom其实是一个VNode对象,是用JS对象记录一个dom节点的副本,当dom发生更改时候,先用虚拟dom进行diff,算出最小差异,然后再修改真实dom,通过递归的方式进行同级vnode的diff,最终实现整个DOM树的更新 Vue.js 中 Virtual DOM 是借鉴了一个开源库 snabbdom 的实现,然后加入了一些 Vue.js 特色的东西
通过Object.defineProperty()来劫持vue中各个属性的setter、getter 代码来源: vue面试常见问题小结
1
2
3
4
5
6
Object.defineProperty(obj, "newKey", {
get:function (){return ...} | undefined,//读取属性返回的值,即类似上面的value
set:function (value){ return ...} | undefined//设置属性的值
configurable: true | false
enumerable: true | false
})
结合发布订阅者模式
通过监听器Observer,用来劫持并监听所有属性,如果有变动的,就通知订阅者
通过订阅者Watcher,可以收到属性的变化通知并执行相应的函数,从而更新视图
通过解析器Compile,可以扫描和解析每个节点的相关指令,并根据初始化模板数据以及初始化相应的订阅器
-- 未完待续 --
✏️ 如有问题,欢迎指正