成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

VUE - MVVM - part11 - Extend

cartoon / 2570人閱讀

摘要:所以方法,是對默認(rèn)進(jìn)行擴(kuò)展,從而實(shí)現(xiàn)擴(kuò)展。這里我用了這個(gè)庫提供的合并方法,用來合并兩個(gè)對象,并不會(huì)修改原對象的內(nèi)容。測試符合我們的預(yù)期,方法也就實(shí)現(xiàn)了,下一步,實(shí)現(xiàn)父子組件。系列文章地址優(yōu)化優(yōu)化總結(jié)

看這篇之前,如果沒有看過之前的文章,移步拉到文章末尾查看之前的文章。

組件的擴(kuò)展

Vue 中有 extend 方法可以擴(kuò)展 Vue 的實(shí)例,在上一步中,有一些實(shí)現(xiàn)是必須要通過子父組件才能實(shí)現(xiàn),而子組件相當(dāng)于一個(gè)特殊的 Vue 實(shí)例,所以這步,我們先把這個(gè)擴(kuò)展實(shí)例的方法實(shí)現(xiàn)。

我們先來看看官網(wǎng)對于 extend 方法的介紹:

使用基礎(chǔ) Vue 構(gòu)造器,創(chuàng)建一個(gè)“子類”。參數(shù)是一個(gè)包含組件選項(xiàng)的對象。

從后面一句和具體的使用方法可以得出其實(shí)是我們創(chuàng)建實(shí)例時(shí),對于傳入?yún)?shù)的擴(kuò)展。對于這個(gè)參入?yún)?shù)我們就叫它 options

我們接著往下想,既然這個(gè) options 是能擴(kuò)展的,那么原 Vue 類下,肯定保存著一個(gè)默認(rèn) options ,而創(chuàng)建 Vue 實(shí)例時(shí),會(huì)把傳入的 options 和默認(rèn)的 options 進(jìn)行合并。

所以 extend 方法,是對默認(rèn) options 進(jìn)行擴(kuò)展,從而實(shí)現(xiàn)擴(kuò)展。

mergeOptions

ok 有了思路,我們來實(shí)現(xiàn)它:

首先是默認(rèn)的 options ,同時(shí)我們假設(shè)一個(gè)方法(mergeOptions)用來合并 options

let uid = 0

export class Vue extends Event {
    ···

    _init(options) {
        let vm = this
        // 為了方便引用合并的 options 我們把它掛載在 Vue 實(shí)例下
        vm.$options = mergeOptions(
            this.constructor.options,
            options,
            vm
        )
        ···
    }
}
// 默認(rèn)的 options
Vue.options = {
    // 組件列表
    components: {},
    // 基類
    _base: Vue
}

接著我們來實(shí)現(xiàn) mergeOptions

import R from "ramda"

export function mergeOptions(parent, child) {
    // data/methods/watch/computed
    let options = {}

    // 合并 data 同名覆蓋
    options.data = mergeData(parent.data, child.data)

    // 合并 methods 同名覆蓋
    options.methods = R.merge(parent.methods, child.methods)

    // 合并 watcher 同名合并成一個(gè)數(shù)組
    options.watch = mergeWatch(parent.watch, child.watch)

    // 合并 computed 同名覆蓋
    options.computed = R.merge(parent.computed, child.computed)

    return options
}

function mergeData(parentValue, childValue) {
    if (!parentValue) {
        return childValue
    }
    if (!childValue) {
        return parentValue
    }
    return function mergeFnc() {
        return R.merge(parentValue.call(this), childValue.call(this))
    }
}

// 由于 watcher 的特殊性,我們不覆蓋同名屬性,而是都保存在一個(gè)數(shù)組中
function mergeWatch(parentVal, childVal) {
    if (!childVal) return R.clone(parentVal || {})
    let ret = R.merge({}, parentVal)
    for (let key in childVal) {
        let parent = ret[key]
        let child = childVal[key]
        if (parent && !Array.isArray(parent)) {
            parent = [parent]
        }
        ret[key] = parent
            ? parent.concat(child)
            : Array.isArray(child) ? child : [child]
    }
    return ret
}

目前我們僅僅實(shí)現(xiàn)了 data/methods/watch/computed4 個(gè) options 中的內(nèi)容,所以我們先合并這 4 項(xiàng),由于 data/methods/computed3 項(xiàng)是具有唯一性(比如 this.a 應(yīng)該是一個(gè)確定的值),所以采用同名屬性覆蓋的方式,而 watch 是當(dāng)發(fā)生變化時(shí)候執(zhí)行方法,所以所有注冊過的方法都應(yīng)該執(zhí)行,因而采用同名屬性的內(nèi)容合并成一個(gè)數(shù)組。

這里我用了 ramda 這個(gè)庫提供的合并方法,用來合并兩個(gè)對象,并不會(huì)修改原對象的內(nèi)容。

extend

ok 合并 options 的方法寫好了,我們接著來實(shí)現(xiàn) extend 同過上面的分析,extend 函數(shù)僅僅是對默認(rèn) options 的擴(kuò)展

Vue.extend = function (extendOptions) {
    const Super = this

    class Sub extends Super {
        constructor(options) {
            super(options)
        }
    }

    Sub.options = mergeOptions(
        Super.options,
        extendOptions
    )

    Sub.super = Super
    Sub.extend = Super.extend

    return Sub
}

同樣的我們使用 mergeOptions 來合并一下 options 即可,同時(shí)將 super 指向父類、獲取 extend 方法。

測試
import {Vue} from "./Vue.mjs"

let subVue = Vue.extend({
    data() {
        return {
            dataTest: 1
        }
    },
    methods: {
        methodTest() {
            console.log("methodTest")
        }
    },
    watch: {
        "dataTest"(newValue, oldValue) {
            console.log("watchTest newValue = " + newValue)
        }
    },
    computed: {
        "computedTest": {
            get() {
                return this.dataTest + 1
            }
        }
    }
})

let test = new subVue({
    data() {
        return {
            subData: 11
        }
    },
    methods: {
        subMethod() {
            console.log("subMethodTest")
        }
    },
    watch: {
        "subData"(newValue, oldValue) {
            console.log("subWatch newValue = " + newValue)
        }
    },
    computed: {
        "subComputed": {
            get() {
                return this.subData + 1
            }
        }
    }
})

console.log(test.dataTest)
// 1
console.log(test.subData)
// 11

console.log(test.computedTest)
// 2
console.log(test.subComputed)
// 12

test.methodTest()
// methodTest
test.subMethod()
// subMethodTest

test.dataTest = 2
// watchTest newValue = 2
test.subData = 12
// subWatch newValue = 12

console.log(test.constructor === subVue)
// true
console.log(subVue.super === Vue)
// true

ok 符合我們的預(yù)期,extend 方法也就實(shí)現(xiàn)了,下一步,實(shí)現(xiàn)父子組件。

系列文章地址

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)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/94796.html

相關(guān)文章

  • VUE - MVVM - part12 - props

    摘要:看這篇之前,如果沒有看過之前的文章,移步拉到文章末尾查看之前的文章。而該組件實(shí)例的父實(shí)例卻并不固定,所以我們將這些在使用時(shí)才能確定的參數(shù)在組件實(shí)例化的時(shí)候傳入。系列文章地址優(yōu)化優(yōu)化總結(jié) 看這篇之前,如果沒有看過之前的文章,移步拉到文章末尾查看之前的文章。 前言 在上一步,我們實(shí)現(xiàn) extend 方法,用于擴(kuò)展 Vue 類,而我們知道子組件需要通過 extend 方法來實(shí)現(xiàn),我們從測試?yán)?..

    bluesky 評論0 收藏0
  • VUE - MVVM - part13 - inject & 總結(jié)

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

    niuxiaowei111 評論0 收藏0
  • VUE - MVVM - part7 - Event

    摘要:事件是什么在標(biāo)準(zhǔn)瀏覽器中,我們經(jīng)常使用來為一個(gè)添加一個(gè)事件等。仔細(xì)看這些情況,歸結(jié)到代碼中,無非就是一個(gè)行為或情況的名稱,和一些列的動(dòng)作,而在中動(dòng)作就是,一系列的動(dòng)作就是一個(gè)函數(shù)的集合。 看這篇之前,如果沒有看過之前的文章,可拉到文章末尾查看之前的文章。 事件是什么? 在標(biāo)準(zhǔn)瀏覽器中,我們經(jīng)常使用:addEventListener 來為一個(gè) DOM 添加一個(gè)事件(click、mouse...

    xialong 評論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)記的過程。 看這篇之前,如果沒有看過之前的文章,可拉到文章末尾查看之前的文章。 回顧 首先我們思考一下截止當(dāng)前,我們都做了什么 通過 defineReactive 這個(gè)函數(shù),實(shí)現(xiàn)了對于數(shù)據(jù)取值和設(shè)置的監(jiān)聽 通過 Dep 類,實(shí)現(xiàn)了依賴的管理 通過 Wa...

    CoffeX 評論0 收藏0
  • VUE - MVVM - part1 - defineProperty

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

    liukai90 評論0 收藏0

發(fā)表評論

0條評論

最新活動(dòng)
閱讀需要支付1元查看
<