写在前面
vue3 马上要来了,vue2 学会了吗?
最近看到了不少类似标题的文章,虽然 vue 的双向绑定、虚拟dom、diff算法等等面试常见问题你可能在几年前就学过了,不过让从零开始实现一个 vue,你可以吗。
本着学习的最好方法就是自己实现一次
的原则,趁着疫情无法返校,计划实现一个尽量完整的 vue,删掉了 flow 和很多的类型判断,只保留各功能的主流程,旨在为直接阅读 vue 源码提供过渡。
毕竟 vue 源码还是比较难啃的,看网上的文章也很难将各个模块联系起来。跟着我先搭起整个框架,然后一个功能一个功能的实现 vue 的主流程,抛开 flow 和类型判断,专注于源码的实现原理,是从小白到直接阅读源码之间一个很好的过渡。
仅供学习交流使用,觉得看文章太慢的可以直接看源码:https://github.com/buppt/YourVue
本篇文章是从零实现 vue2 系列第一篇,vue 主流程实现,先不要管双向绑定、虚拟dom 等等,后面会一点一点加上来。
正文
我们按照 vue 的方式,实现功能,一个数字和一个按钮,点击按钮数字加一。
// main.js
import YourVue from './instance'
new YourVue({
el: '#app',
data: {
count: 0,
},
template: `
<div>
<div>{
{count}}</div>
<button @click="addCount">addCount</button>
</div>
`,
methods:{
addCount(){
const count = this.count + 1
this.setState({
// 没有双向绑定,先通过setState更新
count
})
}
}
})
实现
首先初始化一个 class,这里需要关注的问题有三个
- 第一个是如何实现 data 和 methods 中的变量通过 this 直接访问
- 第二个如何将 template 模版转换成 dom 元素
- 第三个是如何将事件绑定到 dom 元素上面
先上 YourVue 定义。
export default class YourVue{
constructor(options){
this._init(options)
}
_init(options){
this.$options = options
if (options.data) initData(this)
if (options.methods) initMethod(this)
if (options.el) {
this.$mount()
}
}
$mount(){
this.update()
}
update(){
let el = this