从零实现自己的vue框架

逻辑寻云使
• 阅读 119

1.准备工作

我们先利用webpack构建项目:

  • 初始化项目

    npm init -y

  • 安装webpack

    npm i webpack webpack-cli webpack-dev-server html-webpack-plugin --save

  • 配置webpack

    从零实现自己的vue框架

  • 配置package.json

    从零实现自己的vue框架

2 实现数据监听

2.1 创建构造函数MyVue

并初始化用户传入的参数options,我们先假设用户传入的options是只有data属性和el属性的。

从零实现自己的vue框架

从零实现自己的vue框架

到这里我们实现的是new MyVue的时候,通过_init方法来初始化options, 然后通过initData方法将data挂到vm实例的_data上去了

我们可以通过new MyVue来看下是否成功挂上去了
从零实现自己的vue框架
从零实现自己的vue框架
可见已经有了_data属性了

2.2 实现数据监听

想要实现数据双向绑定,就需要先实现数据监听,我们可以实现一个observe方法来实现数据监听

从零实现自己的vue框架

我们将vm.data通过Object.defineProperty 实现数据监听,
其中,我们将vm.data传入Observe的对象中,这个对象就是调用 Object.defineProperty 来实现数据监听的,Observe类定义如下
从零实现自己的vue框架

接下来我们打印vm看下,是否成功实现数据监听
从零实现自己的vue框架
打印发现_data中的属性message已经变成...说明成功(因为我们点击...的时候就会触发get())
但是这里会有一个问题,就是这里只实现了一层的数据监听,即如果data中有个对象属性的话呢?如下面的wife,现在只能监听到wife这一层,但是wife.name 和wife.age我们是监听不到变化的
从零实现自己的vue框架

2.3 解决多层级监听的问题

接下来我们实现多层级监听,要想监听到wife.name,需要用到递归
当我们判断 data中的某个属性是对象的时候(如wife),我们要调用observe,将wife放入到observe中实现监听wife的属性,因此我们在上面代码的基础上,添加上observe(value)就实现了递归监听

从零实现自己的vue框架

然后打印发现,wife的属性也实现了监听
从零实现自己的vue框架

但是到这里,还有一个问题,就是我们上面的data都是new MyVue的时候传进去的,因此要是我们再new 完 改变data的某个值,如下面将wife改成迪丽热巴,打印发现就没办法实现监听了

从零实现自己的vue框架

从零实现自己的vue框架

2.4 解决data中某个属性变化后无法监听的问题

我们知道 wife这个属性已经被我们监听了,所以改变wife的时候,会触发set()方法,因此我们只需要将wife再放进observe()中重新实现监听一遍即可,如代码所示
从零实现自己的vue框架

打印发现实现了监听

从零实现自己的vue框架

2.5 实现数据代理

我们用过vue的都知道,我们获取data中的属性的时候,都是直接通过this.xxx,获取值的,而我们上面只实现了想要获取值需要通过this._data.xxx,所以这一节来实现是数据代理,即将data中的属性挂载到vm上,我们可以实现一个proxy方法,该方法将传入的数据挂载到vm上,而当我们访问this.xxx的时候,其实是访问了this._data.xxx,这就是代理模式。
增加proxy后代码如下
从零实现自己的vue框架

打印发现,vm中已经有了data中的属性

从零实现自己的vue框架

至此,我们已经实现了数据监听,但是还有个问题,即Object.defineProperty的问题,也是面试常见的问题,即Object.defineProperty是无法监听数组的变化的

3 重写数组方法

如图所示,我们企图往数组arr中添加值,结果发现新添加进去的值是没办法被监听到的,因此,我们需要改写push等方法
从零实现自己的vue框架
从零实现自己的vue框架

基本思路就是之前我们调用push方法时,是从Aarray.prototype寻找这个方法,我们改成我们用一个空对象{} 继承 Aarray.prototype,然后再给空对象添加push方法

{
    push:function(){}
}

这样,我们调用push的时候,实际上就是调用上面{}中的push

现在,我们先区分出用户传入的Observe中接受监听的data是数组还是对象,如果是数组,则改变数组的原型链,这样才能改变调用push时,是调用我们自己设置的push,
只需要改Observe中
从零实现自己的vue框架

其中的arrayMethods则是我们一直说的那个对象{},它里面添加push等方法属性
从零实现自己的vue框架

现在,我们看下,调用push时是否调用了 对象{}(即arrayMethods)中的方法
从零实现自己的vue框架

可见已经调用了arrayMethods里的push,然后arrayMethods里的push再调用来原先原型链上的push
现在完善 arrayMethods里面的方法
从零实现自己的vue框架

打印下看看
从零实现自己的vue框架
从零实现自己的vue框架
发现新添加的属性成功实现了监听
但是,发现
从零实现自己的vue框架
这个初始化的时候的属性并没有监听到
所以在初始化的时候也要调用observerArray(data)
从零实现自己的vue框架
再打印,发现初始化的数组属性也成功实现了监听
从零实现自己的vue框架

4 实现渲染数据

基本介绍:
Watcher-->对应html中每一个表达式(即带有{{}})的
Dep -->对应data中每一个属性,如下图中,就要new 四个Dep,其中分别是message,wife,wife.name,wife.age各一个

从零实现自己的vue框架

将el节点挂载到vm上

通过mount方法将 将el节点挂载到vm上
从零实现自己的vue框架

实现一个compiler方法

接下来我们实现一个compiler方法,该方法将获得的el节点(dom树),将其遍历,然后把双括号表达式换成data中的数据,再把改变的dom树添加到el节点上
从零实现自己的vue框架

我们再在vm的原型上添加 _update方法,该方法执行了compiler方法,而—_update方法在mount 中将el挂载到vm实例上后执行
从零实现自己的vue框架

接着打印看是否实现,可见成功实现数据渲染
从零实现自己的vue框架
从零实现自己的vue框架

Wathcer实现渲染和更新(依赖收集)
基本介绍:
Watcher-->对应html中每一个表达式(即带有{{}})的
Dep -->对应data中每一个属性,如下图中,就要new 四个Dep,其中分别是message,wife,wife.name,wife.age各一个
问题:wacther什么时候生成? 答:是在compiler阶段 ,对每个{{}}生成一个watcher
问题:dep什么时候生成? 答:是在数据监听阶段 ,在defineProperty的时候生成,每个属性生成一个dep
综上可知,是先生成 dep,然后再有watcher,每生成一个watcher,就把这个watcher放入对应的dep,同时也把这个dep放进这个watcher

从零实现自己的vue框架

从零实现自己的vue框架

源码地址:https://github.com/peigexing/...

点赞
收藏
评论区
推荐文章
美凌格栋栋酱 美凌格栋栋酱
10个月前
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
放学路上 放学路上
4年前
vscode+vue简单安装教程
1、安装vscode、node.js。2、打开vscode终端,全局安装vuecli:npminstallgvuecli用于构建项目。3、继续安装webpack(打包工具):npminstallgwebpack。4、安装完成创建一个文件夹用于存放项目,比如myvue,cd到该文件夹,使用项目创建命令:vueinitwebpackmyvue。
代码哈士奇 代码哈士奇
3年前
webpack5构建一个简单的vue项目 (练习)
webpack5构建vue必要环境安装ndejs我们需要安装node如果没有安装则安装安装过则跳过执行nodevnpmv初始化项目文件夹新建一个空的项目执行npminity初始化npminity会生成一个package.json安装webpack以及htmlwebpackplugin控制台执行npmiwebpackwebpackcliwebpackdevserverhtmlwebpackpluginD安装babelloaderbabel可以将我们的代码向下
凯特林 凯特林
4年前
Vue 项目性能优化—实践指南
Vue项目性能优化—实践指南前言Vue框架通过数据双向绑定和虚拟DOM技术,帮我们处理了前端开发中最脏最累的DOM操作部分,我们不再需要去考虑如何操作DOM以及如何最高效地操作DOM;但Vue项目中仍然存在项目首屏优化、Webpack编译配置优化等问题,所以我们仍然需要去关注Vue项目性能方面的优化,使项目具有更高效
Souleigh ✨ Souleigh ✨
4年前
Vue 性能优化
前言Vue框架通过数据双向绑定和虚拟DOM技术,帮我们处理了前端开发中最脏最累的DOM操作部分,我们不再需要去考虑如何操作DOM以及如何最高效地操作DOM;但Vue项目中仍然存在项目首屏优化、Webpack编译配置优化等问题,所以我们仍然需要去关注Vue项目性能方面的优化,使项目具有更高效的性能、更好的用户体验。本文是作者通过实际
Easter79 Easter79
4年前
springboot+vue 登录页面(一)
首先了解的技术点是:后台:springboot,mybatis,mybatis逆向工程,mysql,日志前端:nodejs,npm,cnpm,vue,vuecli,webpack,elementui,router,axios开发工具:idea,webstorm该项目前端使用的是vue,目的是实现前后端分离后台:1.选择spr
Jacquelyn38 Jacquelyn38
4年前
React.js中JSX的原理与关键实现
在开始开发之前,我们需要创建一个空项目文件夹。安装1.初始化npm init y2.安装webpack相关依赖npm install webpack webpackcli D3.安装babelloader相关依赖npm install babelloader @babel/core @babel/presetenv D4.
Chase620 Chase620
4年前
面试官问 Vue 性能优化,我该怎么回答
前言Vue框架通过数据双向绑定和虚拟DOM技术,帮我们处理了前端开发中最脏最累的DOM操作部分,我们不再需要去考虑如何操作DOM以及如何最高效地操作DOM;但Vue项目中仍然存在项目首屏优化、Webpack编译配置优化等问题,所以我们仍然需要去关注Vue项目性能方面的优化,使项目具有更高效的性能、更好的用户体验。本文是作者通过
可莉 可莉
4年前
18个常用 webpack插件,总会有适合你的!
!(https://oscimg.oschina.net/oscnet/71317da0c57a8e8cf5011c00e302a914609.jpg)来源| https://github.com/Michaellzg/myarticle/blob/master/webpack/Plugin何为插