成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專(zhuān)欄INFORMATION COLUMN

VUE - MVVM - part12 - props

bluesky / 371人閱讀

摘要:看這篇之前,如果沒(méi)有看過(guò)之前的文章,移步拉到文章末尾查看之前的文章。而該組件實(shí)例的父實(shí)例卻并不固定,所以我們將這些在使用時(shí)才能確定的參數(shù)在組件實(shí)例化的時(shí)候傳入。系列文章地址優(yōu)化優(yōu)化總結(jié)

看這篇之前,如果沒(méi)有看過(guò)之前的文章,移步拉到文章末尾查看之前的文章。

前言

在上一步,我們實(shí)現(xiàn) extend 方法,用于擴(kuò)展 Vue 類(lèi),而我們知道子組件需要通過(guò) extend 方法來(lái)實(shí)現(xiàn),我們從測(cè)試?yán)觼?lái)入手,看看這一步我們需要實(shí)現(xiàn)什么:

let test = new Vue({
    data() {
        return {
            dataTest: {
                subTest: 1
            }
        }
    },
    components: {
        sub: {
            props: {
                propsStaticTest: {
                    default: "propsStaticTestDefault"
                },
                propsDynamicTest: {
                    default: "propsDynamicTestDefault"
                }
            },
            watch: {
                "propsDynamicTest"(newValue, oldValue) {
                    console.log("propsDynamicTest newValue = " + newValue)
                }
            }
        }
    }
})

從例子可知: subtest 的子組件,同時(shí) test 組件向 sub 組件傳遞了 propsStaticTest/propsDynamicTest 兩個(gè) props 。

所以我們這一步要做兩件事

實(shí)現(xiàn)子組件生成樹(shù)結(jié)構(gòu)

實(shí)現(xiàn) props ,從例子上可以看出需要實(shí)現(xiàn)靜態(tài)和動(dòng)態(tài)兩種 prop

VUE 中組件的生成

雖然在之前的步驟中,我們一直沒(méi)有涉及到模板,僅僅是把頁(yè)面的渲染抽象成一個(gè)函數(shù),主要是為了把 MVVM 中的數(shù)據(jù)綁定過(guò)程給解釋清楚,但是父子組件的實(shí)現(xiàn)卻必須要通過(guò)模板來(lái)聯(lián)系,所以我們這里簡(jiǎn)單的介紹下 Vue 中由模板到生成頁(yè)面渲染函數(shù)的過(guò)程

得到模板(DOM 字符串)或是 render 函數(shù)

分析模板,得到 HTML 語(yǔ)法樹(shù)(AST),生成 render 函數(shù)。如果直接給的是 render 則沒(méi)有這個(gè)步驟

render 函數(shù)生成 VNode 這就是虛擬樹(shù)了

Vnode 作為參數(shù)傳入一個(gè)函數(shù)中,就能得到 html 渲染函數(shù)

ok 看起來(lái)和組件好像沒(méi)有什么關(guān)系,我們分析下組件寫(xiě)法

由上面這個(gè)標(biāo)簽我們可以得到什么?

這是一個(gè)子組件,組件名:sub

傳遞了一個(gè)靜態(tài)的 proppropsStaticTest

傳遞了一個(gè)動(dòng)態(tài)的 proppropsDynamicTest

靜態(tài)說(shuō)明這個(gè)屬性不會(huì)發(fā)生變化,動(dòng)態(tài)會(huì),最明顯的區(qū)別就是:動(dòng)態(tài)屬性有 :/v-bind 修飾

結(jié)合上面的第2個(gè)步驟,會(huì)分析出一些東西。僅僅針對(duì) props ,假設(shè)模板解析引擎會(huì)解析出下面這樣一個(gè)結(jié)構(gòu)

let propsOption = [{
    key: "propsStaticTest",
    value: "propsStaticValue",
    isDynamic: false
}, {
    key: "propsDynamicTest",
    value: "dataTest.subTest",
    isDynamic: true
}]

注: 這里僅僅是我的假設(shè),方便理解,在 Vue 中的模板解析出來(lái)的內(nèi)容要比這個(gè)復(fù)雜。

ok 有了上面的鋪墊我們來(lái)實(shí)現(xiàn)父子組件和 props

父子組件

實(shí)例初始化的實(shí)例我們需要做的僅僅就是保存組件之間的關(guān)系就行,ok 我們來(lái)實(shí)現(xiàn)它

class Vue extends Event {
    ···
    _init(options) {
        let vm = this
        ···
        // 獲取父節(jié)點(diǎn)
        let parent = vm.$options.parent
        // 將該節(jié)點(diǎn)放到父節(jié)點(diǎn)的 $children 列表中
        if (parent) {
            parent.$children.push(vm)
        }
        // 設(shè)置父節(jié)點(diǎn)和根節(jié)點(diǎn)
        vm.$parent = parent
        vm.$root = parent ? parent.$root : vm
        // 初始化子節(jié)點(diǎn)列表
        vm.$children = []
    }
}

我們需要做的僅僅就是給傳入 options 設(shè)置 parent ,就能明確組件之間的關(guān)系。

接著我們模擬一下當(dāng)模板編譯的時(shí)候碰到 的情況,具體的來(lái)說(shuō)就是會(huì)執(zhí)行以下代碼:

let testSubClass = Vue.extend(test.$options.components.sub)
let testSub = new testSubClass({parent: test})
console.log(testSub.$parent === test)
// true

ok 現(xiàn)在我們先不想模板編譯具體是如何進(jìn)行的,從這兩行代碼中,我們可以看出我們先使用了 extend 擴(kuò)展了 Vue 實(shí)例,生成一個(gè)子類(lèi)(testSubClass),接著我們實(shí)例化該類(lèi),傳入?yún)?shù)確定父實(shí)例。

想象下一,我們?yōu)槭裁匆謨刹桨褏?shù)傳入。

我們知道當(dāng)我們寫(xiě)好子組件的配置時(shí),子組件的內(nèi)部狀態(tài)就已經(jīng)確定了,所以我們可以根據(jù)這些固定的配置去擴(kuò)展 Vue 類(lèi)方便我們調(diào)用(使用的時(shí)候 new 一下就可以)。

而該組件實(shí)例的父實(shí)例卻并不固定,所以我們將這些在使用時(shí)才能確定的參數(shù)在組件實(shí)例化的時(shí)候傳入。

接著我們來(lái)想象一下,如果子組件(sub)里面還有子組件(sub-sub)會(huì)怎么樣?

使用 extend 擴(kuò)展 Vue 類(lèi)

確定父實(shí)例,new 的時(shí)候傳入,而這個(gè) parent 就是 sub

這樣調(diào)用過(guò)多次之后,一顆 Vue 的實(shí)例樹(shù)就生成了,每一個(gè)節(jié)點(diǎn)都保留著父實(shí)例的引用,子組件列表還有根實(shí)例。

希望你的腦子里已經(jīng)長(zhǎng)出了這顆樹(shù)~

ok 接下來(lái)我們來(lái)實(shí)現(xiàn) props

props

希望你還記得下面這幾行代碼:

let propsOption = [{
    key: "propsStaticTest",
    value: "propsStaticValue",
    isDynamic: false
}, {
    key: "propsDynamicTest",
    value: "dataTest.subTest",
    isDynamic: true
}]

這個(gè)是我們模擬模板編譯時(shí)關(guān)于 props 的部分產(chǎn)出,具體的來(lái)說(shuō)就是鍵值對(duì),以及是否有 :/v-bind 修飾,而我們知道在 Vue 中這個(gè)修飾符是表示是否是動(dòng)態(tài)綁定,所以我在這里使用 isDynamic 來(lái)標(biāo)志。

首先我們來(lái)獲取屬性的數(shù)據(jù),由于動(dòng)態(tài)綁定的 props 是取值路徑,所以我們得去父對(duì)象下獲取值。

let propsData = {}
propsOption.forEach(item => {
    if (item.isDynamic) {
        // eg: "dataTest.subTest" => test.dataTest.subTest 將字符串轉(zhuǎn)換成取值
        propsData[item.key] = item.value.split(".").reduce((obj, name) => obj[name], test)
    } else {
        propsData[item.key] = item.value
    }
})
console.log(propsData)
// { propsStaticTest: "propsStaticValue", propsDynamicTest: 1 }

ok 我們拿到中屬性對(duì)應(yīng)的值,接著把 propsData 給傳進(jìn)去

let testSub = new testSubClass({parent: test, propsData})

接著我們?cè)?_init 方法中來(lái)處理 props

_init(options) {
    ···
    let props = vm._props = {}
    let propsData = vm.$options.propsData
    for (let key in vm.$options.props) {
        let value = propsData[key]
        // 如果沒(méi)有傳值,使用默認(rèn)值
        if (!value) {
            value = vm.$options.props[key].default
        }
        props[key] = value
    }
    observe(props)
    for (let key in props) {
        proxy(vm, "_props", key)
    }
    ···
}

porps 的處理和 data 類(lèi)似,需要變成可監(jiān)聽(tīng)結(jié)構(gòu),代理到 this 對(duì)象下,無(wú)非 data 是從傳入的函數(shù)取值,而 props 從傳入的 propsData 中取值。

ok 直到現(xiàn)在為止,看起來(lái)都很美好,但是部分 props 是動(dòng)態(tài)的,父組件相應(yīng)值的變化是需要同步到子組件中的,但目前我們還沒(méi)有實(shí)現(xiàn)父組件和子組件的聯(lián)系,僅僅是把值給取出放在子組件內(nèi)而已。

其實(shí)一看到監(jiān)聽(tīng)變化就理所當(dāng)然的想到 Watcher,ok 我們用 Watcher 來(lái)實(shí)現(xiàn)它:

propsOption.forEach(item => {
    if (item.isDynamic) {
        new Watcher({}, () => {
            return item.value.split(".").reduce((obj, name) => obj[name], test)
        }, (newValue, oldValue) => {
            testSub[item.key] = newValue
        })
    }
})

ok 最后一步完成,完整的測(cè)試代碼

本來(lái)還想實(shí)現(xiàn)下 provide/inject 但篇幅有點(diǎn)大了,下一步實(shí)現(xiàn),也做個(gè)總結(jié)。

系列文章地址

VUE - MVVM - part1 - defineProperty

VUE - MVVM - part2 - Dep

VUE - MVVM - part3 - Watcher

VUE - MVVM - part4 - 優(yōu)化Watcher

VUE - MVVM - part5 - Observe

VUE - MVVM - part6 - Array

VUE - MVVM - part7 - Event

VUE - MVVM - part8 - 優(yōu)化Event

VUE - MVVM - part9 - Vue

VUE - MVVM - part10 - Computed

VUE - MVVM - part11 - Extend

VUE - MVVM - part12 - props

VUE - MVVM - part13 - inject & 總結(jié)

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/94884.html

相關(guān)文章

  • VUE - MVVM - part13 - inject & 總結(jié)

    摘要:通過(guò)裝作這些變化,我們實(shí)現(xiàn)了從而到達(dá)了數(shù)據(jù)變化觸發(fā)函數(shù)的過(guò)程。于此同時(shí),我們還實(shí)現(xiàn)了來(lái)擴(kuò)展這個(gè)可響應(yīng)的結(jié)構(gòu),讓這個(gè)對(duì)象擁有了觸發(fā)和響應(yīng)事件的能力。最后,根據(jù)我們的實(shí)現(xiàn),這是最終的產(chǎn)出,一個(gè)框架,了解一下系列文章地址優(yōu)化優(yōu)化總結(jié) 看這篇之前,如果沒(méi)有看過(guò)之前的文章,移步拉到文章末尾查看之前的文章。 provide / inject 在上一步我們實(shí)現(xiàn)了,父子組件,和 props 一樣 pr...

    niuxiaowei111 評(píng)論0 收藏0
  • VUE - MVVM - part1 - defineProperty

    摘要:在中關(guān)于如何實(shí)現(xiàn)在網(wǎng)上可以搜出不少,在看了部分源碼后,梳理一下內(nèi)容。換個(gè)說(shuō)法,當(dāng)我們?nèi)≈档臅r(shí)候,函數(shù)自動(dòng)幫我們添加了針對(duì)當(dāng)前值的依賴(lài),當(dāng)這個(gè)值發(fā)生變化的時(shí)候,處理了這些依賴(lài),比如說(shuō)節(jié)點(diǎn)的變化。 在 VUE 中關(guān)于如何實(shí)現(xiàn)在網(wǎng)上可以搜出不少,在看了部分源碼后,梳理一下內(nèi)容。 首先,我們需要了解一下 js 中的一個(gè) API :Object.defineProperty(obj, prop,...

    liukai90 評(píng)論0 收藏0
  • VUE - MVVM - part11 - Extend

    摘要:所以方法,是對(duì)默認(rèn)進(jìn)行擴(kuò)展,從而實(shí)現(xiàn)擴(kuò)展。這里我用了這個(gè)庫(kù)提供的合并方法,用來(lái)合并兩個(gè)對(duì)象,并不會(huì)修改原對(duì)象的內(nèi)容。測(cè)試符合我們的預(yù)期,方法也就實(shí)現(xiàn)了,下一步,實(shí)現(xiàn)父子組件。系列文章地址優(yōu)化優(yōu)化總結(jié) 看這篇之前,如果沒(méi)有看過(guò)之前的文章,移步拉到文章末尾查看之前的文章。 組件的擴(kuò)展 在 Vue 中有 extend 方法可以擴(kuò)展 Vue 的實(shí)例,在上一步中,有一些實(shí)現(xiàn)是必須要通過(guò)子父組件才...

    cartoon 評(píng)論0 收藏0
  • VUE - MVVM - part10 - Computed

    摘要:了解之后我們來(lái)實(shí)現(xiàn)它,同樣的為了方便理解我寫(xiě)成了一個(gè)類(lèi)這里的一般是的實(shí)例將屬性代理到實(shí)例下的構(gòu)造函數(shù)我們實(shí)現(xiàn)了代理屬性和更新計(jì)算屬性的值,同時(shí)依賴(lài)沒(méi)變化時(shí),也是不會(huì)觸發(fā)的更新,解決了以上的個(gè)問(wèn)題。 看這篇之前,如果沒(méi)有看過(guò)之前的文章,移步拉到文章末尾查看之前的文章。 回顧 先捋一下,之前我們實(shí)現(xiàn)的 Vue 類(lèi),主要有一下的功能: 屬性和方法的代理 proxy 監(jiān)聽(tīng)屬性 watche...

    callmewhy 評(píng)論0 收藏0
  • VUE - MVVM - part4 - 優(yōu)化Watcher

    摘要:關(guān)于中的的實(shí)現(xiàn),差不多也就這樣了,當(dāng)然這僅僅是基礎(chǔ)的實(shí)現(xiàn),而且視圖層層渲染抽象成一個(gè)函數(shù)。不同于中的實(shí)現(xiàn),這里少了很多各種標(biāo)記和應(yīng)用標(biāo)記的過(guò)程。 看這篇之前,如果沒(méi)有看過(guò)之前的文章,可拉到文章末尾查看之前的文章。 回顧 首先我們思考一下截止當(dāng)前,我們都做了什么 通過(guò) defineReactive 這個(gè)函數(shù),實(shí)現(xiàn)了對(duì)于數(shù)據(jù)取值和設(shè)置的監(jiān)聽(tīng) 通過(guò) Dep 類(lèi),實(shí)現(xiàn)了依賴(lài)的管理 通過(guò) Wa...

    CoffeX 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<