直接從主流的說起!
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.設計輸入 設計輸入有多種方式,主要包括文字輸入方式 圖形輸入方式和波形輸入方式,還支援文字輸入和圖形輸入兩者混合的方式。文字輸入方式是採用硬體描述...