手写 Vue 系列 之 从 Vue1 升级到 Vue2
前言
上一篇文章 手写 Vue 系列 之 Vue1.x 带大家从零开始实现了 Vue1 的核心原理,包括如下功能:
数据响应式拦截
普通对象
数组
数据响应式更新
依赖收集
Dep
Watcher
编译器
文本节点
v-on:click
v-bind
v-model
在最后也详细讲解了 Vue1 的诞生以及存在的问题:Vue1.x 在中小型系统中性能会很好,定向更新 DOM 节点,但是大型系统由于 Watcher 太多,导致资源占用过多,性能下降。于是 Vue2 中通过引入 VNode 和 Diff 的来解决这个问题,
所以接下来的系列内容就是升级上一篇文章编写的 lyn-vue
框架,将它从 Vue1 升级到 Vue2。所以建议整个系列大家按顺序去阅读学习,如若强行阅读,可能会产生云里雾里的感觉,事倍功半。
另外欢迎 关注 以防迷路,同时系列文章都会收录到 精通 Vue 技术栈的源码原理 专栏,也欢迎关注该专栏。
目标
升级后的框架需要将如下示例代码跑起来
示例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Lyn Vue2.0</title>
</head>
<body>
<div id="app">
<h3>数据响应式更新 原理</h3>
<div>{{ t }}</div>
<div>{{ t1 }}</div>
<div>{{ arr }}</div>
<h3>methods + computed + 异步更新队列 原理</h3>
<div>
<p>{{ counter }}</p>
<div>{{ doubleCounter }}</div>
<div>{{ doubleCounter }}</div>
<div>{{ doubleCounter }}</div>
<button v-on:click="handleAdd"> Add </button>
<button v-on:click="handleMinus"> Minus </button>
</div>
<h3>v-bind</h3>
<span v-bind:title="title">右键审查元素查看我的 title 属性</span>
<h3>v-model 原理</h3>
<div>
<input type="text" v-model="inputVal" />
<div>{{ inputVal }}</div>
</div>
<div>
<input type="checkbox" v-model="isChecked" />
<div>{{ isChecked }}</div>
</div>
<div>
<select v-model="selectValue">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
<div>{{ selectValue }}</div>
</div>
<h3>组件 原理</h3>
<comp></comp>
<h3>插槽 原理</h3>
<scope-slot></scope-slot>
<scope-slot>
<template v-slot:default="scopeSlot">
<div>{{ scopeSlot }}</div>
</template>
</scope-slot>
</div>
<script type="module">
import Vue from './src/index.js'
const ins = new Vue({
el: '#app',
data() {
return {
// 原始值和对象的响应式原理
t: 't value',
t1: {
tt1: 'tt1 value'
},
// 数组的响应式原理
arr: [1, 2, 3],
// 响应式更新
counter: 0,
// v-bind
title: "I am title",
// v-model
inputVal: 'test',
isChecked: true,
selectValue: 2,
}
},
// methods + 事件 + 数据响应式更新 原理
methods: {
handleAdd() {
this.counter++
},
handleMinus() {
this.counter--
}
},
// computed + 异步更新队列 的原理
computed: {
doubleCounter() {
console.log('evalute doubleCounter')
return this.counter * 2
}
},
// 组件
components: {
// 子组件
'comp': {
template: `
<div>
<p>{{ compCounter }}</p>
<p>{{ doubleCompCounter }}</p>
<p>{{ doubleCompCounter }}</p>
<p>{{ doubleCompCounter }}</p>
<button v-on:click="handleCompAdd"> comp add </button>
<button v-on:click="handleCompMinus"> comp minus </button>
</div>`,
data() {
return {
compCounter: 0
}
},
methods: {
handleCompAdd() {
this.compCounter++
},
handleCompMinus() {
this.compCounter--
}
},
computed: {
doubleCompCounter() {
console.log('evalute doubleCompCounter')
return this.compCounter * 2
}
}
},
// 插槽
'scope-slot': {
template: `
<div>
<slot name="default" v-bind:slotKey="slotKey">{{ slotKey }}</slot>
</div>
`,
data() {
return {
slotKey: 'scope slot content'
}
}
}
}
})
// 数据响应式拦截
setTimeout(() => {
console.log('********** 属性值为原始值时的 getter、setter ************')
console.log(ins.t)
ins.t = 'change t value'
console.log(ins.t)
}, 1000)
setTimeout(() => {
console.log('********** 属性的新值为对象的情况 ************')
ins.t = {
tt: 'tt value'
}
console.log(ins.t.tt)
}, 2000)
setTimeout(() => {
console.log('********** 验证对深层属性的 getter、setter 拦截 ************')
ins.t1.tt1 = 'change tt1 value'
console.log(ins.t1.tt1)
}, 3000)
setTimeout(() => {
console.log('********** 将值为对象的属性更新为原始值 ************')
console.log(ins.t1)
ins.t1 = 't1 value'
console.log(ins.t1)
}, 4000)
setTimeout(() => {
console.log('********** 数组操作方法的拦截 ************')
console.log(ins.arr)
ins.arr.push(4)
console.log(ins.arr)
}, 5000)
</script>
</body>
</html>
知识点
示例代码涉及的知识点包括:
基于模版解析的编译器
解析模版得到 AST
基于 AST 生成渲染函数
render helper
_c,创建指定标签的 VNode
_v,创建文本节点的 VNode
_t,创建插槽节点的 VNode
VNode
patch
原生标签和组件的初始渲染
v-model
v-bind
v-on
diff
插槽原理
computed
异步更新队列
效果
示例代码最终的运行效果如下:
说明
该框架只为讲解 Vue 的核心原理,没有什么健壮性可言,说不定你换个示例代码可能就会报错、跑不起来,但是用来学习是完全足够了,基本上把 Vue 的核心原理(知识点)都实现了一遍。
所以接下来就开始正式的学习之旅吧,加油!!
链接
- 配套视频,微信公众号回复:"精通 Vue 技术栈源码原理视频版" 获取
- 精通 Vue 技术栈源码原理 专栏
- github 仓库 liyongning/Vue 欢迎 Star
- github 仓库 liyongning/Lyn-Vue-DOM 欢迎 Star
- github 仓库 liyongning/Lyn-Vue-Template 欢迎 Star
感谢各位的:关注、点赞、收藏和评论,我们下期见。
当学习成为了习惯,知识也就变成了常识。 感谢各位的 关注、 点赞、收藏和评论。
新视频和文章会第一时间在微信公众号发送,欢迎关注:李永宁lyn
文章已收录到 github 仓库 liyongning/blog,欢迎 Watch 和 Star。
手写 Vue 系列 之 从 Vue1 升级到 Vue2的更多相关文章
- 手写 Vue 系列 之 Vue1.x
前言 前面我们用 12 篇文章详细讲解了 Vue2 的框架源码.接下来我们就开始手写 Vue 系列,写一个自己的 Vue 框架,用最简单的代码实现 Vue 的核心功能,进一步理解 Vue 核心原理. ...
- tensorflow笔记(四)之MNIST手写识别系列一
tensorflow笔记(四)之MNIST手写识别系列一 版权声明:本文为博主原创文章,转载请指明转载地址 http://www.cnblogs.com/fydeblog/p/7436310.html ...
- tensorflow笔记(五)之MNIST手写识别系列二
tensorflow笔记(五)之MNIST手写识别系列二 版权声明:本文为博主原创文章,转载请指明转载地址 http://www.cnblogs.com/fydeblog/p/7455233.html ...
- 剖析手写Vue,你也可以手写一个MVVM框架
剖析手写Vue,你也可以手写一个MVVM框架# 邮箱:563995050@qq.com github: https://github.com/xiaoqiuxiong 作者:肖秋雄(eddy) 温馨提 ...
- vue1升级到vue2的问题
router 不能用map方法了,需要改router的结构改为 routers= [ { // 当没有匹配路由时默认返回的首页 path:'/index', compone ...
- 手写vue中v-bind:style效果的自定义指令
自定义指令 什么是自定义指令 以 v- 为前缀,然后加上自己定义好的名字组成的一个指令就是自定义指令.为什么要有自定义指令呢?在有些时候,你仍然需要对普通的DOM元素进行底层的操作,这个时候就可以用到 ...
- 手写vue双向绑定数据
来一张原理图: 实现思路: (1)绑定data 种的数据,为每个数据添加指令.通过Object,defineProperty() 来通知属性是否更改 (2) 找到每个DOM节点的指令.绑定事件.并绑定 ...
- 常见python面试题-手写代码系列
1.如何反向迭代一个序列 #如果是一个list,最快的方法使用reversetempList = [1,2,3,4]tempList.reverse()for x in tempList: pr ...
- 学习手写vue,理解原理
class Compiler{ constructor(el,vm){ // 判断el属性 是不是 一个元素, 如果不是就获取 this.el = this.isElementNode(el)?el: ...
随机推荐
- C语言system函数
我们今天来看看在windows操作系统下system () 函数详解(主要是在C语言中的应用) 注意:在windows下的system函数中命令可以不区别大小写! 函数名: system 功 能: 发 ...
- 【转】 Python生成器generator之next和send运行流程
原文链接:https://blog.csdn.net/pfm685757/article/details/49924099 对于普通的生成器,第一个next调用,相当于启动生成器,会从生成器函数的第一 ...
- Annotation深入研究——@Documented注释使用
Documented注释的作用及其javadoc文档生成工具的使用 代码放在MyDocumentedtAnnotationDemo.java文件中 package org.yu.demo16.docu ...
- Haproxy LVS Nginx的优缺点总结
Haproxy LVS Nginx的优缺点总结 1.haproxy优点 2.Nginx优点 3.Nginx缺点 4.LVS优点 5.LVS缺点 haproxy优点: haproxy也是支持虚拟主机 ...
- 对于Web性能优化, 了解和经验
我们在发布项目之前压缩CSS和JavaScript源代码,这样文件体积就变小了,用户加载必要资源所花的时间也就更短了. 压缩源码和图片 JavaScript文件源代码可以采用混淆压缩的方式,CSS文件 ...
- nginx负载均衡中常见的算法及原理有哪些?
一.nginx负载均衡常用算法 1.1 轮询 轮询,nginx默认方式.一次将请求分配给各个后台服务器. upstream backserver { server 10.0.0.7; server 1 ...
- 有手就行8——项目构建细节3-Jenkins的参数化构建
有手就行8--项目构建细节3-Jenkins的参数化构建 有时在项目构建的过程中,我们需要根据用户的输入动态传入一些参数,从而影响整个构建结果,这时 我们可以使用参数化构建. Jenkins支持非常 ...
- log4j和lockback的比较,二者可否同时使用
一.log4j和logback的介绍 log4j: 可以控制日志信息输送的目的地是控制台.文件.GUI组件,甚至是套接口服务器.NT的事件记录器.UNIX Syslog守护进程等:可以控制每一条日志的 ...
- (Unity)XML文件读写与IO文件操作类使用介绍
using System.Xml; //xml文件操作命名空间 #region 写入操作 void WriteXMLFile(string _fileName) { Xm ...
- gdb调试小技巧
1.进入gdb,需要源码,然后gdb+可执行文件,如果要看代码一起的就gdb+可执行文件+tui 2.设置参数 set args +参数 3.设置断点,可以b +行数或者b+函数名字 4.r就是一直跑 ...