前言
上一篇文章 手寫 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
-
非同步更新佇列
效果
示例程式碼最終的執行效果如下:
動圖地址: https://gitee.com/liyongning/typora-image-bed/raw/master/202203092034307.image
說明
該框架只為講解 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。