摘要:所以方法,是對默認(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ò)展。
mergeOptionsok 有了思路,我們來實(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/computed 這 4 個(gè) options 中的內(nèi)容,所以我們先合并這 4 項(xiàng),由于 data/methods/computed 這 3 項(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)容。
extendok 合并 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
摘要:看這篇之前,如果沒有看過之前的文章,移步拉到文章末尾查看之前的文章。而該組件實(shí)例的父實(shí)例卻并不固定,所以我們將這些在使用時(shí)才能確定的參數(shù)在組件實(shí)例化的時(shí)候傳入。系列文章地址優(yōu)化優(yōu)化總結(jié) 看這篇之前,如果沒有看過之前的文章,移步拉到文章末尾查看之前的文章。 前言 在上一步,我們實(shí)現(xiàn) extend 方法,用于擴(kuò)展 Vue 類,而我們知道子組件需要通過 extend 方法來實(shí)現(xiàn),我們從測試?yán)?..
摘要:通過裝作這些變化,我們實(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...
摘要:事件是什么在標(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...
摘要:關(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...
摘要:在中關(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,...
閱讀 594·2021-11-22 14:45
閱讀 3086·2021-10-15 09:41
閱讀 1585·2021-10-11 10:58
閱讀 2807·2021-09-04 16:45
閱讀 2622·2021-09-03 10:45
閱讀 3252·2019-08-30 15:53
閱讀 1234·2019-08-29 12:28
閱讀 2146·2019-08-29 12:14