#### mvvm

viewModel是整個vue實例
vue在編譯階段會識別出所有綁定在元素(通過 el 屬性傳入)上的指令。
link 過程中,建立這些指令與對應數據(通過 data 屬性傳入初始值)的watcher。watcher會在dep上添加訂閱者,observe用來監聽所有屬性的變化,告知dep,由dep分發給每個watcher,再由watcher更新view。
雙向綁定:數據劫持加收發訂閱模式
數據劫持:defineProperty
```
//數據劫持
function defineReactive (obj, key, val) {
var dep = new Dep();
Object.defineProperty(obj, key, {
get: function() {
//添加訂閱者watcher到主題對象Dep
if(需要添加訂閱者) {
// JS的瀏覽器單線程特性,保證這個全局變量在同一時間內,只會有同一個監聽器使用
dep.addSub(watcher);
}
return val;
},
set: function (newVal) {
if(newVal === val) return;
val = newVal;
console.log(val);
// 作為發布者發出通知
dep.notify();
}
})
}
//observe
function observe(this.data) {
Object.keys(obj).forEach(function(key) {
defineReactive(this.data, key, this.data[key]);
})
}
//dep負責發送通知
function Dep() {
this.subs = [];
}
Dep.prototype = {
addSub: function(sub) {
this.subs.push(sub);
},
notify: function() {
this.subs.forEach(function(sub) {
sub.update();
})
}
}
```
#### vue-router鉤子函數
```
全局
router.beforeEach((to, from, next) //跳轉前
router.afterEach //跳轉后
組件內
beforeRouteEnter
beforeRouteUpdate (2.2 新增)
beforeRouteLeave
路由配置里
beforeEnter
```
指令:v-if、v-show、v-for、v-bind、v-on、v-model
自定義指令:
```
Vue.directive(name, {
//binding包括name\value\expression\arg等
bind(el, binding, vnode) {指令第一次綁定到元素時}
inserted(e, b, v) {被綁定元素插入父節點時調用}
update(e, b, v) {所在組件的 VNode 更新時調用}
等等
})
export default {
name:'',
directives: {
name: {
bind() {}
xxx
}
}
}
```
組件通信
```
父子
props傳遞
子組件$emit(name, args),父級@name($event)
父級通過ref訪問子組件實例
同級之間使用bus或者vuex
var bus = new Vue();
component1 bus.$emit('id-selected', 1)
component2 bus.$on('id-selected', id => {})
```