看完這篇關於MVVM的文章,面試通過率提公升了80

2021-09-24 07:16:53 字數 4549 閱讀 1166

直接從主流的說起!

vue的特點不必多說(簡單易用)。修改資料方便不需要記憶api方法,這都歸功於object.defineproperty,它可以在資料的設定和獲取時增加我們自己的功能!(像牆一樣)

mvvm模式就要將這些板塊進行整合,實現模板和資料的繫結!

看看我畫圖的功底,有個印象就好!

看段大眾**,接下來我們就基於這段**搞一下mvvm的實現

type="text"

v-model="message.a">

我很帥div>

} }div>

src="watcher.js">

script>

src="observer.js">

script>

src="compile.js">

script>

src="mvvm.js">

script>

// 我們的資料一般都掛載在vm上

let vm = new mvvm(,

b:'mvvm'}})

script>

複製**

這裡我們用了自己的mvvm庫,這個庫是用來整合所有板塊的!

直接用es6來打造我們的mvvm

class

mvvm

}}複製**

mvvm中呼叫了compile類來編譯我們的頁面,開始來實現模板編譯

先來個基礎的架子

class

compile

}this.compile(fragment);

// 3.把編譯號的fragment在塞回到頁面裡去}}

/* 專門寫一些輔助的方法 */

iselementnode(node)

/* 核心的方法 */

compileelement(node) {}

compiletext(node) {}

compile(fragment) {}

node2fragment(el) {}

}複製**

接下來乙個個的方法來搞

node2fragment(el) 

return fragment; // 記憶體中的節點

}複製**

compile(fragment)  else 

});}複製**

我們在弄出兩個方法compileelement,compiletext來專門處理對應的邏輯

/*輔助的方法*/

// 是不是指令

isdirective(name)

----------------------------

compileelement(node)

})}compiletext(node) ]+)\}\}/g; // } } }

if (reg.test(expr))

}複製**

我們要實現乙個專門用來配合complie類的工具物件

先只處理文字和輸入框的情況

compileutil = ,

model(node, vm, expr) ,

updater: ,

// 輸入框更新

modelupdater(node, value)

}}複製**

實現text方法

text(node, vm, expr) } }'

// 呼叫gettextval方法去取到對應的結果

let value = this.gettextval(vm, expr);

updatefn && updatefn(node, value)

},gettextval(vm, expr) ]+)\}\}/g, (...arguments) => )

},getval(vm, expr) } [message,a] 實現依次取值

// vm.$data.message => vm.$data.message.a

return expr.reduce((prev, next) => , vm.$data);

}複製**

實現model方法

model(node, vm, expr) 

複製**

看下編譯後的效果^_^

我們一直說object.defineproperty有劫持功能咱就看看這個是怎樣劫持的

預設情況下定義屬性給屬性設定的操作是這樣的

let school = 

school.name = 'jw'; // 當我給屬性設定時希望做一些操作

console.log(school.name); // 當我獲取屬性時也希望對應有寫操作

複製**

這時候object.defineproperty登場

let school = 

let val;

object.defineproperty(school, 'name', ,

set(newval)

});school.name = 'jw';

console.log(school.name);

複製**

這樣我們可以在設定值和獲取值時做我們想要做的操作了

接下來我們就來寫下乙個類observer

// 在mvvm加上observe的邏輯

if(this.$el)

--------------------------------------

class

observer

observe(data)

// 要將資料 一一劫持 先獲取取到data的key和value

object.keys(data).foreach(key=>);

}// 定義響應式

definereactive(obj,key,value),

set(newvalue)

}});

}}複製**

來再看看效果^_^

觀察者的目的就是給需要變化的那個元素增加乙個觀察者,用新值和老值進行比對,如果資料變化就執行對應的方法

class

watcher

// 老套路獲取值的方法,這裡先不進行封裝

getval(vm, expr) , vm.$data);

}get()

// 對外暴露的方法,如果值改變就可以呼叫這個方法來更新

update()

}}複製**

在**使用watcher?答案肯定是compile呀,給需要重新編譯的dom增加watcher

text(node, vm, expr) ]+)\}\}/g, (...arguments) => );

+ })

updatefn && updatefn(node, value)

},model(node, vm, expr) );

updatefn && updatefn(node, this.getval(vm, expr));

}複製**

如何將檢視和資料關聯起來呢?就是將每個資料和對應的watcher關聯起來。當資料變化時讓對應的watcher執行update方法即可!再想想在哪做操作呢?就是我們的set和get!

dep實現

class

dep addsub(watcher)

notify()

}複製**

關聯dep和watcher

watcher中有個重要的邏輯就是this.get();每個watcher被例項化時都會獲取資料從而會呼叫當前屬性的get方法

// watcher中的get方法

get()

// 更新observer中的definereactive

definereactive(obj,key,value),

set(newvalue)

}});

}複製**

到此資料和檢視就關聯起來了!^_^

setval(vm,expr,value)

return prev[next];

},vm.$data);

},model(node, vm, expr) );

+ node.addeventlistener('input',(e)=>);

updatefn && updatefn(node, this.getval(vm, expr));

}複製**

class

mvvm

}proxydata(data),

set(newvalue)

})})

}}複製**

看看最終效果!

看完這篇文章,Class的相關知識你就都懂了。

一.類和物件 1.通過分析 物件 的屬性和行為設計出乙個類 物件導向 2.類就是資料型別 簡單型別 只能表示乙個屬性 變數 c c 內建資料型別。陣列型別 可以表示多個屬性 變數 型別必須相同。結構型別 可以表示多個屬性 變數 但缺少行為 函式 類型別 既能表示屬性,也能表示行為,一種復合的資料型別...

看完這篇文章你就能完全明白web專案中的路徑問題了

今天做網上購物系統 web專案 中個人資訊模組的頭像上傳,一直出現路徑問題,仔細看一下,是自己完全沒有弄明白路徑。經過一番學習,也算是有所收穫,下面我們就來談一下絕對路徑和相對路徑的區別問題。我們都知道,在我們平時使用計算機時要找到需要的檔案就必須知道檔案的位置,而表示檔案的位置的方式就是路徑,例如...

EDA設計流程是怎樣的,看完這篇文章就知道了

eda技術進行電路設計的大部分工作是在eda軟體平台上進行的。eda的設計流程主要包括設計輸入 設計處理 設計驗證 器件程式設計和硬體測試等5個步驟。1.設計輸入 設計輸入有多種方式,主要包括文字輸入方式 圖形輸入方式和波形輸入方式,還支援文字輸入和圖形輸入兩者混合的方式。文字輸入方式是採用硬體描述...