手把手教你从零写一个简单的 VUE
本系列是一个教程,下面贴下目录~
1.手把手教你从零写一个简单的 VUE
2.手把手教你从零写一个简单的 VUE--模板篇
今天给大家带来的是实现一个简单的类似 VUE 一样的前端框架,VUE 框架现在应该算是非常主流的前端数据驱动框架,今天我们来从零开始写一个非常简单的 VUE 框架,主要是让大家知道最核心的 vue 部分是怎么运转起来的。包括数据绑定,模板处理,以及页面渲染,数据驱动视图等几个部分,代码在文章末尾给出来,下面我们开始~
VUE 是怎么运转起来的
在正式动手之前,我们先来了解下 vue 是怎么运转起来的,vue 从核心来说,是一个通过数据去驱动页面渲染的框架,也就是说通过改变数据的状态,可以控制页面中渲染的逻辑,比如展示数据,切换样式,这些的核心都是通过对数据改变的监听,从而将数据发生改变的对应的视图进行更新渲染,这是整个框架的核心运行机制。因此我们制作的简单 vue 框架,主要是围绕着怎么监听,怎么渲染,怎么更新这个流程去做的,旨在让大家知道 vue 怎么跑起来的,其余的 vue 组件,指令,插件等内容将在后面的文章中写出。
设计
首先我们要知道我们要做一个简单数据驱动视图前端框架,它包括以下几个部分:
- 能够编译简单的模板
- 能够监听数据变化
- 数据变化的时候,能够关联对应的视图并同步的更新视图
根据上面列举的需求,我们需要程序抽象以下几个部分:
- 存储数据的
$data
,用于保存数据,渲染视图 - 与每个模板对应的
Node
对象,对象包含对应模板的渲染函数,还有渲染函数需要使用的数据集合 - 对数据进行监听关联的
Watcher
类,用于关联数据和对应的模板,监听数据变化
开始编码
首先介绍下项目用的工具及框架,项目使用rollup
进行项目模块化构建,使用ES6
进行编码。下面开始正式编码。
首先我给框架起了个简单的名字,叫QV
,这个对象会暴露到全局中,进行实例化,实例化代码如下:
在实例化的时候传给了对象 el
、template
、data
等数据,其中el
是模板在页面的挂载点,template 是获取模板的选择器,分别对应body
的<app></app>
标签和script标签中的模板,data 是定义的数据对象。
数据处理
在QV
类的构造函数中,我们会对传入的配置进行处理,首先我们会对数据进行格式化,使得其在被Watcher
正常监控。格式化数据的代码如下:
可以看到formatData
方法在原来的data
上面又挂载了一个_od_
属性,然后将原始数据进行格式化,每个数据分别包含value
(数据值),linkNodes
(被使用的节点值),mounted
(是否已经被格式化过),通过对数据进行预处理,方便后面的数据监控绑定
模板节点处理
模板的能力是一个前端框架的重要组成部分,vue
将模板转化为AST
(抽象语法树),然后去解析其中的语法,比如{{}}
、v-for v-if
等等,模板解析的总体思路如下:
- 将模板字符串通过正则表达式等方法进行切割,切割点为模板定义的关键字
- 将切割完的字符串进行分析,可以生成
AST
(抽象语法树)或者是直接进行处理操作 - 将分析完的东西进行字符串拼接,通过
new Function
生成模板函数
本例子只做流程的说明,所以模板很简单,只有赋值语法,如下:
可以看到模板中只有{{}}
的赋值语法,插入变量为a、sdf、ccc
的语法
那么这个是怎么进行解析的呢,代码如下:
下面重点讲一讲这个函数,可以看到函数的开头定义了一个正则表达式 /{{[ \t]*([\w\W]*?)[ \t]*}}/g
,用于匹配和分割用{{}}
界定的变量,通过 exec
的运行,匹配出来的结果如下:
可以看到a,sdf,ccc
都被匹配出来了,然后通过slice
进行分割后重建,变成一段模板函数字符串,如下:
然后再通过new Function
将上面的字符串变成一个函数,方法如下
其中的new Function("od",$t)
中的od
是这个函数的参数,可以在函数中使用
最后生成的模板函数如下:
这样子就完成了模板函数的开发,而且还将模板用的变量进行抽取,标记这个模板用到了哪些变量
监听器
监听器作为连接数据和视图更新的纽带,是vue
的核心部分,vue
是使用Object.defineProperty
对数据进行处理后实现数据监听的,本程序也是使用这个核心方法进行数据监听的,核心代码如下:
下面我具体说下这段代码:
之前格式化数据的时候在原始数据里面添加了_od_
字段,是用在数据监控时候的,Object.defineProperty
可以设置get set
属性,分别在对应的数据被获取或者被修改的时候会进行回调,因此如果直接操作原始数据,会导致监控程序发生死循环,因此通过_od_
的拷贝数据进行操作,能够避免这种情况,可以看到get
函数会直接返回_od_
里面对应属性的value
,而set
函数我做了一个优化节流,对于连续修改数据只发生一次更新,将使用到这个数据的Node
对象进行update
操作
程序最核心的方法已经开发完成了,演示下结果,直接打开页面,可以看到下面的视图
可以看到程序将数据a sdf ccc
赋值给模板,然后替换页面的app
节点,渲染到页面上
接下来我们通过实例直接修改data
,qv.$data.a = "change data a"
可以看到页面会更新成为
下面说下重新渲染的流程:
- 数据修改之后触发了
Object.defineProperty
的set
方法,方法检测到设置数据与原数据不同,回去获取linkNodes
属性,里面包含了使用这个数据的Node
节点,然后分别调用Node
节点的update
方法 update
方法被调用之后,Node
会重新获取data
去生成dom
元素,然后替换现有的模板元素,至此完成一次更新
结语
这篇文章的例子旨在跟大家说明Vue
是怎么运作的,希望可以帮助到大家在日常使用的时候遇到一些坑,可以从根本原理上面去找原因,当然这个demo 离Vue
还是非常不完整的,缺少了各种模板语法,指令,事件绑定,组件系统,只是把核心的流程展现出来,希望大家喜欢
最后附上源码 点我点我,喜欢的话给个 star 呗~~
手把手教你从零写一个简单的 VUE的更多相关文章
- 手把手教你从零写一个简单的 VUE--模板篇
教程目录1.手把手教你从零写一个简单的 VUE2.手把手教你从零写一个简单的 VUE--模板篇 Hello,我又回来了,上一次的文章教会了大家如何书写一个简单 VUE,里面实现了VUE 的数据驱动视图 ...
- 手把手教你用vue-cli构建一个简单的路由应用
上一章说道:十分钟上手-搭建vue开发环境(新手教程)https://www.jianshu.com/p/0c6678671635 开发环境搭建好之后,那么开始新添加一些页面,构建最基本的vue项目, ...
- 手把手教你用redis实现一个简单的mq消息队列(java)
众所周知,消息队列是应用系统中重要的组件,主要解决应用解耦,异步消息,流量削锋等问题,实现高性能,高可用,可伸缩和最终一致性架构.目前使用较多的消息队列有 ActiveMQ,RabbitMQ,Zero ...
- 【良心保姆级教程】java手把手教你用swing写一个学生的增删改查模块
很多刚入门的同学,不清楚如何用java.swing去开发出一个系统? 不清楚如何使用java代码去操作数据库进行增删改查一些列操作,不清楚java代码和数据库(mysql.sqlserver)之间怎么 ...
- 用Python写一个简单的Web框架
一.概述 二.从demo_app开始 三.WSGI中的application 四.区分URL 五.重构 1.正则匹配URL 2.DRY 3.抽象出框架 六.参考 一.概述 在Python中,WSGI( ...
- 如何写一个简单的http服务器
最近几天用C++写了一个简单的HTTP服务器,作为学习网络编程和Linux环境编程的练手项目,这篇文章记录我在写一个HTTP服务器过程中遇到的问题和学习到的知识. 服务器的源代码放在Github. H ...
- 如何写一个简单的shell
如何写一个简单的shell 看完<UNIX环境高级编程>后我就一直想写一个简单的shell来作为练习,因为有事断断续续的写了好几个月,如今写了差不多来总结一下. 源代码放在了Github: ...
- 分享:计算机图形学期末作业!!利用WebGL的第三方库three.js写一个简单的网页版“我的世界小游戏”
这几天一直在忙着期末考试,所以一直没有更新我的博客,今天刚把我的期末作业完成了,心情澎湃,所以晚上不管怎么样,我也要写一篇博客纪念一下我上课都没有听,还是通过强大的度娘完成了我的作业的经历.(当然作业 ...
- 一步一步写一个简单通用的makefile(三)
上一篇一步一步写一个简单通用的makefile(二) 里面的makefile 实现对通用的代码进行编译,这一章我将会对上一次的makefile 进行进一步的优化. 优化后的makefile: #Hel ...
随机推荐
- c# Winform中如何把图片添加到resources中
我们在Winform项目中中需要插入图片资源,但是新建的项目中找不到Resources文件夹,怎么才能出现呢? 1:双击项目下的Resources.resx,出现视图 2:单击"添加资源&q ...
- JavaWeb-数据库基础
数据库基础 推荐阅读: 数据库:https://www.cnblogs.com/zwtblog/tag/数据库/ 数据库是学习JavaWeb的一个前置,只有了解了数据库的操作和使用,我们才能更好地组织 ...
- tensorflow源码解析之framework-op
目录 什么是op op_def定义 op注册 op构建与注册辅助结构 op重写 关系图 涉及的文件 迭代记录 1. 什么是op op和kernel是TF框架中最重要的两个概念,如果一定要做一个类比的话 ...
- netty系列之:netty中各不同种类的channel详解
目录 简介 ServerChannel和它的类型 Epoll和Kqueue AbstractServerChannel ServerSocketChannel ServerDomainSocketCh ...
- 前端性能优化 —— 使用 BMP 图片代替 canvas.toDataURL
前端开发中有时需要将 canvas 的内容导出成图片文件,例如供 CSS 使用,通常会使用 canvas.toDataURL,兼容性好并且简单. 不过 canvas.toDataURL 显然是非常低效 ...
- VUE3 之 列表动画 - 这个系列的教程通俗易懂,适合新手
1. 概述 老话说的好:可以为别人解决痛点的产品就是好产品. 言归正传,今天我们来聊聊 VUE 的列表动画. 2. 列表动画 2.1 列表中增加和删除元素 <style> .my-ite ...
- 作为一名Python开发,我谈Linux和mac的使用体验
我是一名Python开发,在2018.7~2021.6使用的是Linux系统 Deepin OS 作为自己的开发系统:在2022.7-至今使用的是 mac OS 系统作为开发系统. Deepin OS ...
- Linux上搭建meterSphere
镜像下载.域名解析.时间同步请点击 阿里云开源镜像站 一.安装Docker (1)安装CentOS Docker curl -fsSL https://get.docker.com | bash -s ...
- SolidWorks在一个零件中设置不同的尺寸版本
问题 比如想设置一系列螺丝的长度,一个一个建零件非常麻烦,希望在一个零件中设置不同的长度尺寸版本 解决 比如想设置不同的拉伸长度,右键拉伸>配置特征 可以生成新配置,设置不同的D1参数,即可生成 ...
- HashMap:为什么容量总是为2的n次幂
HashMap:为什么容量总是为2的n次幂1).HashMap是根据key的hash值决定key放到哪个桶中,通过tab[i = (n - 1) & hash]公式计算得出 这里的n是Hash ...