成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Vue.js設(shè)計(jì)與實(shí)現(xiàn)之Vue.js3的設(shè)計(jì)思路

開發(fā) 架構(gòu)
本文中,我們了解到Vue.js框架是通過聲明式描述UI的,而描述UI又有兩種形式:模板字符串和手寫虛擬DOM的形式,虛擬DOM形式比模板字符串更加靈活,但是模板字符串比虛擬DOM形式更加直觀。

1.寫在前面

本文將立足于全局視角去了解Vue.js3的設(shè)計(jì)思路、工作機(jī)制以及一些重要的獨(dú)立組成部分,了解他們之間是如何相互獨(dú)立、又相互配合的。了解描述UI的兩種形式:模板字符串和虛擬DOM,Vue.js框架的兩個(gè)重要組成部分:編譯器和渲染器。

2.聲明式描述UI

通過前面的介紹,我們知道Vue.js3是聲明式UI框架,作者是如何參與設(shè)計(jì)一個(gè)聲明式的UI框架,編寫前端頁面又涉及到哪些內(nèi)容?

  • DOM元素
  • 屬性
  • 事件
  • 元素的層級(jí)結(jié)構(gòu)

上面這些內(nèi)容是原生包含的,進(jìn)行框架設(shè)計(jì)時(shí)如何讓它們變成響應(yīng)式的,在Vue.js3中的解決方案是:

  • 與原生html標(biāo)簽一樣的描述DOM元素和屬性、層級(jí)結(jié)構(gòu)等 <div id="app"><span>onechuan</span></div>
  • 使用:或v-bind來描述動(dòng)態(tài)綁定的屬性,使用@或v-on描述事件 <div id="app" :name="name" @click="handleClick">onechuan</div>

這樣,使用者不需要手寫任何命令式代碼,就可以實(shí)現(xiàn)聲明式描述UI。當(dāng)然除了使用模板形式描述UI外,還能使用JS對(duì)象來描述:

const element = {
//標(biāo)簽元素
tag: "div",
//標(biāo)簽屬性
props:{
onClick: handleClick
},
//子節(jié)點(diǎn)
children: [
{ tag:"span" }
]
}

對(duì)應(yīng)的template模板是:

<div @click="handleClick"><span></span></div>

使用js數(shù)據(jù)對(duì)象描述和template模板有什么異同呢?

//h標(biāo)簽的限制
const level = 3;
const element = {
tag: `h${level}`,//h3標(biāo)簽
}

我們看到對(duì)于js對(duì)象結(jié)構(gòu)代碼簡(jiǎn)潔清晰,而使用模板則需要進(jìn)行窮舉:

<h1 v-if="level === 1"></h1>
<h2 v-else-if="level === 2"></h2>
<h3 v-else-if="level === 3"></h1>
<h4 v-else-if="level === 4"></h1>
<h5 v-else-if="level === 5"></h1>
<h6 v-else-if="level === 6"></h1>

我們?cè)赩ue.js組件中通過手寫渲染函數(shù)就是使用虛擬DOM來描述UI,h函數(shù)的返回值就是一個(gè)對(duì)象,用于開發(fā)者輕松地使用虛擬DOM描述UI。

import {h} from "vue";

export default {
render(){
return h("div",{ onClick: handleClick })//虛擬DOM
}
}

對(duì)應(yīng)的JS對(duì)象描述UI就是如下代碼段:

export default {
render(){
return {
tag:"div",
props:{onClick: handleClick }
}
}
}

組件的渲染函數(shù)renderer的作用:Vue.js根據(jù)組件的render函數(shù)的返回值生成虛擬DOM,進(jìn)而將組件內(nèi)容進(jìn)行渲染到頁面。

3.初識(shí)渲染器

我們可以使用JS數(shù)據(jù)對(duì)象來描述虛擬DOM,那么虛擬DOM又是如何通過渲染函數(shù)轉(zhuǎn)為真實(shí)DOM后,渲染到頁面的呢?

在前面的代碼片段中是使用JS數(shù)據(jù)對(duì)象來描述虛擬DOM:

const vnode = {
tag:"div",
props:{
onclick:()=>console.log("hello pingping")
},
children:"please click me"
}

我們需要編寫渲染函數(shù)renderer去將虛擬DOM渲染為真實(shí)DOM,接收兩個(gè)參數(shù):vnode虛擬DOM對(duì)象以及container真實(shí)DOM元素掛載點(diǎn),container用于掛載渲染函數(shù)渲染的真實(shí)DOM元素。

function renderer(vnode, container){
// 使用vnode的tag作為標(biāo)簽名渲染DOM元素
const el = document.createElement(vnode.tag)
// 遍歷vnode的props作為DOM元素的屬性和事件
for(const key in vnode.props){
if(/^on/.test(key)){
// 如果key以on開頭,這說明他是一個(gè)事件
el.addEventListener(
key.substring(2).toLowerCase(),//事件名稱將onClick-->click
vnode.props[key]//事件處理函數(shù)
)
}
}

// 處理children
if(typeof vnode.children === "string"){
// 如果是字符串,直接作為元素的文本子節(jié)點(diǎn)
el.appendChild(document.createTextNode(vnode.children))
}else if(Array.isArray(vnode.children)){
// 遞歸調(diào)用renderer函數(shù)進(jìn)行渲染子節(jié)點(diǎn),使用當(dāng)前元素el作為掛載點(diǎn)
vnode.children.forEach(child=>renderer(child,el))
}
// 將元素添加到掛載點(diǎn)
container.appendChild(el)
}

調(diào)用:

renderer(vnode, document.body)

點(diǎn)擊按鈕后:

渲染器renderer的實(shí)現(xiàn)思路:

  • 創(chuàng)建元素
  • 給元素添加屬性和事件
  • 遞歸遍歷children創(chuàng)建節(jié)點(diǎn)

4.組件的本質(zhì)

組件是一組DOM元素的封裝,而這組DOM元素就是組件渲染的內(nèi)容,對(duì)此可以定義函數(shù)來描述這段真實(shí)DOM元素對(duì)應(yīng)的虛擬DOM對(duì)象。

const MyComponent = function(){
return {
tag:"div",
props:{
onClick: ()=>console.log("hello world")
},
children:"click me"
}
}

通過虛擬DOM對(duì)象中tag屬性可以用于存儲(chǔ)組件函數(shù),將其作為標(biāo)簽類型進(jìn)行渲染,同樣的也需要渲染器renderer函數(shù)。當(dāng)然,此時(shí)的渲染函數(shù)需要根據(jù)待渲染標(biāo)簽的類型進(jìn)行判定,是普通標(biāo)簽元素還是組件元素。

const vnode = {
tag: MyComponent
}

renderer(vnode, document.body)

function renderer(vnode, container){
// 判斷是標(biāo)簽元素還是組件
if(typeof vnode.tag === "string"){
// 如果是字符串,直接作為元素的標(biāo)簽元素
mountElement(vnode, container)
}else{
mountComponent(vnode, container)
}
}

// 渲染元素
function mountElement(vnode, container){
// 使用vnode.tag 作為標(biāo)簽名稱創(chuàng)建DOM元素
const el = document.createElement(vnode.tag)
// 遍歷vnode的props作為DOM元素的屬性和事件
for(const key in vnode.props){
if(/^on/.test(key)){
// 如果key以on開頭,這說明他是一個(gè)事件
el.addEventListener(
key.substring(2).toLowerCase(),//事件名稱將onClick-->click
vnode.props[key]//事件處理函數(shù)
)
}
}

// 處理children
if(typeof vnode.children === "string"){
// 如果是字符串,直接作為元素的文本子節(jié)點(diǎn)
el.appendChild(document.createTextNode(vnode.children))
}else if(Array.isArray(vnode.children)){
// 遞歸調(diào)用renderer函數(shù)進(jìn)行渲染子節(jié)點(diǎn),使用當(dāng)前元素el作為掛載點(diǎn)
vnode.children.forEach(child=>renderer(child,el))
}
// 將元素添加到掛載點(diǎn)
container.appendChild(el)
}

// 渲染組件
function mountComponent(vnode, container){
// 調(diào)用組件函數(shù),獲取組件要渲染的內(nèi)容-虛擬DOM
const subtree = vnode.tag()
// 遞歸調(diào)用renderer渲染subtree
renderer(subtree, container)
}

5.模板的工作原理

其實(shí),手寫虛擬DOM還是使用模板形式,都可以聲明式描述UI,在Vue.js框架設(shè)計(jì)中是始終支持兩種形式的。我們知道JS對(duì)象描述虛擬DOM的形式,是通過渲染器renderer將虛擬DOM轉(zhuǎn)為真實(shí)DOM的,那么模板又是如何渲染到頁面的呢?

<div @click="handleClick">
hello pingping
</div>
模板字符串渲染到頁面,依賴于

模板字符串渲染到頁面,依賴于Vue.js框架的一個(gè)重要函數(shù)--編譯器compiler,其作用就是將模板字符串編譯成與之功能對(duì)應(yīng)的渲染函數(shù):

render(){
return h("div",{onClick: handleClick},"hello pingping")
}

對(duì)此,我們知道無論是使用模板字符串還是直接手寫渲染函數(shù),都是通過渲染函數(shù)將虛擬DOM轉(zhuǎn)為真實(shí)DOM,最終將描述的內(nèi)容渲染到頁面上。只不過使用模板字符串多了一個(gè)編譯過程,需要通過編譯器將模板字符串編譯成渲染函數(shù)。

6.編譯器和渲染器組成有機(jī)整體

在Vue.js框架設(shè)計(jì)中,組件實(shí)現(xiàn)依賴于渲染器和編譯器,而渲染器和編譯器之間是彼此獨(dú)立又相互依賴的重要部分。

7.寫在后面

本文中,我們了解到Vue.js框架是通過聲明式描述UI的,而描述UI又有兩種形式:模板字符串和手寫虛擬DOM的形式,虛擬DOM形式比模板字符串更加靈活,但是模板字符串比虛擬DOM形式更加直觀。

在Vue.js框架設(shè)計(jì)中有兩種重要的組成部分:編譯器和渲染器,編譯器就是將模板字符串編譯成渲染函數(shù),而渲染器則是將虛擬DOM創(chuàng)建為真實(shí)DOM,最終完成頁面的渲染。

責(zé)任編輯:武曉燕 來源: 前端一碼平川
相關(guān)推薦

2022-04-01 08:08:27

Vue.js框架命令式

2022-04-25 07:36:21

組件數(shù)據(jù)函數(shù)

2022-04-12 08:08:57

watch函數(shù)options封裝

2022-04-18 08:09:44

渲染器DOM掛載Vue.js

2022-04-14 09:35:03

Vue.js設(shè)計(jì)Reflect

2022-04-11 08:03:30

Vue.jscomputed計(jì)算屬性

2022-04-05 16:44:59

系統(tǒng)Vue.js響應(yīng)式

2022-04-03 15:44:55

Vue.js框架設(shè)計(jì)設(shè)計(jì)與實(shí)現(xiàn)

2022-05-03 21:18:38

Vue.js組件KeepAlive

2022-04-09 17:53:56

Vue.js分支切換嵌套的effect

2022-04-17 09:18:11

響應(yīng)式數(shù)據(jù)Vue.js

2022-04-26 05:55:06

Vue.js異步組件

2022-04-16 13:59:34

Vue.jsJavascript

2016-11-01 19:10:33

vue.js前端前端框架

2022-04-19 23:01:54

Vue.jsDOM節(jié)點(diǎn)DOM樹

2022-04-20 09:07:04

Vue.js的事件處理

2019-04-01 19:38:28

Vue.jsJavascript前端

2016-11-04 19:58:39

vue.js

2017-07-04 17:55:37

Vue.js插件開發(fā)

2018-04-04 10:32:13

前端JavascriptVue.js
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 久久精品国产免费 | 三级特黄特色视频 | 久久久久国产精品www | 99精品99 | 亚洲欧美日韩精品久久亚洲区 | 国产99视频精品免费视频7 | 日产精品久久久一区二区福利 | 一区二区三区免费 | 欧美久久国产 | 成人99| 午夜在线视频一区二区三区 | 操久久 | 日韩毛片视频 | 蜜桃免费一区二区三区 | 国产一区二区三区久久久久久久久 | 亚洲免费一区二区 | 97久久精品| 毛片黄片 | 人人亚洲| 国产精品一区在线观看 | 成人国产精品久久久 | 婷婷色网 | 欧美日韩不卡 | 亚洲综合在线视频 | 久国久产久精永久网页 | 日韩欧美亚洲 | 国产一级在线 | 欧美99| 超碰伊人久久 | 国产精品一区二区三区在线 | 久久综合一区二区 | 亚洲色图50p | 99视频在线| 午夜影院黄 | 视频在线观看一区二区 | 色偷偷888欧美精品久久久 | 久久久久国产一级毛片高清网站 | 亚洲成a人片 | 中文字幕成人 | 蜜桃一区二区三区在线 | 国产精品福利视频 |